How does C++'s STL library achieve type distinction

1. Problem background

Sometimes we write a general template class. In the implementation process, we need the types of template parameters, and perform corresponding algorithm operations according to which type. For example, the iterator offset algorithm tool advance of the STL library moves an iterator a given distance, and its template function signature is as follows:

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

Let me talk about the types of iterators in the STL library. There are Input, Output, Forward, Bidirectional, Random Access) 5 types of iterators. The stepping method of these iterators, that is, the operation algorithm is different.

1. Input type iterator (Input): You can only read elements forward one at a time, and return element values ​​one by one in this order. The client can only read the object it refers to, not write, and can only read it once. That is, iterators created only for read operations.

2. Output type iterator (Output): Contrary to Input iterator, it can only move forward, and the client can only write what it refers to, and only once. That is, iterators created only for write operations.

3. Forward iterator (forward): It can perform read and write operations in a correct interval. It has the characteristics of Input Iterator and Output Iterator, as well as the ability to iterate elements forward in a single step.

4. Bidirectional: On the basis of Forward Iterator, it provides the ability to iterate elements backward in a single step.

5. Random Access: It has all the functions of the above iterator and can perform arithmetic calculations like pointers.

Advance wants to implement these kinds of iterator offset operations, how does it recognize these iterator types? After all, from the perspective of template parameters, it is impossible to identify which iterator type IterT is. So how does the STL library do it?

2. Type tag (tag)

We know that in order to identify certain things, one of our methods is to give things a different mark from other things. C++ supports empty types, such as struct Dummy{};, which has unique class attributes. Therefore, using the empty type feature and inheriting the is-a feature can give a unique label to a certain class. This kind of label is called a label structure and can be understood as an identity ID. The system composed of these tags can be called a type system.

C++ STL provides five corresponding types of tags for the iterator types in the above 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 {};

Therefore, using the type extraction (traits) technology provided by C++ can identify these five iterator types, and implement the corresponding iterator offset algorithm according to different types.

Guess you like

Origin blog.csdn.net/xunye_dream/article/details/114778113