4 回答

TA貢獻1942條經(jīng)驗 獲得超3個贊
是什么目的typename
和template
?
typename
并且template
可以在聲明模板以外的情況下使用。
在C ++中有某些上下文,其中必須明確地告訴編譯器如何處理名稱,并且所有這些上下文都有一個共同點; 它們依賴于至少一個模板參數(shù)。
我們指的是這樣的名稱,在解釋中可能存在歧義,因為; “ 從屬名稱 ”。
這篇文章將解釋依賴名稱和兩個關(guān)鍵字之間的關(guān)系。
一個SNACKET超過1000字
嘗試解釋以下功能模板中發(fā)生的事情,無論是對自己,朋友,還是你的貓; 標記為(A)的聲明中發(fā)生了什么?
template<class T> void f_tmpl () { T::foo * x; /* <-- (A) */ }
它可能不像人們想象的那么容易,更具體地說,評估(A)的結(jié)果在很大程度上取決于作為模板參數(shù)傳遞的類型的定義T
。
不同的T
s可以徹底改變所涉及的語義。
struct X { typedef int foo; }; /* (C) --> */ f_tmpl<X> ();struct Y { static int const foo = 123; }; /* (D) --> */ f_tmpl<Y> ();
兩種不同的場景:
如果我們用類型X實例化函數(shù)模板,就像在(C)中一樣,我們將聲明一個名為x的指向int的指針,但是;
如果我們用類型Y實例化模板,如(D)中所示,(A)將由一個表達式組成,該表達式計算123的乘積乘以一些已經(jīng)聲明的變量x。
理由
C ++標準關(guān)心我們的安全和幸福,至少在這種情況下。
為了防止實現(xiàn)可能遭受令人討厭的意外,標準要求我們通過明確說明我們想要將名稱視為類型名稱或模板的任何地方來明確依賴名稱的歧義。id。
如果沒有說明,則依賴名稱將被視為變量或函數(shù)。
如何處理依賴名稱?
如果這是一部好萊塢電影,依賴名字將是通過身體接觸傳播的疾病,立即影響其主人,使其混淆?;靵y可能會導(dǎo)致一個形成不良的人,erhm ..計劃。
甲從屬名稱是任何名稱直接或間接依賴于模板的參數(shù)。
template<class T> void g_tmpl () { SomeTrait<T>::type foo; // (E), ill-formed SomeTrait<T>::NestedTrait<int>::type bar; // (F), ill-formed foo.data<int> (); // (G), ill-formed }
我們在上面的代碼段中有四個依賴名稱:
E)
“類型”取決于實例化
SomeTrait<T>
,包括T
和;F)
“NestedTrait”,它是一個模板ID,取決于
SomeTrait<T>
,和;(F)末尾的“type”取決于NestedTrait,它取決于
SomeTrait<T>
,和;G)
“data”看起來像一個成員函數(shù)模板,間接是一個依賴名稱,因為foo的類型取決于它的實例化
SomeTrait<T>
。
如果編譯器將依賴名稱解釋為變量/函數(shù)(如前所述,如果我們沒有明確說明,則會發(fā)生的情況),語句(E),(F)或(G)都不是有效的。
解決方案
為了使g_tmpl
有一個有效的定義,我們必須明確告訴編譯器我們期望(E)中的類型,(F)中的模板ID和類型,以及(G)中的模板ID。
template<class T> void g_tmpl () { typename SomeTrait<T>::type foo; // (G), legal typename SomeTrait<T>::template NestedTrait<int>::type bar; // (H), legal foo.template data<int> (); // (I), legal}
每次名稱表示一個類型時,所 涉及的所有名稱都必須是類型名稱或名稱空間,考慮到這一點,我們很容易看到我們typename
在完全限定名稱的開頭應(yīng)用。
template
但是,在這方面是不同的,因為沒有辦法得出如下結(jié)論; “哦,這是一個模板,那么另外一件事也必須是模板”。這意味著我們template
直接在我們想要處理的任何名稱前面申請。
我是否只能在任何名字的前面貼上關(guān)鍵詞?
“ 我可以堅持
typename
并template
在任何名字前面嗎?我不想擔(dān)心它們出現(xiàn)的背景...... ” -Some C++ Developer
標準中的規(guī)則規(guī)定,只要您處理限定名稱(K),就可以應(yīng)用關(guān)鍵字,但如果名稱不合格,則應(yīng)用程序格式錯誤(L)。
namespace N { template<class T> struct X { };}
N:: X<int> a; // ... legaltypename N::template X<int> b; // (K), legaltypename template X<int> c; // (L), ill-formed
注意:申請typename
或template
在不需要的情況下,不被視為良好做法; 僅僅因為你可以做某事,并不意味著你應(yīng)該做。
此外,還有地方環(huán)境typename
和template
被明確禁止:
指定類繼承的基礎(chǔ)時
在派生類的base-specifier-list中編寫的每個名稱都已被視為類型名稱,顯式指定
typename
既是格式錯誤又是冗余。// .------- the base-specifier-list template<class T> // v struct Derived : typename SomeTrait<T>::type /* <- ill-formed */ { ... };
當(dāng)template-id是派生類的using-directive中引用的那個時
struct Base { template<class T> struct type { }; }; struct Derived : Base { using Base::template type; // ill-formed using Base::type; // legal };
- 4 回答
- 0 關(guān)注
- 787 瀏覽
添加回答
舉報