天天看點

typename是什麼?

template

<

class

T>

void

foo(

const

T& t)

{

// 聲明一個指向某個類型為T::bar的對象的指針

T::bar * p;

}

struct

StructWithBarAsType

{

typedef

int

bar;

}; 

int

main()

{

StructWithBarAsType x;

foo(x);

}

這段代碼看起來能通過編譯,但是事實上這段代碼并不正确。因為編譯器并不知道T::bar究竟是一個類型的名字還是一個某個變量的名字。究其根本,造成這種歧義的原因在于,編譯器不明白T::bar到底是不是“模闆參數的非獨立名字”,簡稱“非獨立名字”。注意,任何含有名為“bar”的項的類T,都可以被當作模闆參數傳入foo()函數,包括typedef類型、枚舉類型或者變量等。 為了消除歧義,C++語言标準規定: A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename. 意即出現上述歧義時,編譯器将自動預設bar為一個變量名,而不是類型名。是以上面例子中的代碼 T::bar * p 會被解釋為乘法,而不是聲明p為指向T::bar類型的對象的指針。 如果還有另一個名為StructWithBarAsValue類型,如下:

1 2 3 4

struct

StructWithBarAsValue

{

int

bar;

};

那麼,編譯器将以完全不同的方式來解釋 T::bar * p 的含義。 解決問題的最終辦法,就是顯式地告訴編譯器,T::bar是一個類型名。這就必須用typename關鍵字,例如:

1 2 3 4 5 6

template

<

typename

T>

void

foo(

const

T& t)

{   

// 聲明一個指向某個類型為T::bar的對象的指針

typename

T::bar * p;

}

這樣,編譯器就确定了T::bar是一個類型名,p也就自然地被解釋為指向T::bar類型的對象的指針了。