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

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 list
public:
    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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值