Проблема с std :: map и std :: pair - PullRequest
       40

Проблема с std :: map и std :: pair

9 голосов
/ 15 апреля 2010

У меня есть небольшая программа, которую я хочу выполнить, чтобы проверить что-то

#include <map>
#include <iostream>
using namespace std;

struct _pos{
        float xi;
        float xf;

        bool operator<(_pos& other){

                return this->xi < other.xi;
        }
};

struct _val{

        float f;
};

int main()
{
        map<_pos,_val> m;

        struct  _pos k1 = {0,10};
        struct  _pos k2 = {10,15};

        struct  _val v1 = {5.5};
        struct  _val v2 = {12.3};                                                                   

        m.insert(std::pair<_pos,_val>(k1,v1));
        m.insert(std::pair<_pos,_val>(k2,v2));

        return 0;
}

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

$ g++ m2.cpp -o mtest
In file included from /usr/include/c++/4.4/bits/stl_tree.h:64,
                 from /usr/include/c++/4.4/map:60,
                 from m2.cpp:1:
/usr/include/c++/4.4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = _pos]’:
/usr/include/c++/4.4/bits/stl_tree.h:1170:   instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = _pos, _Val = std::pair<const _pos, _val>, _KeyOfValue = std::_Select1st<std::pair<const _pos, _val> >, _Compare = std::less<_pos>, _Alloc = std::allocator<std::pair<const _pos, _val> >]’
/usr/include/c++/4.4/bits/stl_map.h:500:   instantiated 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::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = _pos, _Tp = _val, _Compare = std::less<_pos>, _Alloc = std::allocator<std::pair<const _pos, _val> >]’
m2.cpp:30:   instantiated from here
/usr/include/c++/4.4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’
m2.cpp:9: note: candidates are: bool _pos::operator<(_pos&)
$ 

Я думал, что объявление оператора <на клавише решит проблему, но она все еще там. </p>

Что может быть не так?

Заранее спасибо.

Ответы [ 3 ]

25 голосов
/ 15 апреля 2010

Проблема заключается в следующем:

bool operator<(_pos& other)

Должно быть так:

bool operator<(const _pos& other) const {
//             ^^^^               ^^^^^

Без первого const правая часть сравнения (b в a < b) не может быть const, поскольку без const функция может изменить свой аргумент.

Без второго const левая часть сравнения (a в a < b) не может быть const, поскольку без const функция может изменить this.

Внутренне, ключи карты всегда const.


Следует отметить, что вы предпочитаете использовать функции, не являющиеся членами. То есть лучше это свободная функция:

bool operator<(const _pos& lhs, const _pos& rhs)
{
    return lhs.xi < rhs.xi;
}

В том же пространстве имен, что и ваш класс. (Для нашего примера, прямо под ним.)


Кстати, в C ++ нет необходимости ставить префикс объявления переменной типа структуры с struct. Это идеально, и предпочтительнее:

    _pos k1 = {0,10};
    _pos k2 = {10,15};

    _val v1 = {5.5};
    _val v2 = {12.3};

(Хотя имена ваших типов по общему признанию названы неортодоксальным образом.: P)


Наконец, вы должны предпочесть служебную функцию make_pair для создания пар:

    m.insert(std::make_pair(k1,v1));
    m.insert(std::make_pair(k2,v2));

Это избавляет вас от необходимости выписывать типы для пары и, как правило, легче читать. (Особенно, когда появляются более длинные имена типов.)

4 голосов
/ 15 апреля 2010

Я думаю, что ваше определение оператора <неверно - правая часть (в данном случае аргумент) должна быть помечена как const, и это должна быть функция-член const, например, </p>

    bool operator<(const _pos& other) const{ 

            return this->xi < other.xi; 
    } 
4 голосов
/ 15 апреля 2010

Подпись оператора меньше чем должна быть bool operator<(const _pos& other) const, иначе map не может использовать этот оператор в константных функциях, так как эта функция-член объявлена ​​как неконстантная.

...