template <typename T, T b, uint32_t e>
struct pow : std::integral_constant<decltype(b * 1), b * pow<T, b, e - 1>::value> {};
template <typename T, T b>
struct pow<T, b, 0> : std::integral_constant<decltype(b * 1), T(1)> {};
template <uint32_t e>
using pow_two_with_exp = pow<uint64_t, 2, e>;
template<size_t N, size_t exp>
struct SizeOfBits {
static uint32_t value = (N / pow_two_with_exp<exp>::value) == 0 ? exp:SizeOfBits<N,exp+1>::value;
};
这个meta program用来计算N占用多少个bit表示。
乍看起来没有什么问题,因为对于<N,exp>,计算value时:如果\(2^{exp}>N\)时, 可以得知使用exp位可以表示N;否则测试<N,exp+1>
不过这段代码实际的问题是: 1.条件运算符会实例化所有的分支; 2.使用了::
运算符访问类中的成员会促使类的所有成员被实例化。
可以看到这段代码会导致编译期模板递归超过限制
所以,可以将模板改写成这样:
template<size_t N, size_t exp=0>
struct SizeOfBits {
static constexpr uint32_t value = IfThenElse<exp,SizeOfBits<N,exp+1>,(N / pow_two_with_exp<exp>::value) == 0>::value;
};
template <size_t A, typename B>
struct IfThenElse<A,B,true>{
static constexpr size_t value = A;
};
template <size_t A, typename B>
struct IfThenElse<A,B,false>{
static constexpr decltype(B::value) value = B::value;
};
这段代码的主要修改是使用了IfThenElse
这可以使在计算规模为<N,exp>的SizeOfBits::value时,只实例化一个分支(特化true或者特化false,模板的on demand实例化,见complete guide 1st edition chapter10)
此外,complete guide中还提及了一种归纳变量的方法,以使meta programm更像从递归改为迭代的设计:
标签:struct,实例,pow,value,program,meta,template,exp From: https://www.cnblogs.com/ijpq/p/17557986.html