Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::less<> not working with my std::map

Tags:

c++

std

stl

I wanted to make a map with my own struct 'Point2' as key, however I am getting errors and I don't know what's causing it, since I declared an 'operator<' for the Point2 struct.

Code:

std::map<Point2, Prop*> m_Props_m;
std::map<Point2, Point2> m_Orders;

struct Point2
{
    unsigned int Point2::x;
    unsigned int Point2::y;

Point2& Point2::operator= (const Point2& b)
    {
        if (this != &b) {
            x = b.x;
            y = b.y;
        }
        return *this;
    }

    bool Point2::operator== (const Point2& b)
    {
        return ( x == b.x && y == b.y);
    }

    bool Point2::operator< (const Point2& b)
    {
        return ( x+y < b.x+b.y );
    }

    bool Point2::operator> (const Point2& b)
    {
        return ( x+y > b.x+b.y );
    }
};

Error:

1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const Point2' (or there is no acceptable conversion)
1>c:\testing\project\point2.h(34): could be 'bool Point2::operator <(const Point2 &)'
1>while trying to match the argument list '(const Point2, const Point2)'
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(124) : while compiling class template member function 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const'
1>          with
1>          [
1>              _Ty=Point2
1>          ]

Can anyone see what's causing the problem?

like image 383
xcrypt Avatar asked Dec 17 '22 06:12

xcrypt


2 Answers

std::map expects a const version of operator <:

// note the final const on this line:
bool Point2::operator< (const Point2& b) const
{
    return ( x+y < b.x+b.y );
}

It doesn't make sense to have non-const versions of operator==, operator>, those should be const as well.

As ildjarn points out below, this is a clear case where you can implement these operators as free functions instead of member functions. Generally, you should prefer these operators as free functions unless they need to be member functions. Here's an example:

bool operator<(const Point2& lhs, const Point2& rhs)
{
    return (lhs.x + lhs.y) < (rhs.x + rhs.y);
}
like image 146
Chad Avatar answered Dec 30 '22 21:12

Chad


The operator< should be defined as const, in fact so should your other comparison operators, and in general, any method that doesn't mutate its class:

bool Point2::operator== (const Point2& b) const
{
    return ( x == b.x && y == b.y);
}

bool Point2::operator< (const Point2& b) const
{
    return ( x+y < b.x+b.y );
}

bool Point2::operator> (const Point2& b) const
{
    return ( x+y > b.x+b.y );
}
like image 42
James Avatar answered Dec 30 '22 19:12

James