![]() |
MySQL 9.6.0
Source Code Documentation
|
Code documentation: Ranges.
This library provides general-purpose C++ range definitions. Currently it is the following:
buffer_interface.h: the class Buffer_interface is a CRTP base class/mixin, which given implementations of data and size, provides the members begin, end, operator bool, empty, string_view; subscript operator; comparison operators; std::hash; variants of all member functions that use unsigned char or std::byte instead of char; and ssize that returns ptrdiff_t (signed) instead of size_t. The resulting class satisfies std::ranges::range.
User-defined classes that behave like character buffers can inherit from this class to provide a richer and more easily used API.
While all member functions have default implementations, for example empty returns true if the size() member of the user-defined class returns 0, the user-defined class can override functions for which it can provide faster implementations.
collection_interface.h: the class Collection_interface is an enhanced version of std::ranges::view_interface: this is a CRTP base class/mixin, which given implementations of begin() and end(), provides the members [c][r]begin(), [c][r]end(), [s]size(), empty(), operator!(), operator bool(), front(), back(), data(), operator[]. We need this because not all compilers we build on (as of 2025) have implemented std::ranges::view_interface yet, and also because we want the C++23 extensions and some non-standard extensions.
User-defined classes that behave like collections of objects can inherit from this class to provide a richer and more easily used API. The interface will provide only those member functions that match the iterator type, so [c]rbegin, [c]rend, and back are available only for bidirectional iterators; operator[] only for random access iterators, and data only for contiguous iterators.
While all member functions have default implementations, for example size uses std::ranges::distance with the begin and end iterators, the user-defined class can override functions for which is can provide faster implementations.
disjoint_pairs_view.h: The classes Disjoint_pairs_interface, Disjoint_pairs_view, and Disjoint_pairs_interface are a CRTP base class/mixin, a view, and an iterator. Given an even-length sequence, they provides a sequence of half the length consisting of pairs from the original sequence.
Algorithms that need to inspect elements of a range pair-by-pair can use this as a convenience.
This is optimized for minimizing the number of iterator advancements: it always caches an iterator to the first element of the pair, and lazily caches an iterator to the second element of the pair whenever that is needed.
iterator_with_range.h: The class Iterator_with_range is a wrapper around an iterator, which provides members to get a reference to the source range. In particular, unlike iterators in general, this iterator knows whether it is positioned at the end.
Algorithms that operate on iterators, and sometimes need to either access the underlying range or just test if an iterator has reached the end, can use this class to bundle all they need in one object, rather than having to use two objects.
This is designed to work even in cases where the end iterator may sometimes be invalidated; in particular, it does not cache the end iterator, but gets it from the container each time the user queries if the iterator has reached the end.
flat_view.h: Given a nested data structure, such as set<vector<map<float, list<int>>>>, the class Flat_view<set<vector<map<float, list<int>>>>> provides a linear range view over a sequence over the innermost elements, the ints. If any of the containers are empty, they are omitted.
This is usable whenever an algorithm needs to process only the innermost elements of a nested data structure. The algorithm only needs to be implemented for flat ranges; users can pass the flat view of the nested data structures to it.
It is designed so that:
vector or list, the begin and end iterators can be used directly; for key-value data structures such as map or unordered_map, you can instruct the view to use only the second component (which it may in turn flatten). See also Mapped_view below.The first property may require iterating over multiple empty data structures. The skipping of empty data structures occurs when constructing the begin iterator and when advancing the iterator; those operations are therefore not worst-case constant-time. Comparison and dereference require only a constant number of evaluations of the underlying iterators.
meta.h: metaprogramming features (type aliases and concepts) to determine if a class is a collection, and extract iterator and value types from it.
This is usable in class and function templates that need to restrict the types they operate on, or in code that needs to deduce the iterator or value type from a container or from an iterator.
projection_views.h: Defines the views Key_view<R> and Mapped_view<R>. For a given range R over pairs, they provide views over only the first component and only the second component, respectively. For example, the iterator Key_view<std::map<K, M>> yields values of type K, whereas Mapped_view<std::map<K, M>> yields values of type M. Also Projection_view<N, R> provides a view over the Nth component of tuple-like objects. And for an iterator I over pairs/tuple-like objects, Key_iterator<I>, Mapped_iterator<I> and Projection_iterator<N, I> are the iterators.
These are usable in algorithms that need to iterate over just the keys or values of a view. In particular, Mapped_view is usable with Flat_view to unfold the second component of the pairs from a map.
transform_view.h: Defines the view Transform_view<T, R>. For a given range R and transformation T, it provides iterators over transformed elements.
This is usable in algorithms that need to apply a function to each element of a range.
view_sources.h: Support types to be used in view classes and their iterators, for members holding (references to) the view's source(s). The types intend to prevent dangling references by using the following rule:
"Views and their iterators shall represent sources that are views by-value, and sources that are not views by-reference."
The concept std::ranges::view<T> identifies that a source T is a view. See below for details about the dangling reference problem. This header provides the following types:
View_source<T>: Class for view sources. The internal representation is T if std::ranges::view<T>, and const T * otherwise.Optional_view_source<T>: Class for view sources that are optional. The internal representation of the source is std::optional<T> if std::ranges::view<T>, andconst T * otherwise. The API is similar to std::optional<T>. When this does not hold a source object, it behaves as if the source object is an empty range.Raw_view_source<T>: Type alias for view sources, equal to T if std::ranges::view<T> and T & otherwise. This is a more simplistic variant of View_source. However, View_source is default-constructible if T is, whereas T& is not default-constructible. Therefore, View_source is preferred for views that need to be default-constructible.This is usable in any user-defined view or user-defined iterator that needs to hold references to an underlying source.
In the following discussion, we use the following terminology (part of which is a special case of standard terminology such as std::ranges::view).
The potential issues with dangling references occur when a view references its source, or when a view's iterators reference the view's source or the view's source's iterators. The summary is that, while user must ensure that primary views outlive their source, a secondary view must hold copies of its source to prevent dangling references. This prevents dangling references in chains. More precisely: