次のヘッダーファイルを検討してください。
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
コンパイラーがなぜこれを叫んでいるのか、私にはわかりません。
list<tNode<T>*>::iterator
には、依存名、つまりテンプレートパラメータに依存する名前があります。
そのため、コンパイラはlist<tNode<T>*>
(この時点では定義がありません)を検査できないため、list<tNode<T>*>::iterator
が静的フィールドであるか、型であるかがわかりません。
このような状況では、コンパイラはそれがフィールドであると想定するため、あなたの場合、構文エラーが発生します。この問題を解決するには、宣言の前にtypename
を付けて、それが型であることをコンパイラに伝えます。
typename list<tNode<T>*>::iterator it
まず、既に述べた他の回答のように、依存型にネストされた型名の前にtypename
キーワードを追加する必要があります。
テンプレートが完全に特殊化されている場合、そのキーワードは必要ありません。つまり、list<tnode<int>*>::iterator
はtypename
を必要としませんが、外部クラスがテンプレートパラメーターT
、typename
が存在する必要があります。
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();
宣言は、反復子ではなく関数を宣言します。 ()
を削除します。
list<tNode<T>*>::iterator
は、テンプレートパラメータに依存する型の依存名です。その変数を宣言するには、typename
キーワードを使用する必要があります。
typename list<tNode<T>*>::iterator it = ...;
上記の回答の詳細はこちらをご覧ください
私は別の似たような問題がありました:
typedef std::vector<NodeType*>::iterator ChildIterator;
同じコンパイラエラーが発生しました。ここでの提案と上記のリンクの助けを借りて、私の問題の解決策は
typedef typename std::vector<NodeType*>::iterator ChildIterator;
代わりに。