The function in namespace X returns an enumerator from a locally defined enum class, via an auto deduced return type. That return value is then passed to an unqualified function, and on g++ (7.3, 8.2, trunk) it finds the function in namespace X. On clang, it gives an error for not finding the function.
I assume it has to do with ADL and the question of whether a function-local declared enum is in the function's containing namespace.
Which compiler is right, and why? (Standard citation appreciated.)
namespace X {
template <typename EnumT>
EnumT getA(EnumT) {
return EnumT::A;
}
enum class Foo { B, A, C };
auto getLocalEnumerator() {
enum class Bar { A, B, C };
return Bar::C;
}
}
int main() {
auto e1 = X::Foo::C; // unambiguously in namespace X
auto e2 = X::getLocalEnumerator(); // unsure what namespace this is
auto a1 = getA(e1); // obvious use of ADL
auto a2 = getA(e2); // clang: error, g++: ADL ok
}
live on godbolt: https://godbolt.org/g/w2DhDm
Thanks!
This is a clang bug. From [basic.lookup.argdep]/2:
The sets of namespaces and classes are determined in the following way: [...] If T is an enumeration type, its associated namespace is the innermost enclosing namespace of its declaration. If it is a class member, its associated class is the member's class; else it has no associated class.
The local enumeration Bar has as its associated namespace the innermost enclosing namespace... which is X. Unqualified lookup on getA finds nothing, so we go ahead and look in all the associated namespaces of all of the arguments - the set of associated namespaces is {X}. Lookup there should find X::getA.
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