关于std::enable_if的理解

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值