混沌 IN C++::Template Metaprograms

难度:

 

文前说明:文中涉及到的观点并不是要求你去遵循它,而本文只相当于一篇“科普文章”。其中的关于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-elsetemplate有点大提小做的感觉,呵呵,继续往下看

 

二、  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类型。但是有个缺陷就是但Tint**时却的不到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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值