一、从模板函数std::distance(计算迭代器的距离)开始

#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <stack>
#include <set>
#include <map>int main(int argc, char*argv[])
{std::vector<int> vec;for (int i = 0; i < 10; ++i){vec.push_back(i);}///stack、queue、priority_queue无迭代器///vector、deque有operator-的实现,而list、set、map没有auto d = vec.end() - vec.begin();///distance函数对各类型迭代器都支持,计算迭代器之间的距离auto itrDis = std::distance(vec.begin(), vec.end());return 0;
}


1、stack、queue、priority_queue容器无迭代器,即不能使用此函数。
2、vector、deque容器重载了operator-,实现了计算std::distance功能。内存连续型(迭代器可跳跃)容器,距离为迭代器直接相减。

_NODISCARD difference_type operator-(const _Mybase& _Right) const{   // return difference of iteratorsreturn (*(_Mybase *)this - _Right);}

3、list、set、map容器没有实现operator-,内存不连续型(迭代器不可跳跃)容器。

二、distance模板函数实现剖析

//_Distance1的两个重载版本begin
template<class _InIt>_CONSTEXPR17 _Iter_diff_t<_InIt> _Distance1(_InIt _First, _InIt _Last, input_iterator_tag){    // return distance between iterators; input_Iter_diff_t<_InIt> _Off = 0;for (; _First != _Last; ++_First){++_Off;}return (_Off);}template<class _RanIt>_CONSTEXPR17 _Iter_diff_t<_RanIt> _Distance1(_RanIt _First, _RanIt _Last, random_access_iterator_tag){   // return distance between iterators; random-accessreturn (_Last - _First);}
//_Distance1的两个重载版本end//迭代器的类型萃取begin
template<class _Iter>using _Iter_cat_t = typename iterator_traits<_Iter>::iterator_category;
//迭代器的类型萃取end//distance函数begin
template<class _InIt>_NODISCARD _CONSTEXPR17 _Iter_diff_t<_InIt> distance(_InIt _First, _InIt _Last){   // return distance between iteratorsreturn (_Distance1(_First, _Last, _Iter_cat_t<_InIt>()));}
//distance函数end

1、由_Distance1函数实现,并且_Distance1有两个重载版本(VS2017),其他编译器可能有多个,但并无分别。
2、由第三参数类型input_iterator_tag和random_access_iterator_tag用来重载,也仅仅是用来重载,并未使用类型对象。
3、_Iter_cat_t<_InIt>()则用来萃取(向迭代器提问)其类型,而iterator_category即是答案。

typename T::iterator_category cagy2;     //等同于迭代器的类型萃取

4、迭代器除了可以回答与之容器对应的迭代器类型,还可以回答一下类型。

typedef bidirectional_iterator_tag iterator_category //迭代器的分类
typedef ptrdiff_t difference_type                       //iterator之间的距离
typedef size_t  size_type                               //分配内存大小
typedef T value_type
typedef T* pointer
typedef &T reference

例如:

typename std::iterator_traits<T>::difference_type diff_type;

5、迭代器的五种类型,按移动性质分类,不是枚举、常量宏等类型,为struct,属性在此等同class,并且有继承关系。

struct input_iterator_tag{   // identifying tag for input iterators};struct output_iterator_tag{ // identifying tag for output iterators};struct forward_iterator_tag: input_iterator_tag{   // identifying tag for forward iterators};struct bidirectional_iterator_tag: forward_iterator_tag{  // identifying tag for bidirectional iterators};struct random_access_iterator_tag: bidirectional_iterator_tag{  // identifying tag for random-access iterators};

6、_Distance1模板函数只实现的两个重载版本(内存是否连续型或者说迭代器是否可跳跃),因为继承关系其他类型向上兼容。VS2017只有该两个版本,其他版本编译器可能有多个版本。

到此完完全全讲清楚了模板函数std::distance怎么实现计算迭代器之间的距离。
如对容器的数据结构,底层实现不清楚的可参考:
C++STL容器总结:https://blog.csdn.net/qq_43148810/article/details/118229552

7.拓展:
std::advance:令迭代器移动给定距离。内部实现和distance原理一致,有兴趣可深入研究。

template<class _InIt,class _Diff> inline
void advance(_InIt& Where,_Diff _Off)
{...}

三、类型萃取,惊鸿一瞥 ,STL六大组件关系


总结:Container通过Allocator取得数据的储存空间,Algorithm通过Iterator存取Container内容,Functor可以协助Algorithm完全不同的策略变化,Adapter可以修饰或者套接Functor。

1、std::distance(计算迭代器的距离)算法很好的解释了以上“总结”斜线部分。
2、STL称之为标准模板库,C++面对对对象语言,标准库多为模板编程、元编程的手法,而非面对对象的手法。换而言之多为静态多态性,而非虚函数代表的动态多态性。
3、traits(萃取机)并非六大组件,但是在STL中起到至关重要的作用。
4、由此打开元编程(对类型操作,而非对象)的大门

如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810

C++模板编程之类型萃取 惊鸿一瞥相关推荐

  1. C++ 模板类型萃取技术 traits

    当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案.(类型测试发生在编译期 ...

  2. type_traits 类型萃取

    一. c++ traits traits是c++模板编程中使用的一种技术,主要功能: 把功能相同而参数不同的函数抽象出来,通过traits将不同的参数的相同属性提取出来,在函数中利用这些用traits ...

  3. C++ — 类型萃取

    类型萃取 在编程中我们可能时常会听到类型萃取这个高大上的"学术名词",我们今天来探究一下这个高大上的学术名词 到底是何方神圣,先看看官方的解释类型萃取使用模板技术来萃取类型(包含自 ...

  4. C++特化的应用——类型萃取

    提出问题:如何实现一个对于拷贝内置类型和自定义类型通用的拷贝函数? 1.拷贝内置类型 对于内置类型我们可以用memcpy进行拷贝,因为memcpy属于浅拷贝,内置类型不涉及资源管理的问题. 2.拷贝自 ...

  5. C/Cpp / STL / 类型萃取

    作用 类型萃取使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,用以判断该类型是否含有某些特性,从而在泛型算法中来对该类型进行特殊的处理用来达到提高效率或者其他的目的. 类型萃取的实现的基 ...

  6. C++的类型萃取技术

    http://www.cppblog.com/nacci/archive/2005/11/03/911.aspx?spm=0.0.0.0.iyJqvt&file=911.aspx 自从C++中 ...

  7. C++之类型萃取技巧

    使用类型萃取的原因 就是当你的顺序表是自定义类型,我们进行顺序表增容的时候,这个时候会出现一个问题,比如string类型,这个类型中有一个_buf与_ptr,当储存少于16个的时候这时会储存在_buf ...

  8. C++类型萃取之type_traits和type_info

    类型萃取 类型判断 typeid decltype和declval enable_if 类型萃取 通过type_traits可以实现在编译期计算.查询.判断.转换和选择,增强了泛型编程的能力,也增强了 ...

  9. [c++]——什么是类型萃取

    类型萃取 类型萃取从字面意思上来说其实就是帮助我们挑选某个对象的类型,筛选特定的对象来做特定的事. C++中的类型萃取并不是每个人都熟知,他们一般都出现在STL库底层的实现原理中,和笔者一样,相信听到 ...

最新文章

  1. 玩转 iOS 开发:《iOS 设计模式 — 工厂模式》
  2. WebDriver自动化测试工具(3)---PhantomJS的使用
  3. java serialization/deserialization (序列化对象自描述)
  4. java招聘职位描述,附学习笔记+面试整理+进阶书籍
  5. 简单工厂模式和策略模式结合使用php
  6. android+wear+游戏,技术帝:Android Wear手表运行一代PS游戏
  7. [3rgb.com开发笔记] 初步设想篇
  8. Pytorch损失函数BCELoss,BCEWithLogitsLoss
  9. 用户画像案例一:汽车精准营销
  10. C语言数据结构——串的定义及抽象数据类型
  11. redis中hget命令
  12. MSP430F149用模拟SPI和FM25CL640通信
  13. YARN任务监控界面Aggregate Resource Allocation指标解析
  14. 去掉Nero 8刻录时激活三方专利组件的提示框
  15. Linux man 命令后面的数字含义及作用
  16. 【并查集】银河英雄传说
  17. 基于粒子群算法的冷热电三联供综合能源系统优化调度
  18. [5 种有效方法] 适用于 Android 的通用解锁图案/密码
  19. 多远线性回归代码-波士顿房价问题
  20. 太康一高2021高考成绩查询,2021年太康县高考状元成绩分数,太康县历年高考状元名单...

热门文章

  1. 面试时,最可怕的就是背调?
  2. jmeter-监听器之每秒事务数响应时间活动的线程数服务器性能指标监控
  3. uniapp实现视频上下滑动功能
  4. 我喜欢玩计算机游戏译成英语,50字英语作文带翻译-我喜欢玩游戏
  5. 2022年河北省高职单招(数学)考试冲刺试题及答案
  6. 人脸识别漏洞频出?这里有个开源静默活体检测算法,超低运算量、工业级可用...
  7. Fiddler_IE浏览器打开网页提示安全证书过期或证书错误的解决方法
  8. Numba加速Python教程
  9. 爱奇艺与上海电影学院成立“智能制作联合实验室”
  10. Vue2.x 源码 - VNode渲染过程(update、patch)