函数局部枚举声明和ADL的交互

时间:2018-08-15 22:54:27

标签: c++ c++14 language-lawyer

名称空间X中的函数通过自动推断的返回类型从本地定义的枚举类返回枚举数。然后将该返回值传递给不合格的函数,在g ++(7.3、8.2,trunk)上,它在名称空间X中找到该函数。在clang上,它给出了找不到该函数的错误。

我认为这与ADL和函数本地声明的枚举是否在函数的包含名称空间中有关。

哪个编译器正确,为什么? (赞赏标准引用。)

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
}

靠锚栓生活:https://godbolt.org/g/w2DhDm

谢谢!

1 个答案:

答案 0 :(得分:4)

这是一个clang错误。来自[basic.lookup.argdep]/2

  

以下列方式确定名称空间和类的集合:[...]如果T是枚举类型,则其关联的名称空间是其声明的最内部封闭的名称空间。如果是类成员,则其关联的类是成员的类;否则它没有关联的类。

本地枚举Bar具有最里面的封闭命名空间... X作为其关联的命名空间。在getA上进行不合格的查找不会发现任何内容,因此我们继续查看所有参数的所有关联命名空间-关联命名空间的集合为{X}。在此处查找应该找到X::getA