Difference between revisions of "cpp/iterator/reverse iterator"
m (→Example: "Stack" size: 4 -> 8 to show that it may not be "full" to be traversable (h'm). It's a pity std::stack doesn't have begin/end (at least constexpr-conditionally)...) |
(New iterator concepts relax the requirements) |
||
Line 109: | Line 109: | ||
===Notes=== | ===Notes=== | ||
− | {{tt|std::reverse_iterator}} does not work with iterators whose dereference returns a reference to a member of {{tt|*this}} (so-called "stashing iterators"). An example of a stashing iterator is {{ltt|cpp/filesystem/path#Member_types_and_constants|std::filesystem::path::iterator}}. | + | {{rrev|until=c++20|{{tt|std::reverse_iterator}} does not work with iterators whose dereference returns a reference to a member of {{tt|*this}} (so-called "stashing iterators"). An example of a stashing iterator is {{ltt|cpp/filesystem/path#Member_types_and_constants|std::filesystem::path::iterator}}.}} |
===Example=== | ===Example=== |
Revision as of 01:57, 20 July 2021
Defined in header <iterator>
|
||
template< class Iter > class reverse_iterator; |
||
std::reverse_iterator
is an iterator adaptor that reverses the direction of a given iterator, which must be at least a LegacyBidirectionalIterator or model bidirectional_iterator
(since C++20). In other words, when provided with a bidirectional iterator, std::reverse_iterator
produces a new iterator that moves from the end to the beginning of the sequence defined by the underlying bidirectional iterator.
For a reverse iterator r
constructed from an iterator i
, the relationship &*r == &*(i-1) is always true (as long as r
is dereferenceable); thus a reverse iterator constructed from a one-past-the-end iterator dereferences to the last element in a sequence.
This is the iterator returned by member functions rbegin()
and rend()
of the standard library containers.
Contents |
Member types
|
(until C++20) | ||||||||||||||||
|
(since C++20) |
Member types |
(until C++17) |
Member functions
constructs a new iterator adaptor (public member function) | |
assigns another iterator adaptor (public member function) | |
accesses the underlying iterator (public member function) | |
accesses the pointed-to element (public member function) | |
accesses an element by index (public member function) | |
advances or decrements the iterator (public member function) |
Member objects
Member name | Definition |
current (protected)
|
the underlying iterator of which base() returns a copy
|
Non-member functions
compares the underlying iterators (function template) | |
advances the iterator (function template) | |
computes the distance between two iterator adaptors (function template) | |
(C++20) |
casts the result of dereferencing the adjusted underlying iterator to its associated rvalue reference type (function) |
(C++20) |
swaps the objects pointed to by two adjusted underlying iterators (function template) |
(C++14) |
creates a std::reverse_iterator of type inferred from the argument (function template) |
Helper templates
template< class Iterator1, class Iterator2 > requires (!std::sized_sentinal_for<Iterator1, Iterator2>) |
(since C++20) | |
This partial specialization of std::disable_sentinel_for
prevents specializations of reverse_iterator
from satisfying sized_sentinel_for
if their underlying iterators do not satisfy the concept.
Possible implementation
Below is a partial implementation focusing on the way the inner iterator is saved, calling prev only when the content is fetched via operator*.
template<typename Itr> class reverse_iterator { Itr itr; public: constexpr explicit reverse_iterator(Itr itr): itr(itr) {} constexpr auto& operator*() { return *std::prev(itr); // <== returns the content of prev } constexpr auto& operator++() { --itr; return *this; } constexpr friend bool operator!=(reverse_iterator<Itr> a, reverse_iterator<Itr> b) { return a.itr != b.itr; } }; |
Notes
|
(until C++20) |
Example
#include <iostream> #include <iterator> template<typename T, size_t SIZE> class Stack { T arr[SIZE]; size_t pos = 0; public: T pop() { return arr[--pos]; } Stack& push(const T& t) { arr[pos++] = t; return *this; } // we wish that looping on Stack would be in LIFO order // thus we use std::reverse_iterator as an adaptor to existing iterators // (which are in this case the simple pointers: [arr, arr+pos) auto begin() { return std::reverse_iterator(arr + pos); } auto end() { return std::reverse_iterator(arr); } }; int main() { Stack<int, 8> s; s.push(5).push(15).push(25).push(35); for(int val: s) { std::cout << val << ' '; } }
Output:
35 25 15 5
See also
(C++14) |
creates a std::reverse_iterator of type inferred from the argument (function template) |
(deprecated in C++17) |
base class to ease the definition of required types for simple iterators (class template) |