1.9 模板的控制结构

IF语句

这里可以拿最开始的那个例子。也就是通过if/else实现控制语句。

#include <iostream>
template<bool value, typename If, typename Then>
struct IF {
typedef If type;
};
template<typename If, typename Then>
struct IF<false, If, Then> {
typedef Then type;
};
struct IfClass {
void print() {
std::cout << "IfClass" << std::endl;
}
};
struct ThenClass {
void print() {
std::cout << "ThenClass" << std::endl;
}
};
int main(void) {
IF<true, IfClass, ThenClass>::type x;
x.print();
IF<false, IfClass, ThenClass>::type y;
y.print();
return 0;
}

自定义数据类型

const int len = 4;
typedef IF<sizeof(long long)==len, long long, void>::type long_long_or_void_t;
typedef IF<sizeof(long)==len, long, long_long_or_void_t>::type long_or_llong_void_t;
typedef IF<sizeof(int)==len, int, long_or_llong_void_t>::type int_long_llong_void_t;
typedef IF<sizeof(short)==len, short, int_long_llong_void_t>::type short_int_long_llong_void_t;
typedef short_int_long_llong_void_t int32_t;

这里实际上就是想定义一个完全4bytes的整数类型。

如果嵌套一点,就是

const int len = 4;
typedef
IF_<sizeof(short)==len, short,
IF_<sizeof(int)==len, int,
IF_<sizeof(long)==len, long,
IF_<sizeof(long long)==len, long long,
void>::reType>::reType>::reType>::reType
int32_t; // 定义一个指定字节数的类型
std::cout << sizeof(int32_t) << std::endl;

WHILE语句

通过模板,也可以实现一个WHILE语句。

// cond需要有value/type
// statement需要有next
template<template<typename> class cond, typename statement>
struct WHILE {
struct STOP {
typedef statement type;
};
typedef typename
IF<cond<statement>::value,
WHILE<cond, typename statement::next>,
STOP
>::type::type type;
};

比如下面这个程序就是用来求解1^x + 2^x + 3^x + ... + n^x。代码中用e表示x注意,不是自然对数的那个e

#include <iostream>
template<bool cond, typename If, typename Then>
struct IF {
typedef If type;
};
template<typename If, typename Then>
struct IF<false, If, Then> {
typedef Then type;
};
// cond需要有value/type
// statement需要有next
template<template<typename> class cond, typename statement>
struct WHILE {
struct STOP {
typedef statement type;
};
typedef typename
IF<cond<statement>::value,
WHILE<cond, typename statement::next>,
STOP
>::type::type type;
};
// 计算 1^e+2^e+...+n^e
template<int n, int e>
struct sum_pow {
// pow是取x^e
template<int x>
struct pow {
// p^q的求解
template<int p, int q>
struct pow_q {
static constexpr int value = p * pow_q<p,q-1>::value;
};
template<int p>
struct pow_q<p, 0> {
static constexpr int value = 1;
};
static constexpr int value = pow_q<x,e>::value;
};
template<typename statement>
struct cond {
static constexpr bool value = statement::iter <= n;
typedef statement type;
};
template<int i, int sum>
struct statement {
typedef statement<i+1, sum+pow<i>::value> next;
static constexpr int iter = i;
static constexpr int value = sum;
};
static constexpr int value = WHILE<cond, statement<1,0>>::type::value;
};
int main(void) {
// 1^2 + 2^2 + ... + 10^2
std::cout << sum_pow<10,2>::value << std::endl;
return 0;
}

有趣的编译错误

这个编译错误是在无意中写错程序发现的。那就是利用WHILE循环来求最大公约数。

#include <iostream>
template<bool cond, typename If, typename Then>
struct IF {
typedef If type;
};
template<typename If, typename Then>
struct IF<false, If, Then> {
typedef Then type;
};
// cond has type/value
// statement has next
template<template <typename> class cond, typename statement>
struct WHILE {
struct STOP {
typedef statement type;
};
typedef typename IF<
cond<statement>::value,
WHILE<cond, typename statement::next>,
STOP
>::type::type type;
// 注意:这里有两层type,
// 第一层是IF<>::type,比如递归结束时,定位到STOP
// 第二层是通过剥开STOP,通过STOP拿到最后的类型=STOP::type
};
// Test GCD while循环
/*
* a,b
* while (b) {
* temp = b;
* b = a % b;
* a = b;
* }
*/
template<int a, int b>
struct GCD {
template<typename statement>
struct cond {
static constexpr bool value = statement::i != 0;
};
template<int x, int y>
struct statement {
typedef statement<y, x%y> next;
static constexpr int i = x%y;
static constexpr int value = y;
// 注意:i = y; value = x % y会导致编译通不过
// 这里一定要注意,就是防止出现
// x % 0 的情况
// 由于当i = y, value = x % y的时候无法避免这种情况,
// 报错信息就特别奇怪
// non-type template argument is not a constant expression
// division by zero -> 这里才是关键
// 如果给的值是statement<10, 5>
// -> typedef statement<5, 0> next;
// -> i = 5,
// -> value = 0;
// WHILE里面会发现i = 5,于是还可以展开statement<5,0>
// -> typedef statement<0,5%0> next; <-- 这里也就报错了。
};
static const int value = WHILE<cond, statement<a,b>>::type::value;
};
int main(void) {
std::cout << Sum<100>::value << std::endl;
std::cout << PowSum<10,2>::value << std::endl;
std::cout << GCD<10, 5>::value << std::endl;
return 0;
}

一定要注意程序中的注释:

// 注意:i = y; value = x % y会导致编译通不过
// 这里一定要注意,就是防止出现
// x % 0 的情况
// 由于当i = y, value = x % y的时候无法避免这种情况,
// 报错信息就特别奇怪
// non-type template argument is not a constant expression
// division by zero -> 这里才是关键
// 如果给的值是statement<10, 5>
// -> typedef statement<5, 0> next;
// -> i = 5,
// -> value = 0;
// WHILE里面会发现i = 5,于是还可以展开statement<5,0>
// -> typedef statement<0,5%0> next; <-- 这里也就报错了。