Question

I have a small program I want to execute to test something

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

The problem is that when I try to compile it, I get the following error

$ 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&)
$ 

I thought that declaring the operator< on the key would solve the problem, but its still there.

What could be wrong?

Thanks in advance.

Was it helpful?

Solution

The problem is this:

bool operator<(_pos& other)

Should be this:

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

Without the first const, the right-hand side of the comparison (b in a < b) cannot be const, since without const the function may modify its argument.

Without the second const, the left-hand side of the comparison (a in a < b) cannot be const, since without const the function may modify this.

Internally, the key's of a map are always const.


It should be noted that you should prefer to use nonmember functions. That is, better is a free-function:

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

In the same namespace as your class. (For our example, just underneath it.)


By the way, in C++ there is no need to prefix the declaration of a struct type variable with struct. This is perfect, and preferred:

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

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

(Though your type names are admittedly named in an unorthodox manner. :P)


Lastly, you should prefer the make_pair utility function for making pairs:

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

It saves you from having to write out the types for the pair, and is generally easier to read. (Especially when longer type names come along.)

OTHER TIPS

Signature of the less than operator needs to be bool operator<(const _pos& other) const, otherwise map can not use this operator in const functions since this member function is declared as non-const.

I think that your definition of operator< is wrong - the right hand side (argument in this case) should be marked const and it should be a const member function, e.g.

    bool operator<(const _pos& other) const{ 

            return this->xi < other.xi; 
    } 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top