template<class T, class Enable = void>
class Test {
public:
Test() {
std::cout << "normal template" << std::endl;
}
};
template<class T>
class Test<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
public:
Test() {
std::cout << "is_floating_point" << std::endl;
}
};
int main()
{
auto a1 = std::make_shared<Test<int>>();
auto a2 = std::make_shared<Test<float>>();
return 1;
}
当用float实例化Test的时候(Test<float>)enable_if的type会是什么类型?
先看std::is_floating_point<T>::value是什么。
文件在:D:\DevTools\VS2017\VC\Tools\MSVC\14.16.27023\include\xtr1common
template<class _Ty>
struct is_floating_point
: _Is_floating_point<remove_cv_t<_Ty>>::type
{ // determine whether _Ty is floating point
};
// STRUCT TEMPLATE _Is_floating_point
template<class _Ty>
struct _Is_floating_point
: false_type
{ // determine whether _Ty is floating point
};
_Is_floating_point有关于float的特化版本:
template<>
struct _Is_floating_point<float>
: true_type
{ // determine whether _Ty is floating point
};
// ALIAS TEMPLATE bool_constant
template<bool _Val>
using bool_constant = integral_constant<bool, _Val>;
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
integral_constant的定义:
注意看,这个类里面会定义一个static的value。如果_Ty类型是bool,那么这个value将会是true,或者false。
// STRUCT TEMPLATE integral_constant
template<class _Ty,
_Ty _Val>
struct integral_constant
{ // convenient template for integral constant types
static constexpr _Ty value = _Val;
using value_type = _Ty;
using type = integral_constant;
constexpr operator value_type() const noexcept
{ // return stored value
return (value);
}
_NODISCARD constexpr value_type operator()() const noexcept
{ // return stored value
return (value);
}
};
注意看integral_constant的模板参数。_Ty是类型,_Val是用这个类型定义的值。大概就是类似于:
integral_constant<bool, true>,或者integral_constant<bool, false>
integral_constant<int, 5>
所以,_Is_floating_point<remove_cv_t<float>>::type应该就是integral_constant<bool,true>。
而,std::is_floating_point<float>::value就是integral_constant<bool,true>的第二个类型,也就是true。
继承关系:
struct is_floating_point : _Is_floating_point<remove_cv_t<float>>::type
而:_Is_floating_point : integral_constant<bool, true>
观察到在integral_constant的定义里:
using type = integral_constant;
以及:static constexpr _Ty value = _Val;
所以,_Is_floating_point<remove_cv_t<float>>::type就是integral_constant<bool, true> ?
std::is_floating_point<float>::value就是true,毕竟float的特化版本,继承自true_type 。
那么std::is_floating_point<float>::value推导出来就是true
所以,std::enable_if<true>::type是什么呢
看看enable_if的定义:
// STRUCT TEMPLATE enable_if
template<bool _Test,
class _Ty = void>
struct enable_if
{ // type is undefined for assumed !_Test
};
template<class _Ty>
struct enable_if<true, _Ty>
{ // type is _Ty for _Test
using type = _Ty;
};
template<bool _Test,
class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;
匹配到了泛化版本,所以它的类型就是void。用代码可以验证,等于1:
if (1== std::is_void<std::enable_if<true>::type>::value)
{
int i = 0;
i++;
}
为什么不是匹配成enable_if<true,true>呢。如果是这样的话,内部的type就变成using type=true,貌似是不合理的。
想推导出enable_if里的type,得像这样enable_if<true, float>
比如:
void main()
{
std::enable_if<true, float>::type val = 10.0;
std::cout<<val<<std::endl;
}
打印结果应该是:10.0