今天在项目中,看到大哥有对使用这个 std::enable_if
,并且正好前段时间有在学习模板的知识,浅谈一下我对 std::enable_if
的理解。
先看实现
这是gcc13.2.0的实现
// Primary template.
/// Define a member typedef @c type only if a boolean constant is true.
template<bool, typename _Tp = void>
struct enable_if
{ };
// Partial specialization for true.
template<typename _Tp>
struct enable_if<true, _Tp>
{ typedef _Tp type; };
template<bool _Cond, typename _Tp = void>
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
此模板主要用于SFINAE,影响重载决议。
#include <type_traits>
template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
void fun(T a){
}
int main(int argc, char* argv[]) {
fun<int>(1); // 正确 1
// fun<double>(1); // 错误 2
fun(1); // 正确 3
// fun(1.0); // 错误 4
return 0;
}
- 1表达式,
T
被推断为int
;匿名typename
中std::enable_if_t<std::is_same_v<T, int>>
T
和int
为同一类型,满足is_same_v
限定,被推断为int
(其实推断为什么不重要,重要是被推断出来了),此时的fun<int>(1)
退到出类型template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
。 - 2表达式,不满足
std::is_same_v<T, int>
,typename enable_if<_Cond, _Tp>::type
为空语句,替换失败,因为没有其他的重载函数,所以编译失败。 - 3、4同1、2
如果加上一个重载,bool
是为了重载用的,没有含义。
template <typename T, typename = std::enable_if_t<std::is_same_v<T, double>>>
void fun(T a, bool = false) {
}
上述的2、4表达式,可以重载到这个函数中,因为SFINAE(推导失败不是错误,而是丢弃特化)丢弃了 void fun(T a){}
的特化,符合 void fun(T a, bool = false)
特化,重载到 void fun(T a, bool = false)
这个函数中。