2010-11-19 15 views
3

を使用しているとき、私は、キーワード「型名」を使用する必要があります。..私は小さなプロジェクトで最近取り組んできた、と私は何かを把握することができませんでしテンプレート

私はその.hファイルを与えられてきましたtypenameテンプレートを使用してクラスを含んでいました。そのクラスの中にプライベートクラスがありました。私はクラスの関数を定義したいときに問題が

を「何か」を発生し

template <typename T> 
class Something 
{ 
public: 
     Something(); 
     ~Something(); 

     Node* Function1(int index); 
     int Index(const T& id); 


private: 
     class Node() 
     { 
       public: 
       T id; 

       //Imagine the rest for the Node 


     };  
}; 

ここで(.inlファイルに)私はそれをやっていた方法です

template<typename T> 
Node* Something::Function1(int index) //Is the return type well written? 
{ 
     // returns the node at the specified index 
} 

template<typename T> 
int Something::Index(const T& id) //Is the parameter type well specified? 
{ 
     // returns the index of the node with the specified id 
} 

ので盗聴その部分は定義部分にありました...戻り値の型(この場合はNode *)がtypenameテンプレート(これはtypename Node*)を使用することをコンパイラに伝えなければなりませんか?パラメータはどうですか? typename const Node&

基本的に、関数/パラメータがテンプレートを使用するかどうかを指定する必要があるのはいつですか?

お時間をいただきありがとうございます。

+0

あなたの質問にsinppetsを投稿してください! – mmmmmmmm

+0

スニペットとのリンクを投稿しました。私はスニペットを正しくインデントする方法を理解できませんでした。 – Pacane

答えて

2
template<typename T> 
typename Something<T>::Node * Something::Function1(int index) //Is the return type well written? 
{ 
     // returns the node at the specified index 
} 
+0

Ok、他のメソッドのパラメータタイプはどうですか? – Pacane

+3

'Node'はネストされたクラス名です。だから、 'Something 'のメソッドのコードに入っていないか、完全な 'typename Something :: Node'という名前を使用していない限り、それを使うことはできません。そして、メソッドの戻り値の型(クラスの外で定義されている)は、まだ 'Something'のメソッドの" in "ではないので、コンパイラに明示する必要があります。コンパイラは 'int 'が何を意味するのかを常に知っているので、他の方法ではこのような問題はありません。 – aschepler

+0

説明をいただきありがとうございました。 – Pacane

3

単純なルール:Class部分はテンプレートパラメータに依存している場合あなたは、あなたがClass::Type構文を使用してタイプを命名typenameキーワードを毎回使用する必要があります。 (Classの部分がテンプレートパラメータであるか、クラステンプレートにtypedefなどがある可能性があります)

編集:ネストされたクラスのスコープ規則については混乱もあります。これは主にtypenameの問題とは関係ないので、テンプレート以外の例を示します。

class Outer { 
public: 
    class Inner { 
    }; 
    Inner* func(Inner* obj); 
}; 

Outer::Inner* func(Inner* obj) 
{ 
} 

InnerのフルネームはOuter::Innerです。しかし、より短い名前Innerを、Outerクラスのスコープから、funcの宣言のすべてを含めて使用することもできます。 funcの定義では、戻り値の型はOuterのスコープではないので、完全な名前が必要です。しかし、(の後には、ファンクションパラメータはOuterの範囲にあります。したがって、短い名前は大丈夫です。 Outerの相当Something<T>であることから、元の例のテンプレートネスでこれを組み合わせる

、あなたはSomething<T>::Nodeを言うためにtypenameキーワードを必要としています。

+0

したがって、関数Indexの定義におけるパラメータ型はtypename const Class :: Node&id?と書かれていなければなりません。 – Pacane

+1

@Pacane:それは、あなたが 'T'か' Node'を渡したいのですか? 'Node'を渡したいのであれば、完全版は動作しますが、コンパイラは' Something'メソッドを定義しているのを見ただけで、 'const Node&'は問題ありません。 – aschepler

+0

説明をいただきありがとうございました。 – Pacane

5

Function1の場合、コンパイラにどのノードがあるかを伝える必要があります。この場合、ネストされたタイプはSomething<T>です。それはT(それは従属名です)に依存しているので、コンパイラにタイプであることを伝える必要がありますので、typename Something<T>::Nodeと書く必要があります。問題は、Something<T>::Nodeが実際にタイプ(Something<T>を部分的に専門にしている場合)ではないがある可能性があります。

Indexの場合、const T&const Tへの参照に過ぎず、コンパイラはTを知っています。

+0

そのようなパラメータがノードへのポインタであった場合、typenameの部分をもう一度指定する必要があります。 – Pacane

+1

'Something 'の中にいるので、 'Node *'と書くことができます。しかし、明示的に書いたのであれば、 'Something :: Node *'ではなく、 'typename Something :: Node *'と言う必要があります。 –

+0

説明をしてくれてありがとう、ありがとう。 – Pacane

1

typenameclassは、テンプレート型パラメータリストに等価である:dependent namesに言及する場合

template <class T> class C; 

typenameが要求される場合

template <typename T> class C; 

と同じである。

template <typename T> struct A { 
    typedef typename T::some_type container; 
}; 
+2

実際、typenameとclassはパラメータリストでは等価ではありません。 typenameキーワードは、テンプレート・テンプレート・パラメータが必要なときに 'class'を置き換えることはできません。 –

+0

はい、ありがとう、これを忘れました。それは言語の部分でちょうどブーちゃんです - 彼らはちょうど私がここと同じ事を忘れてしまった:) –

関連する問題