Consider a simple type, in a namespace, with an operator==
:
namespace ANamespace {
struct Foo { int i; float f; };
}
#ifdef INSIDE
namespace ANamespace {
bool operator==(const Foo& l, const Foo& r)
{
return l.i == r.i && l.f == r.f;
}
}
#else
bool operator==(const ANamespace::Foo& l, const ANamespace::Foo& r)
{
return l.i == r.i && l.f == r.f;
}
#endif
bool compareElements(const std::vector<ANamespace::Foo>& l, const std::vector<ANamespace::Foo>& r)
{
return l == r;
}
If operator==
is defined inside ANamespace
(by defining INSIDE
), the example compiles. But if operator==
is defined in the global namespace (the #else
case), the function compareElements()
doesn't compile - both in GCC and Clang, and with both libstdc++ and libc++. All emit a template error along the lines of:
In file included from /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../include/c++/9.2.0/vector:60:
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_algobase.h:820:22: error: invalid operands to binary expression ('const ANamespace::Foo' and 'const ANamespace::Foo')
if (!(*__first1 == *__first2))
~~~~~~~~~ ^ ~~~~~~~~~
...
However, directly comparing two Foo
s in a function, e.g.,
bool compareDirectly(const ANamespace::Foo& l, const ANamespace::Foo& r)
{
return l == r;
}
seems to work fine regardless of where operator==
is defined.
Are there rules in the standard about where the STL expects operator==
to be defined?
!(*__first1 == *__first2)
takes place in std::operator==
, a function template, so it is considered a dependent unqualified function call expression, so during overload resolution only functions found within the definition context of std::operator==
and those found via ADL are candidates.
Clearly there are no operator==(const Foo&, const Foo&)
declared within the context of the definition of the standard comparison operator. In an argument dependent lookup (ADL) the namespaces of each of the arguments are checked to search for a viable function for the call, so this is why defining operator==
inside of ANamespace
works.