簡體   English   中英

模板中的關鍵字“ typename”

[英]Keyword “typename” in Templates

以下是代碼,引自Addison WesleyC ++模板

template <typename T> 
  class MyClass { 
      typename T::SubType * ptr; 
      … 
  };

沒有類型名,SubType將被視為靜態成員。 因此,它將是一個具體的變量或對象。 結果,表達式T::SubType *ptr將是類T的靜態SubType成員與ptr的乘積。

現在,當我不使用關鍵字'typename'編譯該代碼時,我得到的錯誤是: type 'T' is not derived from type 'MyClass<T>'

編譯器識別出“ T”嗎? 如果不是,那么它應該不是未定義的參考錯誤嗎? 如果是,那為什么會出錯?

好了,這里是完整的代碼:

#include <iostream>
#include <vector>

template <typename T> class MyClass 
{ 
     T::SubType * ptr; 
};

int main ()
{
    return 0;
}

我得到的錯誤是這樣的:

~/Desktop/notes **g++ templates/programs/trial.cpp**
templates/programs/trial.cpp:6: error: type ‘T’ is not derived from type ‘MyClass<T>’
templates/programs/trial.cpp:6: error: expected ‘;’ before ‘*’ token

這是從g ++獲取相同錯誤的另一種方法:

class Foo { static const int x = 0;};

template <typename T> class MyClass
{
     Foo::x * ptr;
};

另一個:

class Foo { static const int x = 0;};

class MyClass
{
     Foo::x * ptr;
};

但是,您會得到一個不同的錯誤:

// class Foo { static const int x = 0;};

template <typename T> class MyClass
{
     Foo::x * ptr;
};

所以:

  1. 因為T是從屬類型,所以g ++假定T::SubType是將在第二階段查找發生時定義的對象。 符合預期,這是此處需要typename的常見原因。

  2. 即使 T::SubType存在並且是對象,代碼也仍然是錯誤的,就像Foo::x *ptrFoo::x存在並且是對象時Foo::x *ptr是錯誤的一樣。 我仍然不明白錯誤消息的含義-從MyClass派生Foo會對它有什么幫助? 但是錯誤消息與模板無關。

  3. “未定義的引用”是鏈接器錯誤。 由於此代碼甚至無法編譯,因此您不應期望在任何地方看到“對T的未定義引用”。

  4. 我到目前為止還沒有看到Foo甚至可以從MyClass派生而來。 我嘗試了以下內容,以了解是否可以了解原始消息的含義,但是失敗了,因為MyClass是不完整的類型,它不能告訴我有關Foo派生自MyClass

class MyClass
{
    class Foo: public MyClass { static const int x = 0;};
     Foo::x * ptr;
};

在所有這些情況下,Comeau都會給出更明智的錯誤消息-與派生類型無關,只是說T::SubType不是類型。 因此,解釋g ++的錯誤消息將需要有關g ++內部的知識或猜測,而在嘗試解析類模板的過程中它最終會放棄的確切位置。

沒有類型名,SubType將被視為靜態成員。 因此,它將是一個具體的變量或對象。 結果,表達式T :: SubType * ptr將是類T的靜態SubType成員與ptr的乘積。

當應用於您給出的示例時,此描述不正確。 在類主體中,不能有表達式,也沒有任何構造被解析為乘法。 但是,在C ++ 03語法中,有一個結構如下

struct Base { int a; };
struct Derived : Base {
  Base::a; // access-declaration
};

此構造在C ++ 03中已棄用,但仍受支持,其含義與以下相同

struct Base { int a; };
struct Derived : Base {
  using Base::a; // using-declaration
};

因為您沒有告訴編譯器T::SubType是類型,因此告訴編譯器它應該將其解析為指針聲明的類型,所以編譯器假定T::SubType是訪問聲明中的名稱。 。 因此,它預期分號后直接它,並且因此預期T是一個基類MyClass<T>MyClass<T>派生類T )。 該錯誤消息實際上使它向后:

 if (! UNIQUELY_DERIVED_FROM_P (IDENTIFIER_TYPE_VALUE (cname),
                                   ctype))
      {
        cp_error ("type `%T' is not derived from type `%T'",
                  IDENTIFIER_TYPE_VALUE (cname), ctype);
        ...
      }

雖然宏說

 /* Nonzero iff TYPE is uniquely derived from PARENT.  Under MI, PARENT can
    be an ambiguous base class of TYPE, and this macro will be false.  */
 #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) ...

因為T::SubType是從屬名稱,所以您需要通過鍵入typename關鍵字來告訴編譯器SubType是一種類型 (不是靜態數據成員)。

在此處閱讀有關依賴名稱的信息:


編輯:

關於您的問題(您在評論中重復了):

我認為您發布的不是完整的代碼。 因此,我無法對此發表特別評論。 另外,有時編譯器不夠聰明,無法准確指出模板代碼中的錯誤。 因此,我建議您閱讀有關依賴名稱的信息,以及何時以及為什么需要輸入typename的信息。 希望那之后您將沒有任何問題!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM