为什么clang不允许通过实例访问嵌套的枚举类?

dan*_*pla 9 c++ clang language-lawyer

请考虑以下代码:

struct S {
    enum class EnumClass {
        one
    } ;

    enum Enum {
        one
    };
};

int main()
{
    S s;
    S::EnumClass e = s.EnumClass::one; // <- Doesn't compile with clang
    S::Enum e11 = s.Enum::one;
    S::Enum e12 = s.one;
}
Run Code Online (Sandbox Code Playgroud)

一切都适用于GCC,但clang(3.8和3.9都没有)编译s.EnumClass::one,给出错误:'S::EnumClass::one' is not a member of class 'S'.

鉴于未编码的枚举工作正常,这似乎是一个错误.

Rak*_*111 9

这是gcc 1中的一个错误.相关措辞在[expr.ref] p2中:

在任何一种情况下,id-expression [here:EnumClass::one]都应该命名该类或其一个基类的成员.

EnumClass::one它不是指一个类的成员,它是一个枚举的成员.这个枚举是否是该类的一部分无关紧要,只是该成员one本身不属于该类.

但是Enum::one课程的一部分?是的,根据[class.member] p1:

类的成员是数据成员,成员函数,嵌套类型,枚举器以及其成员模板和特化.

并在[class.member] p3中更加明确:

类中定义的无范围枚举的枚举器是类的成员.


1:我甚至会把它称为标准中的一个错误,因为似乎没有任何(技术)理由为什么不允许这样做,我认为允许它是个好主意.虽然有关于允许它的讨论,但让我们看看委员会的决定.

  • 关于什么是和不是成员,它看起来像`struct S {struct T {static const int t = 0; }; } s; int main(){return sT :: t; 这被gcc,clang,Intel和MSVC都拒绝了.如果不接受,我不明白为什么`enum`等价物应该有任何不同,所以我很难将其视为标准中的错误,而不仅仅是gcc(和MSVC)中的错误. (2认同)
  • 语法`sT :: t`已经具有明确的含义,即从基类中访问成员,即使它们可能已被派生类隐藏.我想可以做一个例外,即`.`的LHS表达式不需要从声明类型派生,如果它实际上不会被使用,但这也会产生许多不需要的东西,并破坏现有的代码依赖SFINAE. (2认同)