2016-11-10 68 views
3

考慮下面的代碼: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

回答

7

[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的問題中沒有涉及,我不認爲可以說規則是相同的。 –

相關問題