0

std::enable_ifこのような構造体にカプセル化する素晴らしいアイデアを思いついたとき、関数テンプレートを選択するために SFINAE を使用していました。

template<typename T, typename U>
struct EnableWhenEqual
{
    typedef typename std::enable_if<std::is_same<T, U>::value>::type type;
};

そして、たとえば、このように使用します

template<typename T, typename U, typename Enable = EnableWhenEqual<T,U>::type >
void foo(T&& t, U&& u)
{
    if (std::is_same<T,U>::value)
        std::cout << "OK, overload allowed." << std::endl;
    else
        std::cout << "Bad. Should not compile!" << std::endl;
}

ただし、呼び出しでわかるように、これは機能しません

foo(1,1);     //prints "OK, overload allowed"
foo(1,2.0);   //prints "Bad, should not compile", but obviously does

一方、作成しようとすることによって、

EnableWhenEqual<int,int>();      //compiles
EnableWhenEqual<int,double>();   //does not compile because type does not exist

コンパイラ エラーが発生します (「型は std::enable_if のメンバーではありません」)。

この動作の理由は何ですか? 私の小さな SFINAE の知識から、型推定のエラーがオーバーロードの除外につながると考えていたので、私は尋ねています...?


完全を期すために、上記の問題はテンプレートのエイリアシングを使用して解決できます

template <typename T, typename U>
using EnableWhenEqual = typename std::enable_if<std::is_same<T,U>::value>::type;

テンプレートエイリアスの代わりに構造体を使用する代替手段はありますか?

編集:ここでは、一般的な問題を解決する実装を意味します。例えば、こちら

template<typename T, typename U, bool B, typename C=void>
struct EnableWhenEqual {};

template<typename T, typename U, typename C>
struct EnableWhenEqual<T,U,std::is_same<T,U>::value>
{
    typedef typename C type;
};

部分的な特殊化には単純な識別子が必要なため、うまくいきません。もしそうなら、std::is_same一般的な構造体に置き換えることができCondition<T,U>ます。代替案はありますか?

4

2 に答える 2

5

これでうまくいくはずです:

template<typename T, typename U>
struct EnableWhenEqual : std::enable_if<std::is_same<T, U>::value>
{
};

http://coliru.stacked-crooked.com/a/650202ba3d42d34b

于 2014-09-02T19:37:35.133 に答える
2

別の種類のカプセル化:

template<class T, class U>
using EnableWhenEqual_t = typename std::enable_if< std::is_same<T,U>::value >::type;

template<typename T, typename U, typename Enable = EnableWhenEqual_t<T,U> >
void foo(T&& t, U&& u) {
  if (std::is_same<T,U>::value)
    std::cout << "OK, overload allowed." << std::endl;
  else
    std::cout << "Bad. Should not compile!" << std::endl;
}

テンプレートの VS 処理について質問する場合は、正確な Visual Studio のバージョンを含めてください。VS テンプレートのサポートは非​​常に風変わりです。

于 2014-09-02T20:38:33.327 に答える