正文

traits编程技法和模板元编程基础2008-01-30 14:16:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/rickone/32496.html

分享到:

哈,我发现我终于成为标题党啦,全拿一些powerful的词做标题,骗点击率。说实话,在学校写论文全是有目的的,保研,升学,拿学位等,其实写的都是些什么哦,这里抄那里抄,能把专家组唬到就是好文章,写博客不同,我爱写就写,你当我是炫耀也好,轻浮也罢,都不放在耳边。 C++语言其实一点都不强大,强大的是那些使用C++的牛人们! 1,traits技法 这个说法我是从《STL源码剖析》中看到的,但是真正明白还是后来慢慢想才明白的。traits的意思是‘特性’,《Eff C++》里说将类的设计视为类型的设计,把class的设计当成type的设计,C++提供了一种无限的可能,使你可以不断的设计新的类型,从而使语言本身更强大。面对各种class,语言本身也没有提供太多的东西去描述‘特性’,有些知识是一开始不可预料的,所以没办法定义,比如,可拷贝性。如果语言定义一开始就很注重这个概念,那可能会多一个关键字操作符,譬如copiable()。在C的时代有sizeof(),在C++的时候有typeof,开玩笑,是typeid,但是这是在运行时,但是有了traits技法,这个是不必要的,将这些事情给编译器在编译期运行,会给运行程序带来更多的效率。我们知道型别本身这个信息也可以看成是基本的‘特性’。 在编译期做‘特性’检查,就是做类似这样的事情: template<typename T>void doSomething(T& t){     if(t 具有某种特性)    {      做一些事情    }    else    {      做另一些事情    }} 在运行期做,可以这样设计T class T{public:   T() : copiable(true) {}   virtual ~T() {}    bool copiable;}; 这样做很糟糕,第一,‘特性’本身做为数据存储起来,那就会存在各个对象内,浪费空间,如果用静态数据,也很麻烦,第二,在doSomething()里要多做一次判断,浪费时间,浪费运行期时间。总之就是,浪费运行期的时间和空间。 将这些事移到编译期做,编译期能做些什么?类型推导。同时还需要C++一个本身的功能,就是偏特化。在运行期的数据、信息,我们转化为类型,用类来表示这些信息,比如特性。 首先,定义表示‘真’和‘假’的类: struct _true_type{};struct _false_type{}; 它们对应于运行期的值,true和false; 再将特性定义成内嵌类型的typedef: class T{   typedef _true_type copiable;}; 然后在doSomething()里做类型推导: template<typename T>void doSomething(T& t){  typedef typename T::copiable copiable;  doSomething_aux(t,copiable());} 真正在推导的是另一个重载的函数doSomething_aux,如下定义 template<typename T>void doSomething_aux(T& t,_true_type){  当可以拷贝时做的事情} template<typename T>void doSomething_aux(T& t,_false_type){ 当不可以拷贝时做的事情} 这样就大功告成,似乎只用到了重载函数,但是这样的特性方法不能推广到基本类型,比如,T是int型,那在doSomething里就出错了,int::copiable没有定义,当然啦,你不可能把这个特性加进去。 再加一层封装可以解决这个问题: template<typename T>struct type_traits{  typedef T::copiable copiable;}; 然后改写doSomething: template<typename T>void doSomething(T& t){  typedef typename type_traits<T>::copiable copiable;  doSomething_aux(t,copiable());} 为什么要转这么个弯?因为这样做了就有机会为基本类型添加特性信息,我们可以特化这个type_traits为基本类型,如 template<>struct type_traits<int>{  typedef _true_type copiable;}; STL里有个文件type_traits.h里面就定义了所有这些基本类型的偏特化版,当然,这里的copiable是我想出来的一个特性。 不仅仅只能为type可以定义traits,还可以为其它很多概念定义traits,比如iterator,它的偏特化版就牵扯到原始指针,可以认为,原始指针是一种iterator,而iterator是一个抽象的概念。 2,模板元编程TMP traits技法是一种TMP,它是将一部分运行期运行的程序移到编译期,更大的挖掘编译器的能力,像上面那些对‘特性’的条件判断,就是利用了参数推导。而循环结构的程序,却是利用了递归,比如求fibonacci数的程序: #include <cstdlib>#include <iostream> using namespace std; template<unsigned int n>struct fibonacci{       enum{value=fibonacci<n-1>::value+fibonacci<n-2>::value};}; template<>struct fibonacci<1>{       enum{value=1};}; template<>struct fibonacci<0>{       enum{value=0};};int main(int argc, char *argv[]){    cout<<fibonacci<10>::value<<endl;    system("PAUSE");    return EXIT_SUCCESS;} 这相当于一个"hello TMP world"程序。更多的内容我还不了解,我只能感叹一句,这样的程序,真酷! rickone 2008/01/30

阅读(5497) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册