2010-12-18 9 views
3

何を検索するのかよくわからなかったので、私は可能な限り最善の方法で説明しようとします。 STLでは、std::sethttp://cplusplus.comからテンプレートパラメータとしてクラスまたは関数を持つ

template <class Key, class Compare, class Allocator> class set;

のように定義される:

比較:比較のクラス:コンテナ要素と同じタイプの2つの引数を取り、ブール値を返すクラス。式comp(a、b)はcompがこの比較クラスのオブジェクトであり、aとbがコンテナ [...]の要素です。これは、関数呼び出し演算子を実装するクラスまたは関数へのポインタ [...]のいずれかです。

私はCompareテンプレートパラメータについて話しています。

私は関数呼び出し演算子を実装するクラスであるテンプレートパラメータを持つテンプレートクラスを記述した場合、私はそれを書くことだったのであれば、私は、

template <class T, class Combine> 
class MyClass 
{ 
public: 
    Combine func; 
    MyClass() 
    { 
     func = Combine(); 
    } 
    T do_it(T a, T b) 
    { 
     return func(a, b); 
    } 
}; 

class IntCombine 
{ 
public: 
    int operator() (int a, int b) 
    { 
     return a + b; 
    } 
}; 

//... 
MyClass<int, IntCombine> ob; 
ob.do_it(4, 5); 

を書いたりしたいです2番目のテンプレートパラメータは関数です:

template <class T, T Combine(T, T)> 
class MyClass 
{ 
public: 
    Combine func; 
    MyClass() 
    { 
     func = Combine; 
    } 
    T do_it(T a, T b) 
    { 
     return func(a, b); 
    } 
}; 

int IntCombine(int a, int b) 
{ 
    return a + b; 
} 

//... 
MyClass<int, IntCombine> ob; 
ob.do_it(4, 5); 

ただし、STLでは、どちらの方法でもsetクラスを使用できます。これはどうやって実現されますか?上記のコードは、obの定義の2番目のテンプレートパラメータがそれぞれoperator()を実装するクラスか関数のいずれかである場合にのみ機能しますが、両方とも動作するようにMyClassを書くことはできません。

私の例はかなり役に立たないようです。基本的には、要素を組み合わせることができるコンテナを作成する必要があります。これはSTLコンテナと同じように一般的です。

答えて

0

上記のコードは、私のobの定義における2番目のテンプレートパラメータがoperator()または関数を実装するクラスのいずれかである場合にのみ機能しますが、両方とも動作するようにMyClassを記述することはできません。

はい次のことができます。

template <typename F> 
struct foo { 
    F f; 
    void call() { 
     f(); 
    } 
}; 

void function() { 
    std::cout << "function called" << std::endl; 
} 

int main() { 
    foo<void(*)()> a = { function }; 
    a.call(); 
} 

これはまさにexample of the std::set constructorに従っています。重要な点は、関数ポインタを使用している場合、テンプレートパラメータがではなく、その関数ポインタがタイプ(ここではvoid (*)())のであることです。実際の関数ポインタは個別に格納する必要があります。

+0

実際にテンプレートで関数ポインタを渡すことも可能です。 – Puppy

+0

@DeadMG:正しいですが、テンプレートパラメータに(* pointer *ではなく)関数を渡す場合と同様に、これは上記のシグネチャでは機能しません。つまり、 'typename'の代わりに関数ポインタテンプレート引数リストに入力します。 –

+0

テンプレート 'を実行するのは完全に合法です。 – Puppy