Как я могу использовать массив в качестве значения карты?

Я пытаюсь создать карту, где ключом является int, а значением является массив следующим образом:

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));

Однако, когда я пытаюсь скомпилировать этот код, я получаю следующую ошибку:

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

Я действительно не вижу, где ошибка. Или даже если есть ошибка.


person Tom    schedule 06.04.2010    source источник


Ответы (9)


Вы не можете копировать массивы по значению.

Вот несколько решений, но я рекомендую № 4 для ваших нужд:

  1. Используйте std::vector вместо массива.

  2. Используйте карту указателей на массивы из 3 элементов:

    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. Используйте повышающие кортежи вместо массивов из 3 элементы.

  4. Вместо использования массива создайте новую структуру, которая принимает 3 элемента. Сделайте map<int, newstructtype>. Или оберните массив в структуру следующим образом:

    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));
    
person Brian R. Bondy    schedule 06.04.2010
comment
о 3) Это небольшой проект, не могу добавить буст, но посмотрю, спасибо. - person Tom; 06.04.2010
comment
@Tom: добавлено 4), которое может быть вашим самым простым решением. - person Brian R. Bondy; 06.04.2010
comment
используйте std::make_pair. Смотри ниже. - person Eddy Pronk; 06.04.2010

Массивы не являются конструкциями первого класса в C++. Это не Copy Constructible и не Assignable, которые являются требованиями для значений std::map. Вы можете использовать boost::array или std::vector.

person AraK    schedule 06.04.2010

Используйте 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));

Или std::array в C++11 и выше.

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));
person missingfaktor    schedule 06.04.2010
comment
также известный теперь как просто std::array ;-), что делает его действительно единственным все еще актуальным ответом, оставшимся здесь. странно, что так мало голосов... - person underscore_d; 14.01.2016

Не сопоставляйте с int[], вместо этого сопоставляйте с int* следующим образом:

#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;
}
person Eric Leschinski    schedule 31.05.2012

Другая альтернатива — поместить массивы в структуру-обертку:

    struct Wrapper { int value[3]; };

    // ...
    Wrapper red = {{1,0,0}};    
    std::map<int,Wrapper> colours;    
    colours.insert(std::pair<int,Wrapper>(1, red));
person Georg Fritzsche    schedule 06.04.2010

Массивы не могут быть сохраненными данными в стандартном контейнере (std::pair)

person aJ.    schedule 06.04.2010

Подход с использованием структуры в 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));
person Merin    schedule 03.10.2017

Я хотел бы расширить третий пункт ответа Брайана Р. Бонди: Поскольку C++11 шаблон класса std::tuple доступен. Таким образом, вам больше не нужен Boost для работы с кортежами.

Кортеж — это набор фиксированного размера, который может содержать несколько элементов. По сравнению, например, с std::vector у него есть то преимущество, что он может хранить разнородные типы. Например, если вы хотите сохранить имя цвета вместе с его значениями RGB, вы можете добавить в кортеж четвертый элемент типа std::string для имени цвета. Но для вашего конкретного случая использования код может быть написан следующим образом:

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;
}

Выход:

0 => { 1, 0, 0 }
1 => { 0, 0, 1 }
2 => { 0, 1, 0 }

Примечание. Работа с кортежами стала проще с C++17, особенно если вы хотите получить доступ к нескольким элементам одновременно. Например, если вы используете структурированное связывание, вы можете распечатать кортеж следующим образом :

for (auto const &[k, v] : colours) {
    auto [r, g, b] = v;
    std::cout << k << " => { " << r << ", " << g << ", " << b << " }" << std::endl;
}

Код на Coliru

person honk    schedule 04.08.2020

если вы хотите передать массив в функцию Map в C++. этот код может вам помочь. это берет элемент массива в качестве входных данных и вставляет его в функцию карты с количеством вхождений. для массива {1, 2, 1, 2, 3, 4, 1} Map будет ›› элемент: число вхождений 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
}

Надеюсь, это поможет вам ~ Mayank Srivastava

person Mayank    schedule 03.02.2021