在 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
如何用于声明返回类型”?
函数模板的参数推导机制不能推断返回值的类型!怎么办呢?那就让迭代器告诉我们吧!
当实现一个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
类模板专门用来“萃取”迭代器的特性,而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++编译期间的多态”。
如果你有疑惑,欢迎评论,我会尽可能回复!
如果本文对你有帮助,点个赞吧,这是我坚持的动力!
文章浏览阅读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
文章浏览阅读1.6k次,点赞4次,收藏15次。关于嵌入式产品常用元器件知识,本文多数资料来源网络,再次做整理总结。好了,开始启程!一、IC的三个温度等级芯片上表示对应温度范围C:表示商业级集成芯片(IC),温度定额为 0℃~+70℃;I: 工业级集成芯片(IC),温度定额为 -40℃~+85℃;A: 汽车工业级芯片(IC),温度定额为 -40℃~+125℃M:..._嵌入式中40u表示什么?
文章浏览阅读202次。给定一棵二叉树的前序遍历序列和中序遍历序列,要求计算该二叉树的高度。
文章浏览阅读6.4k次,点赞20次,收藏148次。一、前言小编有个小伙伴,隔三差五就过来跟我说:这个模型CPLEX怎么写呢?我说我不是给你讲过好多次?他说CPLEX太复杂了,俺没学过学不会呢。Similarly,遇到这个问题的不止小编这个小伙伴。很多刚入行的小伙伴都表示CPLEX对初学者来说并不是很友好,就连学习资料都不知道去哪里看,不像Excel或者Word,百度一下出来好多资料。其实吧,这玩意儿并没有大家想的那么难,尤其是简单使用CPLEX求解一个模型的话,用来用去都是那几个函数而已。下面小编来给大家好好理一下,看完相信你也能用CPLEX跑一下论_cplex does not support nonconvex quadratic constraints
文章浏览阅读1.9k次。实现效果:R语言中ggplot2包提供绘制地图、散点图的方法,是实现在矢量地图上绘制分级设色散点图核心包绘制多边形geom_polygon(data,aes,fill, colour) 绘制点 geom_point .....0、需要用到的包library(maptools) # 读取shp数据常用,可以将shp数据读取为SpatialPolygonsDataFrame 格式,为DataFrame(数据帧)子类,也称为空间多边形数据帧library(ggplot2) #绘图核..._r语言在地图上绘制不同颜色散点图
文章浏览阅读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 向量夹角
文章浏览阅读502次,点赞20次,收藏3次。使用maven进行项目构建时报错,信息如下。_-source 1.5 中不支持 switch 中存在字符串
文章浏览阅读1.2k次。(1) 置换群 拉格朗日(2) 对称性(3) X= 0 这个是舒尔引理二,要背下来(4) 相同,这是重排定理(5) 这个题目讲了连续群在做(6) A(7) 相等(8) Z2群{1,-1}, 为阿贝尔群,D3群为非阿贝尔群二.(1) 封闭性,结合性,恒元,逆元(2) 不构成,没有逆元(3) 群表示矩阵的迹..._z2群
文章浏览阅读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配置
文章浏览阅读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班
文章浏览阅读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