C++的STL库如何做到类型区分

一、问题背景

有时候写一个通用的模板类,在实现过程中我们需要模板参数的类型,根据是哪类类型进行相应的算法操作。比如,关于STL库的迭代器偏移算法工具advance将某个迭代器移动给定的距离,其模板函数签名如下:

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d);

先说说STL库中迭代器的类型,有输入型迭代器(Input)、输出型迭代器(Output)、前向迭代器(forward)、双向迭代器(Bidirectional)、随机存取迭代器(Random Access)5种迭代器类型。这些迭代器的步进方式,即操作算法是不一样的。

1、输入型迭代器(Input):只能一次一个向前读取元素,按此顺序一个个传回元素值。客户只能读取它所指的对象,不可以写入,而且只能读取一次。即,只为读操作创造的迭代器。

2、输出型迭代器(Output):于Input迭代器相反,只能向前移动,客户只能写入它所指的内容,且只能写一次。即,只为写操作创造的迭代器。

3、前向迭代器(forward):可以在一个正确的区间中进行读写操作,它拥有Input Iterator和Output Iterator的特性,以及单步向前迭代元素的能力。

4、双向迭代器(Bidirectional):在Forward Iterator的基础上提供了单步向后迭代元素的能力。

5、随机存取迭代器(Random Access):拥有上述迭代器的所有功能,并且可以像指针那样进行算术计算。

advance要实现这些种类的迭代器偏移操作,它是如何识别这些迭代器类型的呢?毕竟从模板参数来看是没法识别IterT是那种迭代器类型的。那么STL库是如何做到的呢?

二、类型标签(tag)

我们知道要想识别某种事物,我们的一种做法是给事物弄个与其他事物不同的标记。C++支持空类型,如struct Dummy{};,它具有独特的类属性。于是,利用空类型特性加上继承is-a特性就可以给某一类打上独特的标签,这种标签称为标签结构体,可以理解为身份ID。这些标签组成的体系,可以称为类型系统。

C++ STL为上述5中迭代器类型提供了对应的五种类型标签:

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : input_iterator_tag {};
struct bidirectional_iterator_tag : forward_iterator_tag {};
struct random_access_iterator_tag : bidirectional_iterator_tag {};

于是,利用C++提供的类型萃取(traits)技术就可以识别出这五种迭代器类型,根据不同的类型,实现对应的迭代器偏移算法。

猜你喜欢

转载自blog.csdn.net/xunye_dream/article/details/114778113