Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interaction of function-local enum declaration and ADL

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!

like image 990
Chris Uzdavinis Avatar asked Apr 08 '26 20:04

Chris Uzdavinis


1 Answers

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.

like image 59
Barry Avatar answered Apr 10 '26 10:04

Barry