web-dev-qa-db-ja.com

C ++テンプレート型名イテレータ

次のヘッダーファイルを検討してください。

template <typename T> struct tNode
{
    T Data;                      //the data contained within this node
    list<tNode<T>*> SubNodes;       //a list of tNodes pointers under this tNode

    tNode(const T& theData)
    //PRE:  theData is initialized
    //POST: this->data == theData and this->SubNodes have an initial capacity
    //      equal to INIT_CAPACITY, it is set to the head of SubNodes
    {
        this->Data = theData;
        SubNodes(INIT_CAPACITY);   //INIT_CAPACITY is 10
    }

};

次に、別のファイルのコード行を考えてみましょう。

list<tNode<T>*>::iterator it();  //iterate through the SubNodes

コンパイラから次のエラーメッセージが表示されます:Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope

コンパイラーがなぜこれを叫んでいるのか、私にはわかりません。

38

list<tNode<T>*>::iteratorには、依存名、つまりテンプレートパラメータに依存する名前があります。

そのため、コンパイラはlist<tNode<T>*>(この時点では定義がありません)を検査できないため、list<tNode<T>*>::iteratorが静的フィールドであるか、型であるかがわかりません。

このような状況では、コンパイラはそれがフィールドであると想定するため、あなたの場合、構文エラーが発生します。この問題を解決するには、宣言の前にtypenameを付けて、それが型であることをコンパイラに伝えます。

typename list<tNode<T>*>::iterator it
65
akappa

まず、既に述べた他の回答のように、依存型にネストされた型名の前にtypenameキーワードを追加する必要があります。

テンプレートが完全に特殊化されている場合、そのキーワードは必要ありません。つまり、list<tnode<int>*>::iteratortypenameを必要としませんが、外部クラスがテンプレートパラメーターTtypenameが存在する必要があります。

template <typename T> void foo() {
  list<tnode<int>*>::iterator it1; // OK without typename
  typename list<tnode<T>*>::iterator it2; // typename necessary
}

第二に、typenameであっても

typename list<tNode<T>*>::iterator it();

宣言は、反復子ではなく関数を宣言します。 ()を削除します。

21
AnT

list<tNode<T>*>::iteratorは、テンプレートパラメータに依存する型の依存名です。その変数を宣言するには、typenameキーワードを使用する必要があります。

typename list<tNode<T>*>::iterator it = ...;
5
mfontanini

上記の回答の詳細はこちらをご覧ください

C++ typenameキーワードの説明

私は別の似たような問題がありました:

typedef std::vector<NodeType*>::iterator ChildIterator;

同じコンパイラエラーが発生しました。ここでの提案と上記のリンクの助けを借りて、私の問題の解決策は

typedef typename std::vector<NodeType*>::iterator ChildIterator;

代わりに。

1
trueter