2016-06-23 15 views
1

私はテンプレートを書いています。私は、実行するすべてのチュートリアルで実装されている各関数の上にテンプレートを宣言していることに気付きました。これが理由であれば、私は興味があります。もし周りに道があり、それがどのように役に立つのであれば。テンプレート内の各関数の上にテンプレートを宣言する必要があるのはなぜですか?

例:いくつかのファイルの中で(我々はそれをtemplate.h呼びます):それは テンプレートの種類とは何の関係も持っていない場合

template <class T> class MyClass 
{ 
public: 
    MyClass(T parameter); 
    T getParameter() const; 
    void setParameter(); 
    void doSomethingUseless() const; 
private: 
    T mParameter; 
} 


template<class T> 
MyClass<T>::MyClass(T parameter):mParameter{parameter} 
    {} 

template<class T> 
T MyClass<T>::getParameter() const 
    { 
     return mParameter; 
    } 

template<class T> 
void MyClass<T>::setParameter(T parameter) 
    { 
     mParameter = parameter; 
    } 
template<class T> 
void MyClass<T>::doSomethingUseless() const 
    { 
     for (int i = 0; i < 10000; i++) 
    } 
  • は、なぜ、すべての機能をテンプレート化しなければなりませんか? (doSomethingUselessメソッドなど)
  • template<class T>MyClass<T>はどちらもこの機能の上でコンパイルする必要がありますか?
  • これに間違って近づいていますか/これを行う簡単な方法はありますか?

とにかく、ありがとう。メモとして、私は上記の例をコンパイルしませんでした。私は書いた別のテンプレートクラスを一般化しました(そこに多忙な機能はありません)。間違いがある場合は、お詫びします。

+1

クラスと関数の両方に独自のテンプレート引数があるまで待ちます:) – SergeyA

答えて

2

テンプレートクラスのメンバー関数自体もテンプレートです。このため、必要なテンプレートパラメータ(ケースT)で定義する必要があります。あなたがこれをしなかった場合は、あなたのような関数を書くかもしれません:

void MyClass::memberFunc(T var) {} 

この場合Tは何ですか?このスコープ内にTが定義されていません。

だから人々は何をしていますか?多くのコードベースは、クラスにインラインで関数を定義するだけです。しかし、あなたがしたように、他の人はそれらを分離することを主張します。残念ながら、それは単なる言語の要件です。

+0

私は、関数自体がこのテンプレートクラスの関数のテンプレートであることを理解しています。主な質問は、テンプレート化されたクラスのテンプレートを継承して、各テンプレートに同じテンプレートを持たせる必要がない理由です。 –

+0

@MichaelSmith言葉の言い方が単純であるからです。 C++は非常に明示的です - Tは 'template 'がない定義コンテキストには存在しません。 –

+0

このペタンティック仕様から得られる機能はありますか? –

1

テンプレート以外のすべてのデータとメソッドを持つテンプレート以外の基本クラスを使用することもできます(また、そうする必要があります)。こうすることで、宣言が短くなるだけでなく、コードが短くてもコンパイラによっては基本型の参照を持つことができ、テンプレート以外の型に依存する関数(MyClass<int> a(42); const MyBase& b = a; b.doSomethingUseless();)を呼び出すことができます。

1

テンプレート化されたクラスのメンバー関数には、templateが必要です。そのため、関数自体がテンプレート化されていなくてもクラスのテンプレートを指定できます。これは、クラスがclass MyClassではなく、template<typename T> class MyClass<T>であるためですが、関数はデフォルトでそれを認識しません。このため、コンパイラはクラスのテンプレートパラメータが何であるかを知っている必要があります。実際のクラスと関数を関連付けることができ、正しいバージョンのメンバ関数のthisポインタを作成することができます。クラスのテンプレートパラメータリストを使用します。

これは、テンプレートが生コードではなく、コードの青写真であり、コンパイラがインスタンス化やその他の方法で使用するたびに実際のコードを作成するために必要です。このため

template<typename T> class MyClass {}; 

// ... 

MyClass<int> mci; // Compiler creates class "MyClass_int". 
MyClass<bool> mcb; // Compiler creates class "MyClass_bool". 

コンパイラはあまりにも、コードの青写真としてそれらを使用するために知っているように、メンバ関数も、テンプレートする必要があります。

void MyClass::myFunc() {} 
// Compiler thinks this explicitly belongs to class "MyClass". 
// Can't be used with MyClass_int or MyClass_bool. 

template<typename T> 
void MyClass<T>::myFunc() {} 
// Compiler knows this belongs to class template "MyClass<T>". 
// Can be turned into MyClass_int::myFunc() or MyClass_bool::myFunc(). 

通常、テンプレートパラメータリストは、クラス内で定義されたメンバ関数が明示的に指定せずにテンプレートを使用することを可能にするクラスの範囲の全体に対して定義されています。関数はクラス外で定義されている場合

template<typename T> 
class MyClass { 
    public: 
    // Every function in here is implicitly "template<typename T>". 

    void myInternalFunc(T t) {} 
}; 

、しかし、その後、彼らはもはや暗黙のテンプレートパラメータリストへのアクセスを持っていない、とそれを手動で指定する必要があります。このテンプレートのパラメータリストがあることを

template<typename T> 
void MyClass<T>::myExternalFunc(T t) {} 

注ません機能のが、クラスの。これは、関数もテンプレート化されている場合は、別のテンプレートパラメータリストを必要とすることを意味します。まったく正直なところでは、まあまあです。要するに

template<typename T> 
class MyClass { 
    template<typename U> 
    void myTemplatedFunc(U u); 
} 

template<typename T> 
template<typename U> 
void MyClass<T>::myTemplatedFunc(U u) {} 
// Class is:  template<typename T> MyClass<T>. 
// Function is: template<typename U> myTemplatedFunc(U u). 

:それはない機能のテンプレートパラメータリストは、それはコンパイラがクラスに機能を一致させることができ、そしてその機能がで行動できることとなるように使用クラスのテンプレートパラメータリスト、ですクラスのテンプレートパラメータとの関係(戻り値の型としてテンプレートパラメータを持つ、またはパラメータ型として1をとるなど)関数の定義がクラスのスコープ内に含まれていない場合は、関数がクラスのスコープの外にあるクラスのテンプレートパラメータリストを本質的に見ることができないので必要です。