2014-10-17 56 views
15

下面的代碼位在VS2008和GCC 4.8.2編譯typedef Foo <> Foo編譯但它有效嗎?

template<typename T=void> 
struct Foo 
{ 
}; 

// typedef Foo<> Foo; // Does *NOT* compile 

int main() 
{ 
    typedef Foo<> Foo; 
    Foo f1; 

    // Foo<char> f2;  // Does *NOT* compile 
    //::Foo<char> f3; // COMPILES 
} 

是否有效?

+1

您正在模板中提供默認參數。這是完全有效的。 – 2014-10-17 18:29:41

+2

@Captain:但是他們都被命名爲'Foo'的事實呢? – Cameron 2014-10-17 18:30:15

回答

17

按照C++ 11 3.3.10/1:

名稱可以由同一個名字的一個明確的聲明被隱藏一個嵌套聲明區域或派生 類。

(重點煤礦)

這就是爲什麼模板名稱Foo可以通過typedef名稱Foomain()隱藏(不同的範圍),但不是在相同的範圍內模板名稱聲明。

至於爲什麼這種類似的例子是合法的:

struct Foo 
{ 
}; 

typedef Foo Foo; // *DOES* compile 

這由7.1.3/3被明確允許:

在給定的非類範圍,一個typedef符可以是用於重新定義該 範圍內聲明的任何類型的名稱,以指向其已引用的類型。

+4

+1引用規範! – 2014-10-17 19:50:10

+1

3.3.1 [basic.scope.declarative]/p4也是相關的。 – 2014-10-17 22:12:30

11

是它是有效的,出於同樣的原因,這是有效的:

struct Foo { }; 

namespace bar { 
    struct Foo { }; 
} 

你只是在不同的範圍覆蓋了名。裏面的主,你仍然可以這樣做:

::Foo<int> f2; 
+0

啊,typename shadowing。如何美味偷偷摸摸:O – Cameron 2014-10-17 18:33:51

+0

我認爲這個答案不對 - 有一個模板Foo取代了typedef(在一個命名空間中) – 2014-10-17 18:37:14

+0

@DieterLücking爲什麼?我可以很容易地創建一個'int Foo = 7;'這只是一個名字。 – Barry 2014-10-17 18:40:35

相關問題