c++ std::conditional 惰性求值

值得记录一下,加深了我对模板推导的理解

首先std::conditional不是惰性求值的,在模板元编程里面有时候不能对不正确的参数求值

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
template<ll val>
struct loop : loop<val - 1>
  {
  	using type = integral_constant<ll,-1>;
  };
template<typename T>
struct test
  {
  	using type = typename std::conditional<is_same<T,true_type>::value,
	                                       loop<0>::type,
                                               integral_constant<ll,10>
	   				       >::type;
  };
int main()
  {
  	cout << test<false_type>::type::value;
	return 0;
  }

首先loop<0>是个死循环,这个代码逻辑上是没有问题的,但是因为conditional不是惰性求值的问题,编译器会尝试推导loop<0>的类型
解决办法就是加一个间接层

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
template<ll val>
struct loop : loop<val - 1>
  {
  	using type = integral_constant<ll,-1>;
  };
template<ll val>
struct late
  {
  	using type = typename loop<val>::type;
  };
template<typename T>
struct test
  {
  	using type = typename std::conditional<is_same<T,true_type>::value,
	                                      late<0>,
					      integral_constant<ll,10>
	 	    	         	      >::type::type;
  };
int main()
  {
  	cout << test<false_type>::type::value;
	return 0;
  }

编译器只会推导late这个包装层的类型,这个是可以确定的,注意conditional<,,>::type::type
integral_constant::type指向自己的类型,而late这个包装类的type指向loop<0>
这样就可以实现惰性求值,可以简化一些模板元编程的代码
深入的原理还需要看《c++ Templates》
感觉比较有趣,Stack Overflow中也有这个问题的答案,不过写的比较凌乱,这两个代码一对比,读者应该能清晰的看到这个博文的意义在哪里

posted @ 2021-07-01 16:35  XDU18清欢  阅读(512)  评论(0)    收藏  举报