iterator_traits技法-程序员宅基地

技术标签: 算法  c++  C/C++常见问题  数据结构  

问题

在 C++ 泛型编程中,如何知道“迭代器所指对象的类型”,以便声明临时变量呢?我们把迭代器所指对象的类型称为value type

template <class Iterator>
void func(Iterator it)
{
    
    // 如果我想声明Iterator所指对象类型的临时变量应该怎么办呢?
    // 在这里没有办法!
}

函数模板的参数推导机制

但是可以利用函数模板的参数推导机制来达到目的。

template <class Iterator>
void func(Iterator it)
{
    
    func_impl(it, *it);		// 将任务交给func_impl完成
}

template <class Iterator, class T>
void func_impl(Iterator it, T t)
{
    
    // 现在T就是Iterator所指对象的类型
    T tmp;	// 达到目的
}

这种以func函数为对外接口,实际任务由func_impl函数完成的机制称为分派机制。这种机制可以实现所谓的“C++编译期间的多态”,将在下一篇文章中讲述。

编译器会自然推导出 T 的类型,但是思考有一个新的问题“value type如何用于声明返回类型”?

迭代器的value type

函数模板的参数推导机制不能推断返回值的类型!怎么办呢?那就让迭代器告诉我们吧!

当实现一个Iterator类时,必须指明自己的value type是什么,比如:

template <class T>
struct MyIterator {
    
    typedef T value_type;	// 自己指定value type是什么
    .......
};

这样,在泛型编程时可以这样获取迭代器的value type

template <class Iterator>
typename Iterator::value_type	// 这一行都是返回类型声明
func(Iterator it)
{
    
    return *it; 
}

iterator_traits

接下来这个iterator_traits类模板专门用来“萃取”迭代器的特性,而value type正是迭代器特性之一。

template <class Iterator>
struct iterator_traits {
    
    typedef typename Iterator::value_type value_type;
    ......	// 其他更多特性
}

这个如果iterator_traits的作用是:如果Iterator本身有value type,那么就用它。

在这之后,func函数可以重新写成这样:

template <class Iterator>
typename iterator_traits<Iterator>::value_type	// 这一行都是返回类型声明
func(Iterator it)
{
    
    return *it; 
}

为什么要多加一层呢?假设每个迭代器的实现者都指定了自己的value type,但并不是每个迭代器都是class,能够通过域作用符访问里面的成员,比如原生指针int*

int main()
{
    
    int x = 888;
	func(&x);	// 这样是不可以的
}

偏特化

针对原生指针类型,可以使用偏特化技术,为其定制专门的版本。

template <class T>
struct iterator_traits<T*> {
    	// 针对原生指针T*的偏特化
    typedef T value_type;
    ......	// 其他更多特性
}

template <class T>
struct iterator_traits<const T*> {
    	// 针对原生指针const T*的偏特化
    typedef T value_type;
    ......	// 其他更多特性
}

原生指针可能还是const T*类型,为了正确推断出T而不是const T,需要为const T*偏特化一个版本。

总结

总之,iterator_traits这个类模板是一台“榨汁机”,专门“萃取”迭代器的各种特性。它能够正常工作的一个重要原因是,设计迭代器的人共同遵守一个约定:自行定义迭代器的相应类型。STL 大家庭都遵守了这个约定,不遵守这个约定就不能兼容这个大家庭。

迭代器的相应类型共有五种,完整的iterator_traits是这样的:

template <class Iterator>
struct iterator_traits {
    
    typedef typename Iterator::value_type 			value_type;			// 迭代器所指对象的类型
    typedef typename Iterator::iterator_category 	iterator_category;	// 迭代器的类别
    typedef typename Iterator::difference_type 		difference_type;	// 两个迭代器的之间距离
    typedef typename Iterator::pointer 				pointer				// 指向迭代器所指的对象
    typedef typename Iterator::reference 			reference			// 迭代器所指对象的引用
}

正是迭代器的 5 种类型和iterator_traits技法成就了所谓的“C++编译期间的多态”。

最后

如果你有疑惑,欢迎评论,我会尽可能回复!

如果本文对你有帮助,点个赞吧,这是我坚持的动力!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43278899/article/details/128482849

智能推荐

Spring Cloud Eureka项目切换注册中心到Nacos_eureka切换nacos-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏7次。Spring Cloud 项目平滑将注册中心迁移到Nacos上1.问题概述由于项目升级,需要将Eureka注册中心改为阿里的Nacos作为注册中心项目环境1、Java 使用的 JDK-1.82、Spring Boot 使用的 Spring Boot-2.1.4.RELEASE3、Spring Cloud 使用的是 Greenwich.RELEASE2.方案设计2.1 业务应用多注册到Nacos和EurekaSpring Cloud应用默认不支持启动时双向注册,但是阿里商业版上云edas_eureka切换nacos

嵌入式基本知识必备_嵌入式中40u表示什么?-程序员宅基地

文章浏览阅读1.6k次,点赞4次,收藏15次。关于嵌入式产品常用元器件知识,本文多数资料来源网络,再次做整理总结。好了,开始启程!一、IC的三个温度等级芯片上表示对应温度范围C:表示商业级集成芯片(IC),温度定额为 0℃~+70℃;I: 工业级集成芯片(IC),温度定额为 -40℃~+85℃;A: 汽车工业级芯片(IC),温度定额为 -40℃~+125℃M:..._嵌入式中40u表示什么?

还原二叉树-程序员宅基地

文章浏览阅读202次。给定一棵二叉树的前序遍历序列和中序遍历序列,要求计算该二叉树的高度。

用CPLEX写个数学模型就这么难?_cplex does not support nonconvex quadratic constra-程序员宅基地

文章浏览阅读6.4k次,点赞20次,收藏148次。一、前言小编有个小伙伴,隔三差五就过来跟我说:这个模型CPLEX怎么写呢?我说我不是给你讲过好多次?他说CPLEX太复杂了,俺没学过学不会呢。Similarly,遇到这个问题的不止小编这个小伙伴。很多刚入行的小伙伴都表示CPLEX对初学者来说并不是很友好,就连学习资料都不知道去哪里看,不像Excel或者Word,百度一下出来好多资料。其实吧,这玩意儿并没有大家想的那么难,尤其是简单使用CPLEX求解一个模型的话,用来用去都是那几个函数而已。下面小编来给大家好好理一下,看完相信你也能用CPLEX跑一下论_cplex does not support nonconvex quadratic constraints

R语言在矢量地图上绘制分级设色散点图_r语言在地图上绘制不同颜色散点图-程序员宅基地

文章浏览阅读1.9k次。实现效果:R语言中ggplot2包提供绘制地图、散点图的方法,是实现在矢量地图上绘制分级设色散点图核心包绘制多边形geom_polygon(data,aes,fill, colour) 绘制点 geom_point .....0、需要用到的包library(maptools) # 读取shp数据常用,可以将shp数据读取为SpatialPolygonsDataFrame 格式,为DataFrame(数据帧)子类,也称为空间多边形数据帧library(ggplot2) #绘图核..._r语言在地图上绘制不同颜色散点图

【matlab】求空间两个向量之间的夹角_matlab 向量夹角-程序员宅基地

文章浏览阅读3.1w次,点赞28次,收藏73次。原点O[0,0,0]OA=[1,1,0];OB=[1,0,0];sigma = acos(dot(OA,OB)/(norm(OA)norm(OB)));%弧度制sigma/pi180%换算成角度_matlab 向量夹角

随便推点

【项目构建】java: -source 1.5 中不支持switch 中存在字符串_-source 1.5 中不支持 switch 中存在字符串-程序员宅基地

文章浏览阅读502次,点赞20次,收藏3次。使用maven进行项目构建时报错,信息如下。_-source 1.5 中不支持 switch 中存在字符串

群论期中考试必会题目_z2群-程序员宅基地

文章浏览阅读1.2k次。(1) 置换群 拉格朗日(2) 对称性(3) X= 0 这个是舒尔引理二,要背下来(4) 相同,这是重排定理(5) 这个题目讲了连续群在做(6) A(7) 相等(8) Z2群{1,-1}, 为阿贝尔群,D3群为非阿贝尔群二.(1) 封闭性,结合性,恒元,逆元(2) 不构成,没有逆元(3) 群表示矩阵的迹..._z2群

STM32CubeMX配置W25Q128_stm32 w25q128jvsim配置-程序员宅基地

文章浏览阅读444次,点赞9次,收藏7次。W25Q128是华邦公司推出的一款SPI接口的NOR Flash芯片,其存储空间为128Mbit,相当于16M字节。W25Q128V芯片是串行闪存,可以通过标准/两线/四线SPI控制。W25Q128JV阵列被组织成65536个可编程页面,每个页面256字节。一次最多可编程256个字节。页面可以按16组(4KB扇区擦除)、128组(32KB块擦除)、256组(64KB块擦除或整个芯片(芯片擦除)擦除。W25Q128JV分别具有4096个可擦除扇区和256个可擦除块。_stm32 w25q128jvsim配置

java.lang.ProcessBuilder类(系统进程)_processbuilder pb = new processbuilder-程序员宅基地

文章浏览阅读546次。转载地址:http://lavasoft.blog.51cto.com/62575/15662/一、概述 ProcessBuilder类是J2SE 1.5在java.lang中新添加的一个新类,此类用于创建操作系统进程,它提供一种启动和管理进程(也就是应用程序)的方法。在J2SE 1.5之前,都是由Process类处来实现进程的控制管理。 每个 Proces_processbuilder pb = new processbuilder

满城中学-程序员宅基地

文章浏览阅读1.5k次。自传4、在满城中学上高一----拉黎耕地 一九五九年九月,我到满城上高中。这是一所县办校,当时只招高中生。校址设在城南部,校外坡下黄土坑。砖墙瓦盖东西院,临近大街路畅通。东院教室有三栋,里面充满读书声。西院师生当宿舍,水井台在院当中。两院中隔宽街道,由南向北直贯通。南端书店汽车站,北去商店理发厅。化学老师班主任,三十几岁黑面容。穿着整齐而朴素,对人严肃而真诚。俄语老师张琳娜,中国姑娘苏联名。..._满城中学9708班

QUESTION 41-benefits of installing Grid Infrastructure software_which are two benefits of installing grid infrastr-程序员宅基地

文章浏览阅读97次。What are two benefits of installing Grid Infrastructure software for a stand-alone server before installing and creating an Oracle database? (Choose two.)A. Effectively implements role separationB. Enables you to take advantage of Oracle Managed Files.C._which are two benefits of installing grid infrastructure software for a stan