meta program - 实例化
EXAMPLE ONE
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更像从递归改为迭代的设计:
EXAMPLE TWO
第一个是基模板定义,第二个是全特化,第三个是偏特化,第四个是全特化。
EXAMPLE THREE
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <type_traits>
#include <vector>
using namespace std;
struct bracket_word;
struct word;
template <typename A, typename B, bool cond>
struct ifThenElse;
template <typename A, typename B>
struct ifThenElse<A, B, true> {
static constexpr bool value = A::value;
};
template <typename A, typename B>
struct ifThenElse<A, B, false> {
static constexpr bool value = B::value;
};
template <typename... TYPE_VAR>
struct isWord;
template <>
struct isWord<> : integral_constant<bool, true> {};
template <typename TYPE, typename... TYPE_VAR>
struct isWord<TYPE, TYPE_VAR...>
: integral_constant<
bool,
is_same<TYPE, word>::value &&
ifThenElse<isWord<TYPE_VAR...>, integral_constant<bool, true>,
(sizeof...(TYPE_VAR) > 0)>::value> {};
int main() {
static_assert(isWord<>::value, "Expected true");
static_assert(isWord<word>::value, "Expected true");
static_assert(isWord<word, word>::value, "Expected true");
static_assert(isWord<word, bracket_word>::value == false, "");
static_assert(isWord<bracket_word>::value == false, "");
}
本文来自博客园,作者:ijpq,转载请注明原文链接:https://www.cnblogs.com/ijpq/p/17557986.html