4.6.0
Freundlich's C++ toolkit
|
Iterator adaptors and utilities.
There are five iterator categories. Each one dictates which operations an iterator needs to provide and what these operations mean:
Forward, bidirectional and random access iterators are also output iterators if they are not const iterators.
The standard library provides a tag type for each iterator category. std::random_access_iterator_tag
derives from std::bidirectional_iterator_tag
, which derives from std::forward_iterator_tag
, which derives from std::input_iterator_tag
. In this hierarchy, std::output_iterator_tag
is not used, meaning that this tag only comes into play when an iterator is an output iterator only.
For each category, a multitude of operations need to be implemented, a lot of which can be implemented from other operations, which commonly leads to a lot of boiler-plate code. For example, operator!=
can be implemented from operator==
, and operator<
(and <=
,>
and >=
) can be implemented from operator-
that calculates the distance of two random access iterators. However, you might want to provide fundamentally different implementations for all of these (for performance reasons), but this is very rare. To make implementing iterators easier, fcppt::iterator::base provides most operations using a default implementation, which the actual iterator type derives from. This class gets an fcppt::iterator::types as its template parameter, which consists of:
reference
type of the iterator, which is what operator*
returns. value_type
, which is what users of the iterator can use to store a copy of a dereferenced object. difference_type
, which is used to calculate distances between two iterators. This is only significant for random access iterator. Usually, this is std::ptrdiff_t
. iterator_category
. Deriving from fcppt::iterator::base also inherits all of these typedefs. In addition, pointer
is also defined which is always std::remove_reference<reference>::type *
, i.e. for forward iterators it is T *
if reference
is T &
and T const *
if reference
is T const &
for some type T
.
Let It
be the type of the iterator we are going to implement, i.e. the type deriving from fcppt::iterator::base. The following operations need to be implemented by the derived class as public member functions:
reference operator*() const | Returns the object at the current position. |
bool equal(It it) const | Returns true if *this and it point to the same position. For input and output iterators, this is only used to tell if they reached their end. |
void increment() | Moves the iterator to the next position. |
reference
must be an actual reference type. void decrement() | Moves the iterator to the previous position. This operation is the inverse to void increment() . |
void advance(difference_type d) | Moves the iterator forwards (backwards if d is negative) by d positions. This must be equal to d increment operations (-d decrement operations if d is negative). |
difference_type distance_to(It it) const | The distance d of *this to it , meaning that if *this is moved forwards by d positions, then *this and it are equal. |
void increment()
in terms of advance(1)
, void decrement()
in terms of advance(-1)
and bool equal_to(It it) const
as distance_to(it) == 0
. For the time being, this is not done so that the sets of operations to implement are consistent with the order of iterator categories.Here is an example of how to implement a random access iterator which is also an output iterator. For simplicity, we implement a simple iterator using pointers over int
. First, we declare the types we are going to use:
Next, we derive from fcppt::iterator::base and implement all operations required for random access iterators:
Here is an example showing how our iterator can be used:
Classes | |
class | fcppt::iterator::base< Types > |
A template for implementing iterators. More... | |
class | fcppt::iterator::range< Iterator > |
A range formed from two iterators. More... | |
struct | fcppt::iterator::types< Derived, ValueType, Reference, DifferenceType, IteratorCategory > |
The types passed to fcppt::iterator::base. More... | |
Typedefs | |
template<typename Category , typename CategoryRef > | |
using | fcppt::iterator::category_at_least = std::is_base_of<CategoryRef, Category> |
Checks if an iterator category includes another. | |
Functions | |
template<typename Iterator1 , typename Iterator2 > requires (std::is_same_v<std::remove_cvref_t<Iterator1>, std::remove_cvref_t<Iterator2>>) | |
fcppt::iterator::range< std::remove_cvref_t< Iterator1 > > | fcppt::iterator::make_range (Iterator1 &&_begin, Iterator2 &&_end) |
Makes an iterator range. | |
using fcppt::iterator::category_at_least = std::is_base_of<CategoryRef, Category> |
Checks if an iterator category includes another.
Checks if Category models CategoryRef. For example, if Category is std::bidirectional_iterator_category
and CategoryRef is std::forward_iterator_category
, then the value is true.
Category | Must be one of the std:: iterator category classes. |
CategoryRef | Must be one of the std:: iterator category classes. |
|
inline |
Makes an iterator range.