SFINAEをトリガーする方法はたくさんありますがenable_if
、そのうちの1つにすぎません。初めに:
ワットはstd::enable_if?
それはこれだけです:
template<bool, class T=void> enable_if{ typedef T type; };
template<class T> enable_if<false,T> {};
template<bool b, class T=void> using enable_if_t = typename enable_f<b,T>::type;
アイデアはtypename enable_if<false>::type
エラーにすることです。したがって、それを含むテンプレート宣言はすべてスキップします。
では、これはどのようにして関数の選択をトリガーできるのでしょうか?
機能の無効化
アイデアは、ある部分で宣言を誤ったものにしている:
返品タイプ別
template<class Type>
std::enable_if_t<cond<Type>::value,Return_type> function(Type);
実際のパラメータによる
template<class Type>
return_type function(Type param, std::enable_if_t<cond<Type>::value,int> =0)
テンプレートパラメータによる
template<class Type,
std::enable_if_t<cond<Type>::value,int> =0> //note the space between > and =
return_type function(Type param)
機能の選択
次のようなトリックを使用して、さまざまな代替案をパラメータ化できます。
tempplate<int N> struct ord: ord<N-1>{};
struct ord<0> {};
template<class T, std::enable_if<condition3, int> =0>
retval func(ord<3>, T param) { ... }
template<class T, std::enable_if<condition2, int> =0>
retval func(ord<2>, T param) { ... }
template<class T, std::enable_if<condition1, int> =0>
retval func(ord<1>, T param) { ... }
template<class T> // default one
retval func(ord<0>, T param) { ... }
// THIS WILL BE THE FUCNTION YOU'LL CALL
template<class T>
retval func(T param) { return func(ord<9>{},param); } //any "more than 3 value"
これは、満たされている場合、どれよりも1番目/2番目/3番目/4番目の関数を呼び出します。condition3
condition2
condition1
その他のSFINAEトリガー
コンパイル時の条件の記述は、明示的な特殊化の問題か、評価されていない式の成功/失敗の問題のいずれかです。
例えば:
template<class T, class = void>
struct is_vector: std::false_type {};
template<class X>
struct is_vector<vector<X> >:: std::true_type {};
ですis_vector<int>::value
がfalse
、is_vecttor<vector<int> >::value
_true
または、内省によって、
template<class T>
struct is_container<class T, class = void>: std::false_type {};
template<class T>
struct is_container<T, decltype(
std::begin(std::declval<T>()),
std::end(std::declval<T>()),
std::size(std::declval<T>()),
void(0))>: std::true_type {};
与えられれば、コンパイルすることができis_container<X>::value
ます。true
X x
std::begin(x)
秘訣は、すべての部分式がコンパイル可能である場合にのみ、decltype(...)
実際にはvoid
(演算子は前の式を破棄する)ということです。,
他にも多くの選択肢があります。このすべての間にあなたが何か役に立つものを見つけることができることを願っています。