typename,类型成员和非类型成员:它是有效的代码吗?

sky*_*ack 4 c++ gcc clang typename language-lawyer

请考虑以下代码:

struct S {
    struct type {};
    type type;
};

int main() {  
    typename S::type t;
    (void) t;
}
Run Code Online (Sandbox Code Playgroud)

除了这个事实远非一个好主意之外,我在这里阅读了另一个问题后进行了实验.
我发现上面的代码片段被GCC编译没有错误,并且被clang 3.9拒绝,并出现以下错误:

错误:typename说明符引用'S'中的非类型成员'type'

我怀疑在这种情况下clang是正确的并且GCC是错误的(实际上,我正在向后者开放一个问题).
这是正确的结论还是有效使用typename


注意:我不是在问如何解决它,我知道该怎么做.我只询问这段代码是否有效.

cpp*_*ner 7

[temp.res]/4:

通常的限定名称查找用于查找qualified-id,即使存在typename.

也就是说,与elaborated-type-specifier s 的情况不同,在这种情况下,名称查找不会忽略非类型名称.

[temp.res]/3:

如果合格-ID类型名称说明符并不表示一个类型或类模板,是形成不良的程序.

所以这个程序是不正确的.

[temp.res]/4也有一个例子:

struct A {
  struct X { };
  int X;
};
struct B {
  struct X { };
};
template<class T> void f(T t) {
  typename T::X x;
}
void foo() {
  A a;
  B b;
  f(b);             // OK: T::X refers to B::X
  f(a);             // error: T::X refers to the data member A::X not the struct A::X
}
Run Code Online (Sandbox Code Playgroud)

  • @GillBates `S::type` 是一个类型名和一个非类型名,非类型名隐藏了类型名。 (2认同)