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开发者_StackOverflow<_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.
You can't copy arrays by value like that.
Here are several solutions, but I recommend #4 for your needs:
Use an
std::vector
instead of an array.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.
Use boost tuples instead of arrays of 3 elements.
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));
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));
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
.
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;
}
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));
Arrays cannot be the stored data in a standard container( std::pair
)
I'd like to expand on the third item of Brian R. Bondy's answer: Since C++11 the class template std::tuple
is available. So you no longer need Boost to work with tuples.
A tuple is a collection of fixed size that can hold multiple elements. Compared to e.g. std::vector
it has the advantage that it can store heterogeneous types. For example, if you want to store the name of the color together with its RGB values, you can add a fourth element of type std::string
for the color name to the tuple. But for your specific use case, the code could be written as follows:
int main() {
using col_t = std::tuple<int, int, int>;
col_t red = { 1, 0, 0 };
col_t green = { 0, 1, 0 };
col_t blue = { 0, 0, 1 };
std::map<int, col_t> colours;
colours.emplace(GLUT_LEFT_BUTTON, red);
colours.emplace(GLUT_MIDDLE_BUTTON, blue);
colours.emplace(GLUT_RIGHT_BUTTON, green);
for (auto const &kv : colours)
std::cout << kv.first << " => { " << std::get<0>(kv.second) << ", "
<< std::get<1>(kv.second) << ", "
<< std::get<2>(kv.second) << " }" << std::endl;
return 0;
}
Output:
0 => { 1, 0, 0 }
1 => { 0, 0, 1 }
2 => { 0, 1, 0 }
Note: Working with tuples became easier with C++17, espcially if you want to access multiple elements simultaneously. For example, if you use structured binding, you can print the tuple as follows:
for (auto const &[k, v] : colours) {
auto [r, g, b] = v;
std::cout << k << " => { " << r << ", " << g << ", " << b << " }" << std::endl;
}
Code on Coliru
Approach using structure in C++
int MAX_DATA_PER_INSTR = 8;
//struct to hold the values. remember to write the constructor
struct InstrChar
{
InstrChar(int in[MAX_DATA_PER_INSTR]) {
//c alternative is memcopy
std::copy(in, in+MAX_DATA_PER_INSTR, data);
}
int data[MAX_DATA_PER_INSTR];
};
// create a key value pair
std::map <int, InstrChar> address_instructions;
std::map <int, InstrChar>::iterator it;
// sample array, 8 elements
int xp[MAX_DATA_PER_INSTR ] = {31,4,3,4,4,3,1,2};
address_instructions.insert(std::pair<int, InstrChar>(PC, xp));
it = address_instructions.find(PC);
InstrChar buf1 = it->second;
//integer pointer to the array, can be dereferenced as *p, *(p+1), .... //*(p+7)
int *p = buf1.data;
//in case you need to print these values out. They can also be referred to as buf1.data[0], buf1.data[1], buf1.data[2]
printf("%d\n", (*p));
printf("%d\n", *(p+1));
printf("%d\n", *(p+2));
printf("%d\n", *(p+3));
printf("%d\n", *(p+4));
printf("%d\n", *(p+5));
printf("%d\n", *(p+6));
printf("%d\n", *(p+7));
if you want to pass an array into the Map function in C++. this code might help you. this take the array element as input and insert it into map function with count of occurrence. for an array {1, 2, 1, 2, 3, 4, 1} Map will be >> element : number of occurrence 1 3, 2 2. 3 1, 4 1
#include<bits/stdc++.h>
using namespace std;
int main()
{
int size;
cin>>size;
int arr[size];
for(int i = 0 ; i < size ; i++)
{
cin >> arr[i];
}
map <int,int> mp;
for(int i = 0 ; i < size ; i++)
mp[arr[i]]++;
for (auto i = mp.begin(); i != mp.end(); i++)
cout << i->first << " " << i->second << endl;
return 0;
//@rsMayank
}
Hope it may help you ~ Mayank Srivastava
精彩评论