文前说明:文中涉及到的观点并不是要求你去遵循它,而本文只相当于一篇“科普文章”。其中的关于template的语法在这里就不过多介绍了。例如,下文中提到的条件,都是要意识到是编译期常量。
C++ template 为我们提供了编译期计算的功能。编译器在处理template时,实际上相当于一个解释器的作用。充分利用template可以提高代码的运行速度,可以降低代码维护的复杂度,还可以为代码提供更具扩展性的能力。下面就尝试一下这样的编程方式。
一、 C++ template替代if/if-else语句
if(条件)
语句1;
else
语句2;
在C++ template中,我们可以这样写
template<bool cond>
struct my_if{};
template<>
struct my_if<true>{
static void go()
{ 语句1; }
};
template<>
struct my_if<false>{
static void go()
{ 语句2; }
};
例如,我们判断两个整数
my_if<(1<5)>::go();
也许你会觉得这个if/if-else的template有点大提小做的感觉,呵呵,继续往下看
二、 将C++ template版的if/if-else扩展成能应付switch的代码
如果你是一个面向对象编程的高手,你肯定不会在你的代码中安置switch这样的代码,你肯定会用通过抽象、继承、多态和接口来完成这个任务。不过现在要换一个思维,用C++
template来实现。其实这里的代码和上面的if/if-else相差无几,但是在用于switch时,也同样能出色地体现出OC原则。
int i;
switch(i)
{
case 值1;
语句1;
break;
case 值2;
语句2;
break;
default:
语句3;
}
下面是C++ template版本
template<int I>
struct my_switch{
static void go(){
语句3;
}
};
template<>
struct my_switch<值1>{
static void go()
{ 语句1; }
};
template<>
struct my_switch <值2>{
static void go()
{ 语句2; }
};
调用就是my_switch<值>::go();
你也许仍然找不出C++ template版本的switch好处,因为它要写更多的代码。不过你现在静下来认真的想一想,你会发现当你为switch插入新的值判断时,你要返回到switch处,而且还要修改内部的代码。而用C++
template却不需要你去关心my_switch到底在哪里定义的。要添加新的值判断时,只需要你自己在一个合适的地方添加值判断的代码。
三、 基于C++ template的数值运算
计算一个常数N的阶乘
template<int N>
struct factorial{
static const int value = N * factorial<N-1>::value;
};
template<>
struct factorial<1>{
static const int value = 1;
};
当这个类模板实例化factorial<N>,就会接着实例化factorial<N-1>,直到实例化fatorial<1>为止。而你只需要实例化自己想要计算的N就行了,后面的一切全由编译器包办。例如我们要输出10的阶乘答案
std::cout<<factorial<10><<std::endl;
四、 借助上面数值计算的方法以产生更实用的代码
是否考虑过得到指针的原型,比如通过int*,得到int。我们可以写出下面的代码
template<typename T>
struct primitive_type{
typedef T value_type;
};
template<typename T>
struct primitive_type<T*>{
typedef T value_type;
};
typedef int* pint;
primitive_type<pint>::value_type obj=5;
std::cout<<obj<<std::endl;
现在可以明确obj不是int*,而是int类型。但是有个缺陷就是但T是int**时却的不到int,而是得到的int*,这并不是我们想要的答案。现在只需要其实稍微对primitive_type的偏特化版本作下简单的修改,就可以满足要求
template<typename T>
struct primitive_type<T*>{
typedef typename primitive_type<T>::value_type value_type;
};
typedef int**** pint;
primitive_type<pint>::value_type obj=5; 这个obj可以确认他是int,而不是int***
//The End
|