亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我必須在何處以及為何要使用“模板”和“typename”關鍵字?

我必須在何處以及為何要使用“模板”和“typename”關鍵字?

有只小跳蛙 2019-05-20 16:07:40
在模板,在那里,為什么我必須把typename和template上依賴的名字呢?究竟什么是依賴名稱?我有以下代碼:template <typename T, typename Tail> // Tail will be a UnionNode too.struct UnionNode : public Tail {     // ...     template<typename U> struct inUnion {         // Q: where to add typename/template here?         typedef Tail::inUnion<U> dummy;      };     template< > struct inUnion<T> {     };};template <typename T> // For the last node Tn.struct UnionNode<T, void> {     // ...     template<typename U> struct inUnion {         char fail[ -2 + (sizeof(U)%2) ]; // Cannot be instantiated for any U     };     template< > struct inUnion<T> {     };};我遇到的問題就在typedef Tail::inUnion<U> dummy于此。我很確定這inUnion是一個從屬名稱,VC ++在窒息時非常正確。我也知道我應該能夠添加template某個地方告訴編譯器inUnion是一個模板ID。但到底在哪里?然后它應該假設inUnion是一個類模板,即inUnion<U>命名一個類型而不是一個函數?
查看完整描述

4 回答

?
手掌心

TA貢獻1942條經驗 獲得超3個贊

是什么目的typenametemplate

typename并且template可以在聲明模板以外的情況下使用。

C ++中有某些上下文,其中必須明確地告訴編譯器如何處理名稱,并且所有這些上下文都有一個共同點; 它們依賴于至少一個模板參數。

我們指的是這樣的名稱,在解釋中可能存在歧義,因為; “ 從屬名稱 ”。

這篇文章將解釋依賴名稱和兩個關鍵字之間的關系。


一個SNACKET超過1000字

嘗試解釋以下功能模板中發生的事情,無論是對自己,朋友,還是你的貓; 標記為(A)的聲明中發生了什么?

template<class T> void f_tmpl () { T::foo * x; /* <-- (A) */ }


它可能不像人們想象的那么容易,更具體地說,評估(A)的結果在很大程度上取決于作為模板參數傳遞的類型的定義T

不同的Ts可以徹底改變所涉及的語義。

struct X { typedef int       foo;       }; /* (C) --> */ f_tmpl<X> ();struct Y { static  int const foo = 123; }; /* (D) --> */
 f_tmpl<Y> ();


兩種不同的場景

  • 如果我們用類型X實例化函數模板,就像在(C)中一樣,我們將聲明一個名為x指向int指針,但是;

  • 如果我們用類型Y實例化模板,如(D)中所示,(A)將由一個表達式組成,該表達式計算123的乘積乘以一些已經聲明的變量x。



理由

C ++標準關心我們的安全和幸福,至少在這種情況下。

為了防止實現可能遭受令人討厭的意外,標準要求我們通過明確說明我們想要將名稱視為類型名稱模板的任何地方來明確依賴名稱的歧義。id。

如果沒有說明,則依賴名稱將被視為變量或函數。



如何處理依賴名稱?

如果這是一部好萊塢電影,依賴名字將是通過身體接觸傳播的疾病,立即影響其主人,使其混淆?;靵y可能會導致一個形成不良的人,erhm ..計劃。

從屬名稱任何名稱直接或間接依賴于模板的參數。 

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”看起來像一個成員函數模板,間接是一個依賴名稱,因為foo的類型取決于它的實例化SomeTrait<T>。

如果編譯器將依賴名稱解釋為變量/函數(如前所述,如果我們沒有明確說明,則會發生的情況),語句(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在完全限定名稱的開頭應用。

template但是,在這方面是不同的,因為沒有辦法得出如下結論; “哦,這是一個模板,那么另外一件事也必須是模板”。這意味著我們template直接在我們想要處理的任何名稱前面申請。



我是否只能在任何名字的前面貼上關鍵詞

“ 我可以堅持typenametemplate在任何名字前面嗎?我不想擔心它們出現的背景...... ” -Some C++ Developer

標準中的規則規定,只要您處理限定名稱K),就可以應用關鍵字,但如果名稱不合格,則應用程序格式錯誤(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

注意:申請typenametemplate在不需要的情況下,不被視為良好做法; 僅僅因為你可以做某事,并不意味著你應該做。


此外,還有地方環境typenametemplate明確禁止:

  • 指定類繼承的基礎時

    在派生類的base-specifier-list中編寫的每個名稱都已被視為類型名稱,顯式指定typename既是格式錯誤又是冗余。

                       // .------- the base-specifier-list
     template<class T> // v
     struct Derived      : typename SomeTrait<T>::type /* <- ill-formed */ {
       ...
     };


  • template-id是派生類的using-directive中引用的那個時

     struct Base {
       template<class T>
       struct type { };
     };
    
     struct Derived : Base {
       using Base::template type; // ill-formed
       using Base::type;          // legal
     };


查看完整回答
反對 回復 2019-05-20
  • 4 回答
  • 0 關注
  • 798 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號