2011-06-27 13 views
2

テンプレートパラメータがいくつかのクラスのインスタンスであるかどうかによっていくつかのコードを生成するテンプレートを書く必要があります。テンプレートはすべてのクラスに対して生成できますが、クラスが他のクラスのサブクラスである場合にのみ、コードを実行する必要があります。クラスインスタンスなしのC++テンプレートのクラスを確認する

問題は、実装する必要がある関数はクラスのインスタンスを受け取らないため、既知の唯一のものはクラス名です。だから、それはいくつかの説明を追加するオブジェクト

template<T> 
class A 
{ 
    void somefunction(void) 
    { 
    if (T instanceof Foo) then ... 
    else ... 
    } 
} 

のインスタンスを要求としてのdynamic_castでこれを達成することは不可能である

class X: public Foo {}; 
class Y {}; 

class A<X> {} // special logic is generated 
class A<Y> {} // special logic is NOT generated 
+0

あなたはテンプレートでFooのインスタンスのための特別な動作が必要な場合は、I tテンプレートクラスは必要ありません。テンプレートメソッドパターンが必要です。 –

+1

@Miguel Angel:実行時の多形性が必要な場合は**必要です。 –

答えて

3

あなたはテンプレートの特殊化を使用するか、後押し:: is_base_ofを独自の特色を書くboost traits library から、あるいは、もちろん、しかし、あなたはまだテンプレートをマスターしていないため、いけないことができます。特殊化を使用し

、あなたは

template<T> 
class A 
{ 
    void somefunction() { 
    // generic version 
    } 
}; 
template<> 
class A <Foo> 
{ 
    void somefunction() { 
    // foo version 
    } 
}; 

いつものように、私はVandevoorde/Josuttis氏 "C++テンプレート:完全ガイド" をお勧めしてみましょうことができます。多くのうち一つだけmemberfunctionは特殊なする必要があるため、あなたがコードの膨張を恐れる場合

、あなたはまだその機能を外部委託することができます

template <typename T> struct somefunction_helper { 
    static void thatfunction() { 
     // generic form 
    } 
}; 
template <> struct somefunction_helper<Foo> { 
    static void thatfunction() { 
     // Foo form 
    } 
}; 

template<T> 
class A 
{ 
    void somefunction() { 
    somefunction_helper<T>::thatfunction(); 
    } 
}; 
+0

is_base_ofは有望そうです – Boris

1

どちらかAを専門またはいくつかの無料の機能にsomeFunction()メンバ関数テンプレートの作業を委任Tを(完全に)専門にするテンプレート。

+0

上記と同じコメント - Fooは基本クラスのみです。テンプレートはパラメータとしてインスタンス化されません – Boris

2

これは、テンプレートの特殊化のためのものです。彼らは書くのがより難しいですが、それはあなたがそれらで何をするかです。例:

template<T> class A 
{ 
    void somefunction(void) { 
     ...//default for any object type. 
    } 
}; 

template<> class A<Foo> 
{ 
    void somefunction(void) { 
     ...//specific to the type Foo. 
    } 
}; 

はい、余分な作業が必要です。あなたが望むようにこれを行うためのいくつかのテンプレートメタプログラミング方法がありますが、他の誰かがそれらを説明しなければなりません。

+0

Fooは基本クラスであり、テンプレートとしてインスタンス化されません。 – Boris

+0

@Boris:あなたのコメントは意味をなさない。 'A'がインスタンス化されない場合、メンバー関数は決して呼び出されません。 _If_ 'A'が実際に使用されていれば、' T'の実際のパラメータが存在し、これは動作します。 (Nicolも私の解決法も、 'T'型のオブジェクトをインスタンス化する必要はないことに注意してください) – sbi

+0

クラスX:Foo {}、クラスY {}、AはパラメータとしてXとYだけをインスタンス化しますが、Foo自体はインスタンス化しませんおよびA ) - クラスXでは、特別なロジックを呼び出す必要があります。 – Boris

-1

編集#2 - 作業例を参照してください。これはテンプレートの特殊化(コンパイル時に発生する)の実行時に相当し、RTTIを有効にする必要があることに注意してください。

#include <iostream> 
#include <typeinfo> 
using namespace std; 

class Foo {}; 
class X: public Foo {}; 
class Y {}; 

template<typename T> class A { 
public: 
    void somefunction() 
    { 
    if (typeid(T) == typeid(X)) { 
     cout << "X specific logic happening" << endl; 
    } 
    else { 
     cout << "Default behavior" << endl; 
    } 
    } 
}; 

int main() { 
    A<X> ax; 
    A<Y> ay; 
    ax.somefunction(); // prints "X specific logic happening" 
    ay.somefunction(); // prints "Default behavior" 
} 

typeidは、テンプレートパラメータのタイプを抽出するためにテンプレートを使用することができる - 以下に記載のように:から撮影

// expre_typeid_Operator_3.cpp 
// compile with: /c 
#include <typeinfo> 
template < typename T > 
T max(T arg1, T arg2) { 
    cout << typeid(T).name() << "s compared." << endl; 
    return (arg1 > arg2 ? arg1 : arg2); 
} 

http://msdn.microsoft.com/en-us/library/fyf39xec(v=vs.80).aspx

注値ことname()は実装定義です。

+0

'name()'の戻り値は実装定義であり、その内容に依存してはならない。 –

+0

Ok - 私は 'name()'の移植性についてのノートを含めるように答えを更新しています – Nick

+0

これを手で問題を解決するためにどのくらい正確に適用できますか? – sbi

0

テンプレートパラメータがしか導出されますので、専門は動作しませんので、 Fooから、別の答えが言ったことを使用します。それは既にC++ 0xのの部分をサポートしている場合is_base_of、ブーストまたは標準ライブラリのいずれかから:

#include <type_traits> // C++0x 

class Foo{}; 

template<class T> 
class A{ 
    void specialOnFoo(){ 
    // dispatch the call 
    specialOnFoo(std::is_base_of<T, Foo>::type()); 
    } 

    void specialOnFoo(std::true_type){ 
    // handle Foo case 
    } 

    void specialOnFoo(std::false_type){ 
    // non-Foo case 
    } 
}; 
関連する問題