22

与えられた:

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;
}

これもうまくいきませんが、なぜだかわかりません。だから私はこのスレッドを見つけて、結局:

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()では、whatとは呼ばれず、実際にはかなりの作業を行います。実際には、ではなく、ユーザー定義の型に「特化」したいと思いますfloat

4

3 に答える 3

13

部分的な特殊化は、クラステンプレートに対してのみ、標準で明示的に許可されています(14.5.5クラステンプレートの部分的な特殊化を参照)。

クラステンプレートのメンバーには、明示的な特殊化のみが許可されます。

14.7(3)は言う:

関数テンプレート、クラステンプレート、クラステンプレートのメンバー、またはメンバーテンプレートに対して、明示的な特殊化を宣言できます。明示的な特殊化宣言は、template<>によって導入されます。

したがって、で始まる定義

template<typename T>  

クラステンプレート特殊化のメンバーに許可されている構文ではありません。

[編集]

SFINAEの試行に関しては、実際にはオーバーロードもスペシャライゼーションも存在しないため失敗しました(SFINAEは、オーバーロード解決の候補関数のセットを定義している間、または適切なスペシャライゼーションを選択しているときに機能します)。what()は、クラステンプレートの単一のメソッドとして宣言されており、単一の定義を持っている必要があり、この定義は次の形式である必要があります。

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

または、クラスBの特定のインスタンス化に明示的に特化することもできます。

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

他のフォームは構文的に無効であるため、SFINAEは役に立ちません。

于 2012-04-24T08:02:31.677 に答える
1

に変更してみませんか。

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;
   }
}; 
于 2012-04-23T20:01:33.047 に答える
0

ユースケースに応じて考えられる2つの解決策:

  1. 柔軟な実装クラス:メソッドの問題の1つは、型に柔軟性がないことです。真または偽の型にすぎません。この優れたCppConトーク(スライド77)に基づいて、別の実装固有のクラステンプレートに作業を委任することにより、このソリューションを作成しました。このコードはここで確認して実行できます。このメソッドの欠点は、残りのクラスメンバーにアクセスできないことですが、それらを渡すことはできます。
  2. Enable Ifの操作: enable_ifソリューションが機能しなかった理由を完全には理解していませんが、これが私のものであり、機能しています。それはあなたがクラス自体の中で部分的に専門化することを可能にします。

PSここにコードを直接追加しようとしていますが、フォーマットに問題があります。誰かがColiruからフォーマットされたコードを追加するのを手伝ってくれるなら、それは素晴らしいことです。

于 2018-09-18T16:50:29.393 に答える