UML软件工程组织

混沌 in C++ (4)
文前说明:文中涉及到的观点并不是要求你去遵循它,而本文只相当于一篇“科普文章”。其中的关于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

 

版权所有:UML软件工程组织