![]() |
MySQL 9.6.0
Source Code Documentation
|
Code documentation: Iterators.
This library provides helper functionality for defining custom iterators:
Iterator_interface makes it easy to define iterator types that meet the C++ standard library iterator named requirements and concepts. See below for details.Empty_sequence_iterator is an iterator over an empty sequence of a given (default-constructible) type.Iterator_concept_tag gives the type tag for the strongest iterator concept satisfied by an iterator.Is_declared_legacy_input_iterator and similar concepts determine if an iterator, through std::iterator_traits<It>iterator_category, is declared to satisfy each of the legacy iterator named requirementsnull_iterator.h: The function template null_iterator returns an iterator object for a given source type, created without passing a source object, while guaranteeing that two such iterators for the same type compare as equal.
The use case is a view which does not have a source: then the view can return null iterators its their begin and end member functions, making it behave as a view over an empty range.
Note that default-constructed iterators do not generally work in this case, because comparison for default-constructed standard library iterators is undefined behavior.
To define, for example, a random access iterator, it suffices to inherit from Iterator_interface and define 3 functions. This interface is already unit-tested and carefully designed to satisfy both the semantic and the syntactic iterator requirements. It works the same way whether the iterator returns by-value or by-reference.
In contrast, to define a random access iterator without inheriting from Iterator_interface, requires:
Iterator_interface can be used to define input iterators, forward iterators, bidirectional iterators, random access iterators, or contiguous iterators. Given appropriate functions implemented by the user, the library deduces both the correct standard named requirement (LegacyInputIterator, LegacyForwardIterator, LegacyBidirectionalIterator, or LegacyRandomAccessIterator) and makes it satisfy the standard C++20 concept (std::input_iterator, std::forward_iterator, std::bidirectional_iterator, std::random_access_iterator, or std::contiguous_iterator).
The benefits of the library are greater for the more advanced iterators. For all categories, the library saves repetitive and error-prone work, and requires less knowledge about standard library details, compared to an iterator implementation without the library.
To make It an iterator that iterates over values of type V, inherit like:
It must be default-constructible, copy/move-constructible, and copy/move-assignable. In addition, define a subset of the following member functions:
C++ defines two hierarchies of iterators, which are confusingly similar and subtly different:
LegacyInputIterator, which can be queried at compile-time using std::iterator_traits<It>iterator_category.std::input_iterator, which can be queried at compile-time using these concepts.This class deduces both the iterator category and the iterator concept, as follows:
LegacyInputIterator requries any get or get_pointer function, either next or advance, and either is_equal or distance_from.LegacyForwardIterator requries LegacyInputIterator, and that get returns by reference, and the class must be copyable.LegacyBidirectionalIterator requires LegacyForwardIterator, and either prev or advance.LegacyRandomAccessIterator requries LegacyBidirectionalIterator, and advance, and distance_from.LegacyContiguousIterator requries LegacyRandomAccessIterator, and requires get_pointer.std::input_iterator requries any get or get_pointer function, and either next or advance. (It is weaker than LegacyInputIterator because it does not require that iterators can be compared.)std::forward_iterator requries std::input_iterator, and either is_equal or distance_from, and the class must be copyable. (It is weaker than LegacyForwardIterator because it does not require that get returns by reference.)std::bidirectional_iterator requries std::forward_iterator, and either prev or advance. (It is weaker than LegacyBidirectionalIterator because it does not require that get returns by reference.)std::random_access_iterator requires std::bidirectional_iterator, and advance and distance_from. (It is weaker than LegacyRandomAccessIterator because it does not require that get returns by reference.)std::contiguous_iterator requires std::random_access_iterator, and requires get_pointer. This coincides with the requirements for LegacyContiguousIterator.To summarize the previous section, the following diagram illustrates the relative strengths between deduced iterator concepts and categories for types derived from this class. The notation A-->B indicates that B is stronger that A, i.e., requires everything that A requires and more. The abbreviations I/F/B/R/C/ct/cy mean input/forward/bidirectional/random_access/contiguous/concept/category, respectively.
Each arrow is annotated by a number that refers to the following list, indicating what you need to implement to "follow the arrow": (1) Implement is_equal to make iterators equality-comparable. (2) Implement the copy constructor (actually, just don't delete it). (3) Make get return by reference. (4) Implement prev to enable moving backwards. (5) Implement advance and distance_from instead of get/next/is_equal, to make it possible to take long steps. (6) Implement get_pointer and ensure that returned objects are adjacent in memory.
Iterators that return value rather than reference can't meet the LegacyForwardIterator requirement. This determines the behavior of standard algorithms like std::prev, std::advance, and std::distance. Thus, just because the iterator returns by value, both std::advance(it, negative_number) and std::prev produce undefined behavior (typically an infinite loop), and std::distance is linear-time (even if the iterator satisfies std::random_access_iterator). Use std::ranges::prev, std::ranges::advance, and std::ranges::distance instead.
If your iterator needs a sentinel type, this class limits it to be the mysql::iterators::Default_sentinel type. Define one or both of the member functions is_sentinel or distance_from_sentinel.