13

I'm trying to compile the following code:

#include <boost/geometry/geometries/point_xy.hpp> #include <iostream> #include <utility> typedef boost::geometry::model::d2::point_xy<long> Point; typedef std::pair<Point, Point> Vector; bool operator==(const Point& p1, const Point& p2) { return p1.x() == p2.x() && p1.y() == p2.y(); } int main() { Vector vec1(Point(0,0), Point(1,1)); Vector vec2(Point(0,0), Point(1,2)); std::cout << ((vec1 == vec2) == false) << std::endl; std::cout << ((vec1 == vec1) == true) << std::endl; } 

VS2012 C++ compiler returns the following compilation error:

...VC\include\utility(219): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const Point' (or there is no acceptable conversion)

GCC C++ compiler returns the following compilation error:

/usr/include/c++/4.8/bits/stl_pair.h:

In instantiation of ‘bool std::operator==(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = boost::geometry::model::d2::point_xy; _T2 = boost::geometry::model::d2::point_xy]’:

test.cpp:22:28: required from here /usr/include/c++/4.8/bits/stl_pair.h:215:51: error:

no match for ‘operator==’ (operand types are ‘const boost::geometry::model::d2::point_xy’ and ‘const boost::geometry::model::d2::point_xy’) { return __x.first == __y.first && __x.second == __y.second; }

Error disappears if I overload == operator for Vector:

bool operator==(const Vector& v1, const Vector& v2) { return v1.first == v2.first && v1.second == v2.second; } 
2
  • 4
    @WhozCraig Yes, since == is defined for std::pair by the standard library. Commented Oct 9, 2014 at 8:28
  • @WhozCraig: If the operator that compares the Point objects had been found by ADL, there would not be any need to provide an operator== for Vectors. Commented Oct 9, 2014 at 8:46

1 Answer 1

16

The reason why this fails is that the operator == for std::pair uses == to compare the pairs' members, which in turn uses argument-dependent lookup (ADL) to find the proper operator == for them. But you've provided the overload in the wrong namespace, since Point is actually a typedef for something in ::boost::geometry::model::d2, and not in ::.

If you move the operator into the correct namespace (which is a good idea anyway), it works:

#include <boost/geometry/geometries/point_xy.hpp> #include <iostream> #include <utility> typedef boost::geometry::model::d2::point_xy<long> Point; typedef std::pair<Point, Point> Vector; namespace boost { namespace geometry { namespace model { namespace d2 { bool operator==(const Point& p1, const Point& p2) { return p1.x() == p2.x() && p1.y() == p2.y(); } } } } } int main() { Vector vec1(Point(0,0), Point(1,1)); Vector vec2(Point(0,0), Point(1,2)); std::cout << ((vec1 == vec2) == false) << std::endl; std::cout << ((vec1 == vec1) == true) << std::endl; } 

Live example

Sign up to request clarification or add additional context in comments.

5 Comments

+1 I concur, Can you add an addendum explaining the seemingly rather cryptic error message: Candidate template ignored: could not match 'pair' against 'point_xy' that clang chooses to bless us with? I.e. How did that expression give us that mismatched comparison? Why did ADL miss one and not the other (or did it miss both) ?
@WhozCraig: unqualified lookup found the operator== that involves two pairs, ADL did not find any additional overloads. The compiler (clang) is telling you: I cannot use this one, and I don't know of any other.
Regarding the proposed solution, I don't quite like the idea of adding code to a namespace you don't own. Rather than adding the operator I would try to find out what alternative the library proposes (I would not expect that to be an oversight on the library, but intentionally left aside for some reason that escapes me). By adding code to their library you are risking breaking with the next update (what if they add the operator in the future?) and undefined behavior (what if two translation units see/don't see the operator, or see different versions?) I'd create a named function instead.
@DavidRodríguez-dribeas I likely didn't ask the right question. I know that ADL didn't find a matching equivalence operator. What i was trying to ask was the why the specific types in the resulting error message were reported. Neither item on that comparison is a simple point_xy, either in the call or in the implementation.
@WhozCraig I believe it's trying to compare the two point_xys inside the pair, but only finds the operator== template for comparing pairs.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.