How can I use an array as map value?

72,268

Solution 1

You can't copy arrays by value like that.

Here are several solutions, but I recommend #4 for your needs:

  1. Use an std::vector instead of an array.

  2. Use a map of pointers to arrays of 3 elements:

    int red[3]   = {1,0,0};
    int green[3] = {0,1,0};
    int blue[3]  = {0,0,1};
    std::map<int,int(*)[3]> colours;
    colours.insert(std::pair<int,int(*)[3]>(GLUT_LEFT_BUTTON,&red));
    colours.insert(std::pair<int,int(*)[3]>(GLUT_MIDDLE_BUTTON,&blue));
    colours.insert(std::pair<int,int(*)[3]>(GLUT_RIGHT_BUTTON,&green));
    // Watch out for scope here, you may need to create the arrays on the heap.
    
  3. Use boost tuples instead of arrays of 3 elements.

  4. Instead of using an array make a new struct that takes 3 elements. Make the map<int, newstructtype>. Or wrap your array in a struct as follows:

    struct Triple
    {
        int color[3];
    };
    
    // Later in code
    Triple red = {1, 0, 0}, green = {0, 1, 0}, blue = {0, 0, 1};
    std::map<int,Triple> colours;
    colours.insert(std::pair<int,Triple>(GLUT_LEFT_BUTTON,red));
    colours.insert(std::pair<int,Triple>(GLUT_MIDDLE_BUTTON,blue));
    colours.insert(std::pair<int,Triple>(GLUT_RIGHT_BUTTON,green));
    

Solution 2

Use std::tr1::array.

typedef std::tr1::array<int, 3> Triple;
Triple red   = {1, 0, 0};
Triple green = {0, 1, 0};
Triple blue  = {0, 0, 1};
std::map<int, Triple> colours;
colours.insert(std::make_pair(GLUT_LEFT_BUTTON,   red));
colours.insert(std::make_pair(GLUT_MIDDLE_BUTTON, blue));
colours.insert(std::make_pair(GLUT_RIGHT_BUTTON,  green));

Or std::array in C++11 and above

using  Triple = std::array<int, 3>; 
Triple red   = {1, 0, 0};
Triple green = {0, 1, 0};
Triple blue  = {0, 0, 1};
std::map<int, Triple> colours;
colours.insert(std::make_pair(GLUT_LEFT_BUTTON,   red));
colours.insert(std::make_pair(GLUT_MIDDLE_BUTTON, blue));
colours.insert(std::make_pair(GLUT_RIGHT_BUTTON,  green));

Solution 3

Arrays are not first class constructs in C++. They are not Copy Constructible nor Assignable which are requirements for values of std::map. You can use boost::array or std::vector.

Solution 4

Don't map to an int[], instead, map to an int* like this:

#include <iostream>
#include <map>
using namespace std;
int main(){
    std::map<int,int*> colors;
    int red[] = {3,7,9};
    colors[52] = red;
    cout << colors[52][1];  //prints 7
    colors[52][1] = 11;
    cout << colors[52][1];  //prints 11
    return 0;
}

Solution 5

Another alternative is to put the arrays in a wrapping struct:

    struct Wrapper { int value[3]; };

    // ...
    Wrapper red = {{1,0,0}};    
    std::map<int,Wrapper> colours;    
    colours.insert(std::pair<int,Wrapper>(1, red));
Share:
72,268
Tom
Author by

Tom

Updated on February 04, 2021

Comments

  • Tom
    Tom over 3 years

    I'm trying to create a map, where the key is an int, and the value is an array as follows:

    int red[3]   = {1,0,0};
    int green[3] = {0,1,0};
    int blue[3]  = {0,0,1};
    
    std::map<int, int[3]> colours;
    
    colours.insert(std::pair<int,int[3]>(GLUT_LEFT_BUTTON,red));    // THIS IS LINE 24!
    colours.insert(std::pair<int,int[3]>(GLUT_MIDDLE_BUTTON,blue));
    colours.insert(std::pair<int,int[3]>(GLUT_RIGHT_BUTTON,green));
    

    However, when I try to compile this code, I get the following error:

    g++ (Ubuntu 4.4.1-4ubuntu8) 4.4.1
    
    In file included from /usr/include/c++/4.4/bits/stl_algobase.h:66,
                     from /usr/include/c++/4.4/bits/stl_tree.h:62,
                     from /usr/include/c++/4.4/map:60,
                     from ../src/utils.cpp:9:
    /usr/include/c++/4.4/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = int, _T2 = int [3]]’:
    ../src/utils.cpp:24:   instantiated from here
    /usr/include/c++/4.4/bits/stl_pair.h:84: error: array used as initializer
    /usr/include/c++/4.4/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = int, _U2 = int [3], _T1 = const int, _T2 = int [3]]’:
    ../src/utils.cpp:24:   instantiated from here
    /usr/include/c++/4.4/bits/stl_pair.h:101: error: array used as initializer
    In file included from /usr/include/c++/4.4/map:61,
                     from ../src/utils.cpp:9:
    /usr/include/c++/4.4/bits/stl_map.h: In member function ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int [3], _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int [3]> >]’:
    ../src/utils.cpp:30:   instantiated from here
    /usr/include/c++/4.4/bits/stl_map.h:450: error: conversion from ‘int’ to non-scalar type ‘int [3]’ requested
    make: *** [src/utils.o] Error 1
    

    I really can't see where the error is. Or even if there's an error.

  • Tom
    Tom about 14 years
    about 3) This is a small project, cant add boost, but will take a look, thanks.
  • Brian R. Bondy
    Brian R. Bondy about 14 years
    @Tom: Added a 4) which may be your easiest solution.
  • Eddy Pronk
    Eddy Pronk about 14 years
    use std::make_pair. See below.
  • underscore_d
    underscore_d over 8 years
    also known now as simply std::array ;-) making this really the only still-relevant answer left here. weird how it has so few votes...
  • Amy Cohen
    Amy Cohen over 2 years
    When inserted in the 2nd way, how can they be accessed? For example, if I need to access the first element of GLUT_LEFT_BUTTON I tried doing `colours[0][0] but it's not printing the value I want.