触发 SFINAE 的方法有很多,这enable_if
只是其中之一。首先:
Wats 是 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"
如果满足,这将调用第一个/第二个/第三个/第四个函数,而不是没有一个。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
(运算符丢弃先前的表达式)。,
甚至可以有许多其他选择。希望在这一切之间你能找到一些有用的东西。