Effective C++第七章-模板和泛型编程之traits和TMP(模板元编程)

来源:互联网 发布:中小学教学软件 编辑:程序博客网 时间:2024/05/22 17:43

traits

  • traits不是C++关键字或一个预先定义好的构件,是一种技术,也是一个C++程序员共同遵守的协议。该技术要求对内置(built-in)类型和用户自定义类型的表现必须一样好。
  • traits允许你在编译期间取得某种类型信息,习惯上traits总被实现为struct。
  • 标准技术是把traits放进一个template及其一或多个特化版本中。这样的template在标准程序库中有若干个,其中针对迭代器者被命名为iterator_traits:
  • 设计和实现一个traits class的步骤:
    1. 确认若干你希望将来可取得的类型相关信息。例如,对迭代器而言,我们希望将来可取得其分类(category)
    2. 为该信息选择一个名称(例如,iterator_category).
    3. 提供一个template和一组特化版本(例如iterator_traits),内含你希望支持的类型相关信息。
  • 以迭代器为例:我们希望取得迭代器的类型,并命名为iterator_category:
STL中的迭代器: input 向前移动,只能读一次 output 向前移动,只能写一次 forward 向前,可读可写一次以上 bidirectional 向前向后,list、set、multiset、map、multimap迭代器 random access 可以执行迭代器算术,vector、deque、string
template<...>class deque{public:    class iterator{     public:            typedef random_access_iterator_tag iterator_category;    };};template<...>class listpublic:    class iterator{     public:            typedef bidirectional_iterator_tag iterator_category;    };};...//其他迭代器template<typename IterT>struct iterator_traits{    typedef typename IterT::iterator_category iterator_category;//条款42:在template中指涉一个嵌套从属类型就必须在其前放置关键字typename.};//但对于指针(特殊的迭代器)不能嵌套,因此需要提供偏特化版本,如下:template<typename IterT>//template偏特化struct iterator_traits<IterT*>{    typedef random_access_iterator_tag iterator_category;};
  • traits提供的信息也可以作为重载函数的参数,例如:

    template<typename IterT , typename DistT>void doSomething(IterT& iter,DistT , std::random_access_iretator_tag){...}//实现random access迭代器template<typename IterT , typename DistT>void doSomething(IterT& iter,DistT , std::bidirectional_iterator_tag){...}//bidirectional迭代器...
  • traits广泛用于标准程序库,例如还有char_traits用来保存字符类型的相关信息。

  • TR1导入许多新的traits class用来提供类型信息,包括is_fundamental< T >(判断T是否是内置类型),is_array< T> ,以及is_base_of< T1,T2 >(T1和T2相同,抑或T1是T2的base class)。

Template metaprogramming(TMP,模板元编程)

定义:TMP就是编写基于模板的C++程序并执行于编译期的过程。

可将工作由运行期移往编译器,因而得以实现早期错误侦测和更高的执行效率。

TMP的起手程序(类似于hello world):

//阶乘运算,示范如何通过“递归模板具现化”实现循环template<unsigned n>struct factorial{    enum{value = n* factorial<n-1>::value};};template<>struct factorial<0>{  enum{value =1};};//每个factorial template具现化都是一个struct,每个struct都使用enum hack声明一个名为value的TMP变量,每个value有其循环内适当值。如果是循环实现的话,可能只存在一个value,并不断更新值。//调用int main(){  std::cout<<factorial<5>::value;}
阅读全文
0 0