为什么标准库里要有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. SAP系统邮件功能配置

    相信SAP顾问或多或少都会接到用户要求SAP系统能够定时发送邮件的功能,定时将用户需要的信息已邮件的方式发送给固定的人员. 下面就来讲一下SAP发送邮件应该如何配置: 1.RZ10做配置: is/SM ...

  2. 更改组织属性-以更改maxrecordsforexporttoexcel为例

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复232或者20161101可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  3. Impala基于内存的SQL引擎的详细介绍

    一.简介 1.概述 Impala是Cloudera公司推出,提供对HDFS.Hbase数据的高性能.低延迟的交互式SQL查询功能. •基于Hive使用内存计算,兼顾数据仓库.具有实时.批处理.多并发等 ...

  4. RPM命令总结

    RPM软件管理程序 rpm命令是RPM软件包的管理工具.rpm原本是Red Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功能强大方便,因而广受欢迎.逐渐受到其他 ...

  5. 『003』Shell命令

    『001』索引-Linux Shell Command shell命令 <01>[线上查询及帮助][001]-[001] [001]- 点我快速打开文章[man][help][已改版] & ...

  6. 漫长的 windows caffe编译过程 (OnlyCpu)

    在windows下 编译caffe代码. 官方推荐是vs2013 而我手头只有VS2017 .准备开始下载代码开始编译. 1 代码下载 windows版本的代码有两份,一份是官方的编译的windows ...

  7. SP1716 GSS3 - Can you answer these queries III 线段树

    问题描述 [LG-SP1716](https://www.luogu.org/problem/SP1716] 题解 GSS 系列的第三题,在第一题的基础上带单点修改. 第一题题解传送门 在第一题的基础 ...

  8. CF1244F Chips

    题目链接 problem 有一个长度为\(n\)个点连成的环.每个点为黑色或白色.当一个点和与他相邻的两个点颜色不同时.该点的颜色就会改变. 问改变\(K\)次后每个点的颜色. solution 发现 ...

  9. 【2019.10.7 CCF-CSP-2019模拟赛 T3】未知的数组(unknown)(并查集+动态规划)

    预处理 考虑模数\(10\)是合数不好做,所以我们可以用一个常用套路: \(\prod_{i=l}^ra_i\equiv x(mod\ 10)\)的方案数等于\(\prod_{i=l}^ra_i\eq ...

  10. HTML文件通过jQuery引入其他HTML文件报错has been blocked by CORS policy

    HTML通过jQuery引入模板 完整报错 新创建一个chrome快捷方式,命名为chrome-debug 右键属性,在目标后添加参数,原始路径如下 "C:\Program Files (x ...