2012-04-23 16 views
16

考える:部分特殊

struct A 
{ 
    virtual bool what() = 0; 
}; 

template<typename T, typename Q> 
struct B : public A 
{ 
    virtual bool what(); 
}; 

私は部分的に似whatを専門にしたい:(

template<typename T, typename Q> 
bool B<T, Q>::what() 
{ 
    return true; 
} 

template<typename Q> 
bool B<float, Q>::what() 
{ 
    return false; 
} 

しかし、これが不可能であることが表示されますが、それはCであります++ 11?)私はSFINAEを試しました。

template<typename T> 
typename std::enable_if<std::is_same<T, float>::value, bool>::type B<T>::what() 
{ 
    return true; 
} 

template<typename T> 
typename std::enable_if<!std::is_same<T, float>::value, bool>::type B<T>::what() 
{ 
    return false; 
} 

これも機能しませんが、私はなぜ誰もしませんか?だから私はthis threadを発見してしまった:

template<typename T, typename Q> 
struct B : public A 
{ 
    virtual bool what() 
    { 
     return whatimpl(std::is_same<T, float>()); 
    } 

    bool whatimpl(std::false_type) 
    { 
     return false; 
    } 

    bool whatimpl(std::true_type) 
    { 
     return true; 
    } 
}; 

この最終的な解決策は動作しますが、なぜenable_if技術の仕事をしないのですか?私はまた、私がまだ遭遇していないよりきれいな答えの提案に非常にオープンです。 、what()と呼ばれ、実際に仕事の公平なビットをしていない私の本当のユースケースでは、と私は、ユーザー定義型に「特化」したいと思う -

は、私はできるだけ私の例を簡略化しないfloat

+1

@Nawaz私はそれを認識しましたが、これは私が何をしようとしているかを示す単純なケースです:)記事の最後の行を読んでください。 – David

+0

_what_は、A :: what()をオーバーライドするためのテンプレートメソッドではありません。クラステンプレートBの単一の非テンプレートメソッドでなければなりません。テンプレート以外のメソッドを特化することはできません。enable_ifも他のテクニックも使用できません。しかし、あなたはクラスB全体を特殊化することができます – user396672

+0

@ user396672なぜ、これは機能しますか(部分的なものではなく完全な特殊化): 'template <> bool B :: what() { return false; } ' – David

答えて

7

部分特殊化が明示的にのみ、クラステンプレートのための標準によって許可されているために

それを変更しません明示的な特殊化のみが許可されます。

14.7(3)と言う:

明示的な特殊機能テンプレート、クラステンプレート、クラス テンプレートまたはメンバテンプレートのメンバーに対して宣言されてもよいです。明示的な専門化宣言は、テンプレート<>によって導入されています。

ので

template<typename T> 

で始まる任意の定義は、クラステンプレートの特殊化のメンバーのために許可され構文ではありません。ここで実際にどちらのオーバーロードや専門分野は、(オーバーロードの解決のための候補関数のセットを定義しながら、または適切な専門を選ぶ間SFINAE作品)があるので

は、[編集]

はSFINAEの試みについては、それが失敗しました。どのような()がクラステンプレートの単一のメソッドとして宣言され、単一の定義を有するべきであり、この定義は、形状を有していなければならない:

template<typename T, typename Q> 
B<T,Q>:: bool what(){...} 

または明示的に、クラスBの特定のインスタンス化のために特化されてもよい。

template<> 
B<SomeParticularTypeT,SomeParticularTypeTypeQ>:: bool what(){...} 

他のフォームは構文上無効です。したがって、SFINAEはサポートできません。

+0

ありがとう、これは最初に失敗した試行を説明します。 SFINAE試行の洞察? – David

+0

@Dave:SFINAEは "SPECIALIZATIONの失敗はエラーではありません"という略語なので、_specialization_のための特定のテクニックです。テンプレートで始まって...あなたは、ちょっと複雑な方法を使ってクラステンプレートのメソッドを部分的に特殊化しようとしました。 – user396672

+0

@Dave :: ...またはテンプレートは、クラステンプレートB のメソッド_definition_を開始することができますが、この場合、それはまったく特殊化ではなく、SFINAEも機能しません。 – user396672

2

理由だけではなく、クラステンプレートのメンバーについて(14.5.5クラステンプレート部分的な特殊化を参照)。..

template<typename T, typename Q> 
struct B : public A 
{ 
    bool what() 
    { 
     return false; //Or whatever the default is... 
    } 
}; 

template<typename Q> 
struct B<float, Q> : public A 
{ 
    bool what() 
    { 
     return true; 
    } 
}; 
+3

Bは巨大クラスなので、 'what()'の各特殊化のために巨大クラスを15回コピー&ペーストしたくないです。 – David

+0

@Dave:...あなたは中間の巨大クラスから継承することができますが、 )オーバーライドします。 – user396672

+0

@ user396672私は継承に余分なクラスを追加した場合にのみそれを行うことができました.Aはテンプレート化されていないので、Bの機能は本当にそこに配置できませんでした。余分なクラスはテンプレート化され、AとBの間に移動する必要があります。これは、これを処理するための他のテクニックに応答する別の答えとして書くことができます – David

関連する問題