为什么标准库里要有traits?

我们先回忆一下,标准库提供的算法的一些特征:

  • 参数一般包括iterator。

  • 要根据iterator的种类,和iterator包装的元素的类型等信息,来决定使用最优化的算法。

    比如如果是vector的iterator,那么就可以使用+,-操作;

    如果是list的iterator,那么就不可以使用+,-操作。

所以,算法必须知道一些关于iterator的信息。

有一些容器对应的iterator是个类,所以在这个类里,定义了如下的信息:

template<typename T>
struct __list_iterator {
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;

有了上面定义的定义,算法就能够知道iterator的信息了,算法就可以正常工作了。到这里位置貌似没有traits什么事,

但是,vector,array的iterator并不是类,而是c++里内置的指针,当把内置指针当参数传递给算法后,算法无法得知iterator里定义的iterator_category,value_type,difference_type等信息,算法就无法工作。怎么办?

加一个中间层,也就是创建一个iterator_traits类,它包装了iterator,并使用模板局部特化技术,来解决上面的问题。

traits是萃取机的意思,也就是萃取iterator里的信息,并给到算法。

traits技术:

//使用iterator提供的信息
template<typename Iterator>
struct iterator_traits
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_typep;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
}; //由于无法使用iterator的信息,所以traits自己提供了。
//局部特化,c++内置指针。
template<typename T>
struct iterator_traits<T *>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
}; //由于无法使用iterator的信息,所以traits自己提供了。
//局部特化,c++内置指针。
template<typename T>
struct iterator_traits<const T *>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;//注意这里不是const T;如果是const T,算法拿到这个类型,用这个类型定义变量后,却无法改变其值,那就没有作用了,所以是T。
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
};

算法向iterator_traits类要它需要的信息,iterator_traits再向iterator要,如果要到了,就使用;如果没有要到就使用iterator_traits提供的。

算法举例:list类的size方法。

size_type size() const {
size_type result = 0;
distance(begin(), end(), result);
return result;
//return distance(begin(), end());
} struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {}; template <class InputIterator, class Distance>
inline void __distance(InputIterator first, InputIterator last, Distance& n,
input_iterator_tag)
{
while (first != last) { ++first; ++n; }
} template <class RandomAccessIterator, class Distance>
inline void __distance(RandomAccessIterator first, RandomAccessIterator last,
Distance& n, random_access_iterator_tag)
{
n += last - first;
} template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&) {
typedef typename iterator_traits<Iterator>::iterator_category category;//--①
return category();
} template <class InputIterator, class Distance>
inline void distance(InputIterator first, InputIterator last, Distance& n)
{
__distance(first, last, n, iterator_category(first));
}

代码解说:在①处,算法向iterator_traits要iterator_category的信息,如果iterator能提供,就使用iterator里的iterator_category,如果iterator不能提供,就使用iterator_traits里的iterator_category。得到iterator_category后,就可以在编译阶段确定调用哪一个__distance方法了。

注意:是在编译阶段就可以确定,比在运行阶段确定调用哪个__distance方法的效率要高。

下面代码是没有trais技术,是在运行阶段才能确定调用哪个__distance方法。

template <class Iterator>
void distance(Iterator& i){
if(is_random_access_iterator(i)){
__distance1();
}
if(is_bidirectional_iterator(i)){
__distance2();
}
}

标准库的iterator_traits类,定义在stl_iterator.h文件里。

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

stl标准库 iterator_traits的更多相关文章

  1. STL标准库-算法-常用算法

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 介绍11种STL标准库的算法,从这11种算法中总结一下算法的基本使用 1.accumulate() 累加 2.for_each( ...

  2. STL标准库-容器-set与multiset

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. set与multiset关联容器 结构如下 set是一种关联容器,key即value,value即key.它是自动排序,排序特点依据key se ...

  3. STL标准库-容器-deque

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. deque双向开口可进可出的容器 我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去 deque却可以,它创造了内存 ...

  4. STL标准库-容器-vector

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. 向量容器vector是一个动态数组,内存连续,它是动态分配内存,且每次扩张的原来的二倍. 他的结构如下 一 定义 vector ...

  5. STL标准库-容器-set与map

    STL标准库-容器-set与multiset C++的set https://www.cnblogs.com/LearningTheLoad/p/7456024.html STL标准库-容器-map和 ...

  6. C++STL标准库学习笔记(五)set

    前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来,这一篇后面主要都是我的记录了,为了防止大片蓝色字体出现,后面就不改蓝色 ...

  7. C++STL标准库学习笔记(三)multiset

    C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...

  8. C++STL标准库学习笔记(二)二分查找

    二.STL中的二分查找算法 1.binary_search 2.lower_bound 3.upper_bound 记得#include<algorithm>! 前言: 在这个笔记中,我把 ...

  9. C++STL标准库学习笔记(一)sort

    前言: 近来在学习STL标准库,做一份笔记并整理好,方便自己梳理知识.以后查找,也方便他人学习,两全其美,快哉快哉! 这里我会以中国大学慕课上北京大学郭炜老师的<程序设计与算法(一)C语言程序设 ...

随机推荐

  1. Android 查看项目依赖树的四种方式

    Android 查看项目依赖树的四种方式: 方式一: ./gradlew 模块名:dependencies //查看单独模块的依赖 ./gradlew :app:dependencies --conf ...

  2. Django_xadmin_TypeError: Related Field got invalid lookup: icontains

    问题: 当我在给某一张表加上外键搜索的时候,会出现 TypeError: Related Field got invalid lookup: icontains 问题原因: a 表关联 b表,也就是说 ...

  3. Transportable tablespace on standby (Doc ID 788176.1)

    APPLIES TO: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 10.2.0.4 [Release 10.2]Oracle ...

  4. [PHP] 解决php中上传大文件的错误

    修改nginx配置文件,下面这个参数client_max_body_size 110M; 修改php配置文件中下面两个参数在php.ini中找到下面两个配置,配置项给改大,如果找不到php.ini的位 ...

  5. 图像处理&计算机视觉中upscale,downscale的翻译理解

    最近在看SAN网络(Second-order Attention Network for Single Image Super-Resolution)的论文,其中的Upscale module理解的不 ...

  6. 【西北师大-2108Java】第五次作业成绩汇总

    [西北师大-2108Java]第五次作业成绩汇总 作业题目 面向对象程序设计(JAVA) 第7周学习指导及要求 实验目的与要求 (1)掌握四种访问权限修饰符的使用特点: (2)掌握Object类的用途 ...

  7. Leetcode 90. 子集 II

    地址  https://leetcode-cn.com/problems/subsets-ii/ 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重 ...

  8. [C0] 引言(Introduction)

    引言(Introduction) 欢迎(Welcome) 机器学习是目前信息技术中最激动人心的方向之一.在这门课中,你将学习到这门技术的前沿,并可以自己实现学习机器学习的算法. 你或许每天都在不知不觉 ...

  9. Sphinx 2.0.8 发布,全文搜索引擎 Installing Sphinx on Windows

    参考资料地址信息 http://sphinxsearch.com/docs/latest/installing-windows.html http://my.oschina.net/melonol/b ...

  10. x86-64数据格式、通用寄存器与操作数格式

    x86-64数据格式.通用寄存器与操作数格式 数据格式 ​ Intel用术语"字(word)"表示16位数据类型,32位为"双字(double words)", ...