Tatooine
Public Types | Public Member Functions | Private Member Functions | Friends | List of all members
tatooine::iterator_facade< Iter > Class Template Reference

C++20 implementation of an iterator facade. More...

#include <iterator_facade.h>

Inheritance diagram for tatooine::iterator_facade< Iter >:
[legend]

Public Types

using iterator_type = Iter
 
using this_type = iterator_facade< iterator_type >
 

Public Member Functions

auto operator* () const -> decltype(auto)
 
auto operator-> () const
 
auto operator++ () -> auto &
 
auto operator++ (int)
 
auto operator-- () -> auto &
 
auto operator-- (int)
 
auto operator[] (difference_type_arg< iterator_type > auto pos) -> decltype(auto)
 

Private Member Functions

auto as_derived () -> auto &
 
auto as_derived () const -> auto const &
 

Friends

auto operator+ (iterator_type left, difference_type_arg< iterator_type > auto const off)
 
auto operator+= (iterator_type &self, difference_type_arg< iterator_type > auto const offset) -> auto &
 
auto operator+ (difference_type_arg< iterator_type > auto const offset, iterator_type right)
 
auto operator- (iterator_type left, difference_type_arg< iterator_type > auto off)
 
auto operator-= (iterator_type &left, difference_type_arg< iterator_type > auto off) -> auto &
 
auto operator-= (iterator_type &left, iter_sentinel_arg< iterator_type > auto sentinel) -> auto &
 
auto operator- (iterator_type const &left, iterator_type const &right)
 
auto operator- (iterator_type const &left, iter_sentinel_arg< iterator_type > auto const right)
 
auto operator- (iter_sentinel_arg< iterator_type > auto const right, iterator_type const &left)
 
auto operator<=> (iterator_type const &left, iterator_type const &right)
 
auto operator== (iterator_type const &left, iterator_type const &right)
 
auto operator!= (iterator_type const &left, iterator_type const &right)
 
auto operator== (iterator_type const &iter, iter_sentinel_arg< iterator_type > auto const) -> bool
 
auto operator!= (iterator_type const &iter, iter_sentinel_arg< iterator_type > auto const) -> bool
 
auto operator== (iter_sentinel_arg< iterator_type > auto const, iterator_type const &iter) -> bool
 
auto operator!= (iter_sentinel_arg< iterator_type > auto const, iterator_type const &iter) -> bool
 

Detailed Description

template<typename Iter>
class tatooine::iterator_facade< Iter >

C++20 implementation of an iterator facade.

Code originally taken from here: https://vector-of-bool.github.io/2020/06/13/cpp20-iter-facade.html

iterator_facade uses CRTP for inheritance.

It automatically infers value_type (see infer_value_type), difference_type (see infer_difference_type), iterator_category, reference and pointer in the std::iterator_traits. Alternatively value_type can be explicitely specified in the iterator implementation. difference_type can be implicitely specified by implementing a distance_to method.

The implementation needs at least the methods dereference, increment, equal and a default constructor.

One can also use sentinels by specifying the type sentinel_type in the iterator implementation. With this your iterator implementation needs to specify an equal method.

This is an example of how to implement an iterator class with help of iterator_facade:

#include <tatooine/vec.h>
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
//==============================================================================
using namespace tatooine;
//==============================================================================
// Range that uses iterators that inherit from iterator_facade.
struct my_range {
// Iterator implementation.
// It uses a sentinel as end.
struct iterator : iterator_facade<iterator> {
struct sentinel_type {};
std::size_t m_vh{};
// CTORS
constexpr iterator() =
default; // ITERATORS NEED TO BE DEFAULT-CONSTRUCTIBLE!!!
constexpr explicit iterator(std::size_t const vh) : m_vh{vh} {}
constexpr iterator(iterator const&) = default;
constexpr iterator(iterator&&) noexcept = default;
// Assign ops
constexpr auto operator=(iterator const&) -> iterator& = default;
constexpr auto operator=(iterator&&) noexcept -> iterator& = default;
// DTOR
~iterator() = default;
constexpr auto increment() { ++m_vh; }
constexpr auto decrement() { --m_vh; }
[[nodiscard]] constexpr auto dereference() const { return m_vh; }
[[nodiscard]] constexpr auto equal(iterator other) const {
return m_vh == other.m_vh;
}
[[nodiscard]] constexpr auto at_end() const { return m_vh == 10; }
};
static constexpr auto begin() { return iterator{std::size_t{0}}; }
static constexpr auto end() { return typename iterator::sentinel_type{}; }
};
//==============================================================================
// With this you can use rvalues with `operator|`
template <>
inline constexpr const bool std::ranges::enable_borrowed_range<my_range> = true;
//==============================================================================
auto main() -> int {
auto v = std::vector<std::size_t>{};
auto r = my_range{};
for (auto i : r) {
std::cout << i << '\n';
}
auto square = [](auto const x) { return x * x; };
using namespace std::ranges;
// use borrowed range
copy(my_range{} | views::transform(square), std::back_inserter(v));
copy(r | views::transform(square), std::back_inserter(v));
for (auto i : v) {
std::cout << i << '\n';
}
using it_traits = std::iterator_traits<my_range::iterator>;
std::cout << "iterator_category: "
<< type_name<it_traits::iterator_category>() << '\n';
std::cout << "reference: " << type_name<it_traits::reference>()
<< '\n';
std::cout << "pointer: " << type_name<it_traits::pointer>() << '\n';
std::cout << "value_type: " << type_name<it_traits::value_type>()
<< '\n';
std::cout << "difference_type: " << type_name<it_traits::difference_type>()
<< '\n';
}
// OUTPUT:
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 0
// 1
// 4
// 9
// 16
// 25
// 36
// 49
// 64
// 81
// 0
// 1
// 4
// 9
// 16
// 25
// 36
// 49
// 64
// 81
// iterator_category: std::bidirectional_iterator_tag
// reference: unsigned long
// pointer: tatooine::arrow_proxy<unsigned long>
// value_type: unsigned long
// difference_type: long
C++20 implementation of an iterator facade.
Definition: iterator_facade.h:154
Definition: algorithm.h:6
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322

Member Typedef Documentation

◆ iterator_type

template<typename Iter >
using tatooine::iterator_facade< Iter >::iterator_type = Iter

◆ this_type

template<typename Iter >
using tatooine::iterator_facade< Iter >::this_type = iterator_facade<iterator_type>

Member Function Documentation

◆ as_derived() [1/2]

template<typename Iter >
auto tatooine::iterator_facade< Iter >::as_derived ( ) -> auto &
inlineprivate

◆ as_derived() [2/2]

template<typename Iter >
auto tatooine::iterator_facade< Iter >::as_derived ( ) const -> auto const &
inlineprivate

◆ operator*()

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator* ( ) const -> decltype(auto)
inline

◆ operator++() [1/2]

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator++ ( ) -> auto &
inline

◆ operator++() [2/2]

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator++ ( int  )
inline

◆ operator--() [1/2]

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator-- ( ) -> auto &
inline

◆ operator--() [2/2]

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator-- ( int  )
inline

◆ operator->()

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator-> ( ) const
inline

◆ operator[]()

template<typename Iter >
auto tatooine::iterator_facade< Iter >::operator[] ( difference_type_arg< iterator_type > auto  pos) -> decltype(auto)
inline

Friends And Related Function Documentation

◆ operator!= [1/3]

template<typename Iter >
auto operator!= ( iter_sentinel_arg< iterator_type > auto const  ,
iterator_type const &  iter 
) -> bool
friend

◆ operator!= [2/3]

template<typename Iter >
auto operator!= ( iterator_type const &  iter,
iter_sentinel_arg< iterator_type > auto const   
) -> bool
friend

◆ operator!= [3/3]

template<typename Iter >
auto operator!= ( iterator_type const &  left,
iterator_type const &  right 
)
friend

◆ operator+ [1/2]

template<typename Iter >
auto operator+ ( difference_type_arg< iterator_type > auto const  offset,
iterator_type  right 
)
friend

◆ operator+ [2/2]

template<typename Iter >
auto operator+ ( iterator_type  left,
difference_type_arg< iterator_type > auto const  off 
)
friend

◆ operator+=

template<typename Iter >
auto operator+= ( iterator_type self,
difference_type_arg< iterator_type > auto const  offset 
) -> auto &
friend

◆ operator- [1/4]

template<typename Iter >
auto operator- ( iter_sentinel_arg< iterator_type > auto const  right,
iterator_type const &  left 
)
friend

◆ operator- [2/4]

template<typename Iter >
auto operator- ( iterator_type const &  left,
iter_sentinel_arg< iterator_type > auto const  right 
)
friend

◆ operator- [3/4]

template<typename Iter >
auto operator- ( iterator_type const &  left,
iterator_type const &  right 
)
friend

◆ operator- [4/4]

template<typename Iter >
auto operator- ( iterator_type  left,
difference_type_arg< iterator_type > auto  off 
)
friend

◆ operator-= [1/2]

template<typename Iter >
auto operator-= ( iterator_type left,
difference_type_arg< iterator_type > auto  off 
) -> auto&
friend

◆ operator-= [2/2]

template<typename Iter >
auto operator-= ( iterator_type left,
iter_sentinel_arg< iterator_type > auto  sentinel 
) -> auto&
friend

◆ operator<=>

template<typename Iter >
auto operator<=> ( iterator_type const &  left,
iterator_type const &  right 
)
friend

◆ operator== [1/3]

template<typename Iter >
auto operator== ( iter_sentinel_arg< iterator_type > auto const  ,
iterator_type const &  iter 
) -> bool
friend

◆ operator== [2/3]

template<typename Iter >
auto operator== ( iterator_type const &  iter,
iter_sentinel_arg< iterator_type > auto const   
) -> bool
friend

◆ operator== [3/3]

template<typename Iter >
auto operator== ( iterator_type const &  left,
iterator_type const &  right 
)
friend

The documentation for this class was generated from the following file: