注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

一路

To find the final symmetry & beauty

 
 
 

日志

 
 
 
 

模板元编程学习笔记一,数值计算[原创]  

2011-02-05 14:41:30|  分类: c++学习笔记 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    元编程的英文是metaprogramming,其前面的meta之意是高一层(a level higher)意思就是比原生的编程高出一层,这是什么意思呢?可以这么理解,比如老师,学生都从老师处学得东西。但是一个国家的教育水平真正的希望是在老师本身吗?其实不是的,真正的决定作用应该是老师的老师,比老师本身更高一层的上一级的教育,师范院校,绝大部分老师都要来自那里,那里的教育水平可以决定整个国家的综合教育水平。与之同理,元编程就是编写生成程序的程序,这种元编程的思想不是C++模板中原创的,在程序语言的早期就有着这种思想,比如编译器本身就是一个生成程序的程序,机器码和汇编代码就是原始的编程语言,而编译器给编程加上一层抽象,用高级语言编写程序比用机器语言和汇编代码方便宜多了,而且程序有很强的可维护性、可扩展性、可移植性等很很多优点。而C++中的模板元也是这种思想,但是高级语言的代码生成程序并没有低级语言那么简单,在没有模板的C语言中被广泛应用的就是宏,但是宏严格来说并不是C语言本身的一部分,因为它是不受编译器检查的,这使得复杂的宏难以调试和维护,而C++模板的特点就与宏不一样,它本身是语言的一部分,其应用会受到编译器的严格检查,这使得模板的应用十分安全而且易于使用,不会像宏一样产生诡异的难以调试的BUG.但是现在宏的地位还是不可替代的,但是语言源代码中的宏的数量可以大大减少了,如果模板与宏配合使用,功能将更加强大。

    这里介绍几个数值计算的例子,数值计算是模板元编程中最为简单和易于理解的,就从这里入手吧。

  1. 计算二进制表示的十进制,对于C/C++语言本身就有对于16进制8进制与10进制的转换,它们可以在编译期进行运算,之后把代码中的表示的字串转化为二进制的数字存储在编译后的代码中,但是却没有原生的二进制的转换功能。虽然可以人手工转化为十六进制之后存储,但是有时操作不便也易出错,但是有了强大的模板构造这样一个编译期计算的功能也不是难事。如下代码:

template<unsigned long N>

class binary

{

    public:

        static unsigned long const value = binary<N/10>::value<<1|N%10;

    //algorithm

    //compute the last digit and make or operation with other digits computed by the N/10 shifted left by one.

};

template<>

class binary<0>

{

    public:

        static unsigned long const value = 0;

};

算法本身十分简单,主要是模版元部分。却定类型的模板的特化类型只能是整型常量或是编译期常指针(最新的C++标准可能引入新的支持类型,比如浮点数)。而类的静态整型常量可以在定义时初始化为常量,这样就可以把模板特化常量传递给类。而类常量是可以对其它类进行依赖的,这样就可以构造递归过程。递归的终止条件通过特化模板来确定,这样就可以在编译期通过模板构造完整的递归函数,以计算编译期常量。由于是编译期计算,不会对运行时系统有任何性能影响,因此功能十分强大灵活。

下面有几个类似的实现代码,以供参考:

 

//written by saturnman

//meta_numeric.cpp

#include<iostream>

 

//1. binary representation

//compile-time algorithm

template<unsigned long N>

class binary

{

    public:

        static unsigned long const value = binary<N/10>::value<<1|N%10;

    //algorithm

    //compute the last digit and make or operation with other digits computed by the N/10 shifted left by one.

};

template<>

class binary<0>

{

    public:

        static unsigned long const value = 0;

};

//run-time algorithm

unsigned long binary_to_decimal(unsigned long input)

{

    if(input==0)

    {

        return 0;

    }

    return binary_to_decimal(input/10)<<1 | input%10;

}

//2. hanoi tower steps computation

template<unsigned long N>

class hanoi

{

    public:

        static unsigned long const value = 2*hanoi<N-1>::value+1;

};

template<>

class hanoi<1>

{

    public:

    static unsigned long const value = 1;

};

//3. Fibonacci Number

template<unsigned long N>

class fibonacci

{

    public:

        static unsigned long const value=fibonacci<N-1>::value+fibonacci<N-2>::value;

};

template<>

class fibonacci<0>

{

    public:

        static unsigned long const value = 1;

};

template<>

class fibonacci<1>

{

    public:

        static unsigned long const value = 1;

};

//main entry function

int main()

{

    //binary representation demo.

    std::cout<<"compile-time computed. dec:"<<binary<10010110>::value<<std::endl;

    std::cout<<"run-time computed. dec:"<<binary_to_decimal(10010110)<<std::endl;

    //hanoi tower steps computation

    std::cout<<"When move 7 plates we need "<<hanoi<10>::value<<" movements"<<std::endl;

    //Fibonacci number computation

    std::cout<<"The 10th Fibonacci number is "<<fibonacci<10>::value<<std::endl;

    return 0;

}

 

Ref:

<<C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond>>

 

  评论这张
 
阅读(1061)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017