3

I have a map with a more or less custom Key-Type (Point2f from OpenCV) and thus need to write my own operator<. Except, my operator< doesn't get accepted.

Creation of the Map/Accessing an element by key:

using namespace cv;
void foo()
{
    map<Point2f, double> properties;

    properties[Point2f(0, 0)] = 0;
}

and this is my operator:

using namespace cv;
bool operator<(Point2f lhs, Point2f rhs)
{
    return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;
}

but when I try to set a value of the map using a key like above, my compiler gives me

/usr/include/c++/4.8/bits/stl_function.h|235|error: no match for ‘operator<’ (operand types are ‘const cv::Point_<float>’ and ‘const cv::Point_<float>’)|

(gcc, IDE Code::Blocks)

I already tried

  • specifying the type exactly (cv::Point_<float>)
  • putting the operator directly above the function calling it
  • using const, reference or const reference for the variables passed to the operator instead of values

Nothing worked, the error keeps coming. Why does it appear and what do I need to change to make it work?

captain
  • 35
  • 5
  • Where is your `operator<` declared in relation to this code? – NathanOliver Jan 11 '16 at 17:49
  • You need to indicate what parts of your code snippets are within the `cv` namespace, I think the problem is you have your `operator<` defined outside of the namespace, and ADL is not able to find it. – Praetorian Jan 11 '16 at 17:51
  • @NathanOliver First I tried it with the operator< declared in a header file included in the source file using the map. When that didn't work I just moved the definition above the function using the map. Still didn't work. – captain Jan 11 '16 at 17:52
  • @Praetorian I imported both namespaces in all my files (with using namespace std/cv) and it still does not work (I know that is not good practice, but this is just a small project). – captain Jan 11 '16 at 17:58
  • @captain It works here with a made-up `Point2f` class and everything you've described in your post: http://ideone.com/dvCX1r -- So it is something that you're not telling us, or that `Point2f` class has something internal that is throwing the code off. – PaulMcKenzie Jan 11 '16 at 18:12
  • @PaulMcKenzie Thank you for taking the time to create an example, something the OP should've done himself! The problem with it is that your `Point2f` is not within the `cv` namespace. – Praetorian Jan 11 '16 at 18:32
  • @Praetorian Was my first question on this board, but I will remember that. Thank you. – captain Jan 11 '16 at 18:41

1 Answers1

5

Adapting the example posted in the comments, so that the mock Point2f class is within the cv namespace, as the original is, reproduces the error.

namespace cv
{
struct Point2f
{
    int x, y;
    Point2f(int v1, int v2) : x(v1), y(v2) {}
};
}

Live demo

Adding a using directive following the definition above makes no difference because using namespace cv means bring everything under the cv namespace into the current scope, not everything that follows automatically gets added to the cv namespace.

Define your operator< as follows so that ADL is able to find it.

namespace cv
{
bool operator<(Point2f const& lhs, Point2f const& rhs) // pass by reference is not necessary
                                                       // but might as well
{
    std::cout << "calling custom operator <\n";
    return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;
}
}

Live demo


Another option, to avoid adding operator overloads to someone else's namespace, is to define a comparator for Point2f objects.

struct Point2fLess
{
    bool operator()(Point2f const&lhs, Point2f const& rhs) const
    {
        std::cout << "calling custom operator <\n";
        return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;
    }
};

Now define your map as

std::map<Point2f, double, Point2fLess> properties;

Live demo

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328