This may be asked before but I didn't have luck finding an answer...
I have an unordered container (i.e. a hash; we'll call it QHash, because it is, though this probably happens in any similar situation) that needs a comparison operator for it's key type.
Consider the following:
// foo.h
class Bar
{
public:
class Foo {};
};
// foo.cpp
#include <QtCore/QHash>
namespace
{
typedef Bar::Foo Foo;
bool operator==(Foo const& a, Foo const& b) { return &a == &b; }
}
uint qHash(Foo const& foo) { return qHash(&foo); }
int main()
{
QHash<Foo, int> hash;
// do stuff with hash, e.g.:
hash.insert(Foo(), 5);
return 0;
}
Using G++, all is well. However, clang gives an error in the bowels of qhash.h about invalid operands to binary expression
where trying to use ==
on instances of Foo
. It seems to me that clang is either not finding or rejecting the definition of operator==
in the anonymous namespace, probably due to different lookup rules than G++.
I am wondering, which compiler is correct?
p.s. I'm building in C++11 mode, in case it makes a difference.
Well, ADL looks into the namespaces a class is defined in. Look at [basic.lookup.argdep]/2: "For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set."
Note the last sentence.
So, for the original example, the typedef in the namespace of the operator doesn't help, gcc is wrong and clang is right.
This is a known GCC bug. Essentially, the problem is that GCC does not correctly implement two-phase name lookup for operator names. Your operator==
is not found by unqualified lookup (because it is declared too late) and is not found by argument-dependent name lookup (because ::(anonymous namespace)
is not an associated namespace of Bar::Foo
, so should not be considered inside the instantiation of qHash
.
If you move the definition of qHash
into the anonymous namespace, GCC will then reject the code, because its bug only applies to operator names and not to normal function names.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With