Как я могу использовать структуру в качестве ключа в std :: map?

У меня есть следующий код, но в последней строке появляется сообщение об ошибке:

struct coord { 
    int x, y; 

    bool operator=(const coord &o) {
        return x == o.x && y == o.y;
    }

    bool operator<(const coord &o) {
        return x < o.x || (x == o.x && y < o.y);
    }
};

map<coord, int> m;
pair<coord, int> p((coord{0,0}),123);
m.insert(p); // ERROR here

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


Я попытался изменить код на такой:

struct coord { 
    int x, y; 

    bool const operator==(const coord &o) {
        return x == o.x && y == o.y;
    }

    bool const operator<(const coord &o) {
        return x < o.x || (x == o.x && y < o.y);
    }
};

Но я все еще получаю следующую ошибку:

C:\Users\tomc\Desktop\g>mingw32-make g++ test.cpp -std=c++0x In file included from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/string:5 0:0,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/loc ale_classes.h:42,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/ios
_base.h:43,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/ios:43,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/ostream: 40,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/iostream :40,
                 from test.cpp:1: c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_function.h: In member  function 'bool std::less<_Tp>::operator()(const _Tp&, const
_Tp&) const [with _ Tp = coord]': c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_tree.h:1184:4: inst antiated from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key,  _Val, _KeyOfValue, _Compare,
_Alloc>::_M_insert_unique(const _Val&) [with _Key
= coord, _Val = std::pair<const coord, int>, _KeyOfValue = std::_Select1st<std:: pair<const coord, int> >, _Compare = std::less<coord>, _Alloc = std::allocator<std::pair<const coord, int>>]' c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_map.h:501:41: insta ntiated from 'std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>,  std::_Select1st<std::pair<const _Key,
_Tp> >, _Compare, typename _Alloc::rebind <std::map<_Key, _Tp,
_Compare, _Alloc>::value_type>::other>::iterator, bool> std ::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::map<_Key, _Tp,
_Compare, _ Alloc>::value_type&) [with _Key = coord, _Tp = int,
_Compare = std::less<coord>,  _Alloc = std::allocator<std::pair<const coord, int> >, typename std::_Rb_tree<_ Key, std::pair<const _Key,
_Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _ Compare, typename _Alloc::rebind<std::map<_Key, _Tp, _Compare,
_Alloc>::value_ty pe>::other>::iterator = std::_Rb_tree_iterator<std::pair<const coord, int> >, st d::map<_Key,
_Tp, _Compare, _Alloc>::value_type = std::pair<const coord, int>]' test.cpp:56:12:   instantiated from here c:\mingw\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_function.h:230:22: er ror: passing 'const coord' as 'this' argument of 'const bool coord::operator<(co nst coord&)' discards qualifiers mingw32-make: *** [game] Error 1

person Community    schedule 26.08.2011    source источник
comment
Какая у вас ошибка?   -  person R. Martinho Fernandes    schedule 26.08.2011
comment
Это не ваша проблема, но ваш оператор = должен быть оператором ==   -  person jcoder    schedule 26.08.2011
comment
Это должно быть bool operator<(const coord &o) const   -  person Andreas Brinck    schedule 26.08.2011
comment
const в неправильном месте, после списка аргументов не раньше. То, что вы сделали, делает возвращаемый тип const, то есть const bool, но вы хотите сделать метод const.   -  person john    schedule 26.08.2011
comment
Прочтите FAQ по перегрузке оператора. Фактически, это должно быть закрыто как дурак, так как там все объясняется.   -  person sbi    schedule 26.08.2011


Ответы (4)


Попробуйте сделать operator < const:

bool operator<(const coord &o)  const {

(Ваш = operator, вероятно, тоже должен быть == operator и const)

person Andreas Brinck    schedule 26.08.2011
comment
Вы можете объяснить, почему добавление const устраняет ошибку? , Благодарность - person ; 26.08.2011
comment
На самом деле, я бы сделал оператор бесплатной функцией, а не функцией-членом. - person sbi; 26.08.2011
comment
@ x4: ключ карты имеет тип const Key, поэтому вы можете выполнять только операции со структурой, помеченной как const. Попытка использовать методы, которые не помечены как const в этом случае, приводит к указанной выше ошибке (с использованием квалификаторов XXX отбрасывает) - person Dave S; 26.08.2011
comment
отличный ответ. Сэкономил много времени на отладку. - person Achal; 13.04.2019

Безусловно, самым простым является определение глобального оператора «меньше чем» для вашей структуры вместо функции-члена.

std :: map использует - по умолчанию - функтор 'lessthan', который, в свою очередь, использует глобальный «оператор‹ », определенный для ключевого типа карты.

bool operator<(const coord& l, const coord& r) {
     return (l.x<r.x || (l.x==r.x && l.y<r.y));
}
person haavee    schedule 06.04.2012

Как упоминалось в ответе Andrii, вместо этого вы можете предоставить пользовательский объект сравнения для map определения operator< для вашей структуры. Поскольку C ++ 11, вы также можете использовать лямбда-выражение вместо определения объекта сравнения. Более того, вам не нужно определять operator== для вашей структуры, чтобы map работала. В результате вы можете сделать свою структуру такой короткой, как это:

struct coord {
    int x, y;
};

А остальную часть вашего кода можно было бы записать следующим образом:

auto comp = [](const coord& c1, const coord& c2){
    return c1.x < c2.x || (c1.x == c2.x && c1.y < c2.y);
};
std::map<coord, int, decltype(comp)> m(comp);

Код на Ideone

person honk    schedule 28.02.2019
comment
Это очень полезно, когда у вас нет доступа к самому коду структуры и вам нужно добавить его на карту. Спасибо! - person Overt_Agent; 07.07.2020

Другое решение, которое можно использовать для сторонних типов данных, - передать Comparison object в качестве третьего параметра шаблона. пример

person Andrii    schedule 05.12.2011