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>
ます。代替案はありますか?