STL Traits编程技法

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(偏特化)


 1 //class type的“内嵌型别”
2 template <class _Iterator>
3 struct iterator_traits {
4 typedef typename _Iterator::iterator_category iterator_category;
5 typedef typename _Iterator::value_type value_type;
6 typedef typename _Iterator::difference_type difference_type;
7 typedef typename _Iterator::pointer pointer;
8 typedef typename _Iterator::reference reference;
9 };
10
11 //对原生指针的偏特化
12 template <class _Tp>
13 struct iterator_traits<_Tp*> {
14 typedef random_access_iterator_tag iterator_category;
15 typedef _Tp value_type;
16 typedef ptrdiff_t difference_type;
17 typedef _Tp* pointer;
18 typedef _Tp& reference;
19 };
20
21 //对const指针的偏特化
22 template <class _Tp>
23 struct iterator_traits<const _Tp*> {
24 typedef random_access_iterator_tag iterator_category;
25 typedef _Tp value_type;
26 typedef ptrdiff_t difference_type;
27 typedef const _Tp* pointer;
28 typedef const _Tp& reference;
29 };

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

提高效率

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

例如 advance():


 1 //用于input_iterator的版本
2 template <class _InputIter, class _Distance>
3 inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
4 while (__n--) ++__i;
5 }
6
7 //用于 bidirectional_iterator的版本
8 template <class _BidirectionalIterator, class _Distance>
9 inline void __advance(_BidirectionalIterator& __i, _Distance __n,
10 bidirectional_iterator_tag) {
11 __STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);
12 if (__n >= 0)
13 while (__n--) ++__i;
14 else
15 while (__n++) --__i;
16 }
17
18 //用于 random_access_iterator的版本
19 template <class _RandomAccessIterator, class _Distance>
20 inline void __advance(_RandomAccessIterator& __i, _Distance __n,
21 random_access_iterator_tag) {
22 __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
23 __i += __n;
24 }
25
26 //advance方法的对外接口
27 template <class _InputIterator, class _Distance>
28 inline void advance(_InputIterator& __i, _Distance __n) {
29 __STL_REQUIRES(_InputIterator, _InputIterator);
30 __advance(__i, __n, iterator_category(__i));
31 }

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 };


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

为保守起见都定义为__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编程技法,码迷,mamicode.com

时间: 2024-10-11 15:31:47

STL Traits编程技法的相关文章

stl源码剖析学习笔记(二)traits编程技法简明例程

解释说明 traits侯捷老师的翻译是萃取.其目的就是在编译期进行模板调用的类型识别,从而做一些事情. 最突出的例子,我觉得不是<STL源码剖析>中"迭代器概念与traits编程技法"这一章的说明,而是stl算法中copy的实现.代码在stl源码的stl_algobase.h中. copy的最终实现,大致分为两类,一类是直接整块内存的memmove操作,另一类是一个个对象赋值.其中涉及has_trivial_assignment_operator的类型推断. 如果has_t

STL中的Traits编程技法

最近在看读<STL源码剖析>,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力.那么什么是Traits编程技法呢?且听我娓娓道来: 我们知道容器的许多操作都是通过迭代器展开的.其中容器类似于数组,迭代器类似于指针.我们用数组来写个例子: 1 int arr[5] = {1,2,3,4,5}; 2 int *p; 3 p = &arr[2]; 假设,我将第1.2遮挡起来,问你p所指向的对象arr[2]是什么类型,你恐怕无法回答.因为它可以是int,char,float甚至

STL iterator和traits编程技法

今天终于看完了<STL源码分析>,最近忙于两个比赛的各种文档,没时间写东西,趁着看完的劲,把欠下的补上来. <Design patterns>中对于iterator模式描述如下:提供一种方法,使之能够依序寻访某个聚合物所含的各个元素,而又无需暴露该聚合物的内部结构.在STL中,iterator扮演着连接container和algorithms的作用,下面以STL find()函数展现一下iterator在container和algorithm之间的连接作用. template &l

STL之traits编程技法

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

[转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法

本文从三方面总结迭代器   迭代器的思想   迭代器相应型别及traits思想   __type_traits思想 一 迭代器思想 迭代器的主要思想源于迭代器模式,其定义如下:提供一种方法,使之能够依序巡防某个聚合物(容 器)所含的元素,而又无需暴露该聚合物的内部表达式.可见她的主要作用便是能够降低耦合,提高代码的 模块性. STL的的中心思想在于:将数据容器和算法分开,彼此独立设计,最后再以一贴胶着剂将它们撮合 在一起,这贴胶着剂便是迭代器.迭代器的行为类似智能指针(例如标准库的auto_pt

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

在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器所指对象的类型只是里面的其中一个.后面会讨论到相应类型的另外几种. 假设算法需要声明一个变量,以“迭代器所指对象的类型”为类型,该怎么做?或许我们可能会想到RTTI性质中的typeid(),但获得的只是类型名称,并不能拿来声明变量. 其中一个解决方法是:利用模版函数中的参数推导(argument d

traits编程技法

看了<stl源码剖析>中关于traits的部分,由于对模板还不是很熟悉,就看了一下还未完工的C++ Template 进阶指南 ,感觉收获很大,推荐一下. 在使用迭代器时,为了知道它的相应类型,可以使用模板的参数推导,代码如下 template <class T> struct MyIter typedef T value_type; T* ptr; MyIter(T* p=0) : ptr(p) { } T& operator*() const { return *ptr

STL源码剖析—迭代器与traits编程方法

STL的中心思想就是将算法和容器分开,彼此独立设计,最后再以粘合在一起,算法和容器的泛型化,并不是很难,C++的class templates和function templates可以达成目标,但是粘合在一起就是迭代器的事情. 这么一说迭代器就是为了粘合算法和容器的,如果单独设计迭代器,那么这个迭代器就必须知道某个特定容器的内部数据,会暴露太多的信息,这样就规定每一种STL容器都提供有专属迭代器. 迭代器所指对象的型别,称为该迭代器的value_type.所谓value_type,是指迭代器所指

《STL源码剖析》学习之traits编程

侯捷老师在<STL源码剖析>中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘.如此一说,其重要性就不言而喻了.      之前已经介绍过迭代器,知道了不同的数据结构都有自己专属的迭代器,不同的迭代器也有不同的特性,由于算法的接口是统一的,通过迭代器的不同属性,算法自动选择正确的执行流程,在完全任务的同时,也尽可能提高算法的执行效率.那算法如何获知迭代器的属性呢?这一光荣的任务就是traits完成的.在STL实现中,traits编程技术得到大量的运用