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

问题描述:

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

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

int main() { 
    typename S::type t; 
    (void) t; 
} 

除了一个事实,即是远不是一个好主意,我看了这里SO另一个问题后进行试验。
我发现上面的代码片段是compiled with no errors by GCC,它是rejected by clang 3.9,出现以下错误:

error: typename specifier refers to non-type member 'type' in 'S'

我怀疑铛就在这种情况下,和GCC是错误的(实际上,我打开一个问题的后者)。
这是正确的结论还是typename的有效使用?


注:我不是问如何解决它,我知道如何做到这一点。我只问这个代码是否有效。

+0

较旧的gcc像4.4.7拒绝它太:http://melpon.org/wandbox/permlink/Oh2Rp4jWjGPIoIwv – marcinj

+1

Couldn”在标准中找到关于这种合法性的任何东西。尽管如此,'typename'只是在模板方面提到的,所以也许这是一种违背精神的行为?无论如何,解决这种特定歧义的正确和标准方法似乎是'struct S :: type t;' – StoryTeller

+2

@marcinj这似乎是因为GCC 4.4.7没有在外部实现[CWG 382:允许'typename' (http://wg21.link/cwg382)。 – cpplearner

[temp.res]/4

The usual qualified name lookup is used to find the qualified-id even in the presence of typename .

也就是说,不像的情况下阐述类型说明符秒,在这种情况下,不忽略非类型名称的名称查找。

[temp.res]/3

If the qualified-id in a typename-specifier does not denote a type or a class template, the program is ill-formed.

所以有问题的程序是病态的。

[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 
} 
+0

但'S :: type'是一种类型。 –

+0

@GillBates'S :: type'是类型名称和非类型名称,非类型名称隐藏类型名称。 – cpplearner

+0

虽然这是模板名称解析,但在OP的问题中没有涉及,我不认为可以说规则是相同的。 –