2012-03-30 28 views
5

オブジェクトの作成を管理するクラスWorldがあります...作成後、afterCreationメソッドが呼び出され、作成されたオブジェクトはエンティティ(例えばMyEntity)私はaddEntityに電話したいと思う。私はオブジェクトが何か他のものだったので、私は何もしません。それはすべての派生クラスのためのユニークなIDを生成するので、 addEntity等、適切なTで呼び出さなければなりません。ここ特定の型から派生した型のテンプレートを特化する方法

は私のソリューションです:

template <int v> 
struct ToType 
{ 
    enum { value = v }; 
}; 

template <typename T> 
void World::afterCreation(T * t) 
{ 
    afterCreation(t, ToType<std::is_base_of<Entity, T>::value>()); 
} 

template <typename T> 
void World::afterCreation(T * t, ToType<true>) 
{ 
    addEntity(t); //here I cant pass Entity *, I need the real type, eg. MyEntity 
} 

template <typename T> 
void World::afterCreation(T * t, ToType<false>) 
{ 

} 

私の質問をされた - でより良い方法を行うことができますか?

ToTypeまたはそれに類するものを除いて、次のコードをどのようにシミュレートできますか?

template <typename T> 
void afterCreation(){/*generic impl*/} 

template <typename T where T is derived from Entity> 
void afterCreation(){/*some specific stuff*/} 
  • タイトルに「特化」のみ、あなたが多型のポインタでこれを行うことができますテンプレートの特殊

答えて

3

はるかに良いにするつもりはないが、あなたはSFINAEを使用することによって間接のいずれかのレベルを削除することができます。

template <typename T> 
typename std::enable_if< std::is_base_of<Entity, T>::value >::type 
World::afterCreation(T * t) 
{ 
    // Derived from Entity 
} 
template <typename T> 
typename std::enable_if< !std::is_base_of<Entity, T>::value >::type 
World::afterCreation(T * t) 
{ 
    // generic 
} 

このしくみを教えてください。コンパイラがafterCreationへの呼び出しを検出すると、どのオーバーロードがであるかを判断しようとします。そのため、それはタイプに一致し、置換を実行しようとします。どちらの場合も、マッチした型(引数から)を取り、式全体に置換を適用します。 enable_ifテンプレートには、最初の引数として渡された値がtrueである場合は内部型typeが含まれます。そうでない場合は、そのような型は含まれません。型の置換中に、オーバーロードの1つが無効な関数シグネチャ(条件が偽であるもの)を生成し、候補セットから削除されます。

1

の問題を解決する必要が私の意図を記載していないことです。

template <typename T> 
void afterCreation(T* x) { 
    T* entity = dynamic_cast<Entity*> x; 

    if (!entity) { 
     // ... generic implementation 
    } else { 
     // ... entity implementation, use "entity" 
    } 
} 

これは(小さな)実行時のオーバーヘッドがあるため、これは最善の解決策ではないかもしれませんが。非常にスマートなコンパイラは、静的解析によってこのオーバーヘッドを取り除くかもしれませんが、コンパイラがこれを選択するかどうかは疑問です。

+0

Eddie Edwards:実行したいオブジェクトのポインタを渡すだけです。 'エンティティx; afterCreation(&x); '。 – orlp

+0

+1、シンプルでポイントに:)実際に問題を解決するのではなく、SFINAEよりはるかに簡単なアプローチで解決します。 Entity'の派生型、つまり、entity-derivedEntityName()のようなものはありません。これは、Entity以外の派生型ではコンパイルできません) –

+0

申し訳ありませんナイトクラッカー申し訳ありません。コンパイラの多くはdynamic_castを削除します。これは、xの型の完全な知識を持っているからです。あるいは、テンプレート化されたソリューションがまったく動作することができると仮定して、少なくとも必要な知識が必要です。 –

関連する問題