traits编程技法大量运用于STL实现中。通过它在一定程度上弥补了C++不是强型别语言的遗憾,增强了C++关于型别认证方面的能力。

traits编程技法是利用“内嵌型别”的编程技法和编译器的template参数推导功能实现的。

iterator_traits

1.对于class type要求其“内嵌型别”

要求与STL兼容的容器,其迭代器必须定义一下五种型别:

iterator_category  迭代器类型

value_type  迭代器所指对象类型

difference_type  迭代器间的距离类型

pointer

reference

2.对于非class type(如:原生指针)需要使用template partial specialization(偏特化)

 //class type的“内嵌型别”
template <class _Iterator>
struct iterator_traits {
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
}; //对原生指针的偏特化
template <class _Tp>
struct iterator_traits<_Tp*> {
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
}; //对const指针的偏特化
template <class _Tp>
struct iterator_traits<const _Tp*> {
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
};

iterator中为什么要引入traits机制?

提高效率

对效率的至极追求贯穿整个STL设计,traits机制的引入是为了实现 同一方法用于不同类型时调用对该类型最高效的版本 以提高效率。

例如 advance():

 //用于input_iterator的版本
template <class _InputIter, class _Distance>
inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
while (__n--) ++__i;
} //用于 bidirectional_iterator的版本
template <class _BidirectionalIterator, class _Distance>
inline void __advance(_BidirectionalIterator& __i, _Distance __n,
bidirectional_iterator_tag) {
__STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);
if (__n >= )
while (__n--) ++__i;
else
while (__n++) --__i;
} //用于 random_access_iterator的版本
template <class _RandomAccessIterator, class _Distance>
inline void __advance(_RandomAccessIterator& __i, _Distance __n,
random_access_iterator_tag) {
__STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
__i += __n;
} //advance方法的对外接口
template <class _InputIterator, class _Distance>
inline void advance(_InputIterator& __i, _Distance __n) {
__STL_REQUIRES(_InputIterator, _InputIterator);
__advance(__i, __n, iterator_category(__i));
}

SGI STL中迭代器之外的 __type_traits

STL只对迭代器进行了traits规范,制定类iterator_traits。SGI 把这种规范扩大到类迭代器之外,也就是__type_traits(__前缀表示是SGI 内部使用的,不在STL规范内)。

iterator_traits负责萃取iterator特性,而__type_traits则负责萃取一下五种型别(type)特性:

  has_trivial_default_constructor  是否有平凡的默认构造函数

  has_trivial_copy_constructor  是否有平凡的拷贝构造函数

  has_trivial_assignment_operator  是否有平凡的分配操作

  has_trivial_destructor  是否有平凡的析构函数

  is_POD_type  是否为POD类型(POD:Plain Old Data

如果class内含指针成员,并对它进行内存动态分配,那么这个class就需要实现自己的 non-trivial-xxx。

上述特性应该响应我们“真”或“假”,但却不能是bool值,因为我们要利用其响应来进行参数推导,而编译器只有面对class object形式的参数时才能进行参数推导,因此响应应该是带有“真”“假”性质的不同类。SGI STL中如下定义:

1 struct __true_type {
2 };
3
4 struct __false_type {
5 };
 template <class _Tp>
struct __type_traits {
typedef __true_type this_dummy_member_must_be_first;
/* Do not remove this member. It informs a compiler which
automatically specializes __type_traits that this
__type_traits template is special. It just makes sure that
things work if an implementation is using a template
called __type_traits for something unrelated. */ /* The following restrictions should be observed for the sake of
compilers which automatically produce type specific specializations
of this class:
- You may reorder the members below if you wish
- You may remove any of the members below if you wish
- You must not rename members without making the corresponding
name change in the compiler
- Members you add will be treated like regular members unless
you add the appropriate support in the compiler. */ typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};

为保守起见都定义为__false_type

在SGI STL的Type_traits.h中对C++ 内建的bool/char/signed char/unsigned char等标记为__true_type。

为什么要引入__type_triats?

答案还是提高效率

对于标记为__true_type的型别,对其对象进行构造/析构/拷贝/赋值等操作时就可以采用最有效率的措施。(如:不必调用高层次的constructor/destructor,而采用内存直接处理操作malloc()/memcpy()等)

STL Traits编程技法的更多相关文章

  1. STL源码--iterator和traits编程技法

    第一部分 iterator学习 STL iterators定义: 提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式. 任何iteartor都应该提供5 ...

  2. STL源码分析读书笔记--第三章--迭代器(iterator)概念与traits编程技法

    1.准备知识 typename用法 用法1:等效于模板编程中的class 用法2:用于显式地告诉编译器接下来的名称是类型名,对于这个区分,下面的参考链接中说得好,如果编译器不知道 T::bar 是类型 ...

  3. STL中的Traits编程技法

    最近在看读<STL源码剖析>,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力.那么什么是Traits编程技法呢?且听我娓娓道来: 我们知道容器的许多操作都是通过迭代器展开 ...

  4. STL——迭代器与traits编程技法

    一.迭代器 1. 迭代器设计思维——STL关键所在 在<Design Patterns>一书中对iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素 ...

  5. STL源码之traits编程技法

    摘要 主要讨论如何获取迭代器相应型别.使用迭代器时,很可能用到其型别,若需要声明某个迭代器所指对象的型别的变量,该如何解决.方法如下: function template的参数推导机制 例如: tem ...

  6. STL源码剖析——iterators与trait编程#2 Traits编程技法

    在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器 ...

  7. STL之traits编程技法

    traits编程技法利用了“内嵌型别”的编程技巧与编译器的template参数推导功能. 下面主要看看利用traits编程技法实现的迭代器萃取机制. 5种迭代器类型定义: struct input_i ...

  8. 【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

    大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub : https://github.com/rongweihe/Mor ...

  9. [转]Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧

    STL中,traits编程技法得到了很大的应用,了解这个,才能一窥STL奥妙所在. 先将自己所理解的记录如下: Traits技术可以用来获得一个 类型 的相关信息的. 首先假如有以下一个泛型的迭代器类 ...

随机推荐

  1. TreeView节点拖拉操作1

      TreeView节点拖拉操作1 //事先设置 TreeView1.DragMode= dmAutomatic;   unit Unit1; interface uses   Windows, Me ...

  2. 日志管理 rsyslog服务浅析

    http://www.xiaomastack.com/2014/11/13/rsyslog/

  3. shared_ptr的简单实现

    前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针 ...

  4. Maven 修改本地存储库位置--转

    step1:默认会放在~/.m2/repository目录下 (“~”代表用户的目录,比如windows下一般都是C:\Documents and Settings\[你的用户名]\), step2: ...

  5. 美H1B签证额满,硕士以上学位仍可申请

    美国公民与移民服务局6月1日宣布,2007会计年度的工作签证H1B名额已经用完,下年度的申请从明年4月1日开始.但在美国获得硕士以上学位的高学历者仍可申请. 据北美世界日报报道,美国移民律师协会对连续 ...

  6. Maven学习小结(六 setting.xml详解[转])

    当Maven运行过程中的各种配置,例如pom.xml,不想绑定到一个固定的project或者要分配给用户时,我们使用settings.xml中的settings元素来确定这些配置.这包含了本地仓库位置 ...

  7. JavaFX(二)自定义窗口标题栏

    1.问题场景 PC客户端登录界面仿QQ,上边显示图片,下边显示输入框和登录按钮.而JavaFX默认的窗口,不满足需求. 2.解决思路 隐藏窗口默认的标题栏,使用创建label对象,使用css将按钮图片 ...

  8. MapReduce中的作业调度

    MapReduce是hadoop提供一个可进行分布式计算的框架或者平台,显然这个平台是多用户的,每个合法的用户可以向这个平台提交作业,那么这就带来一个问题,就是作业调度. 任何调度策略都考虑自己平台调 ...

  9. html笔记01:顺序和无序列表

    <!DOCTYPE html> <html> <body> <li>Yellow <ul><li>Wet soil</li ...

  10. C&python文件读写效率

    不同缓冲区读写文件的效率比较 环境:CentOS6.3/ext3/ 读取文件大小:100000000B BUFSIZE TIMECOST 1 real 0m38.909s user 0m5.960s  ...