iterator_facade for C++20
- Free software: CC0
- Documentation: https://iterator-facade.readthedocs.io.
- Workaround for Clang bug
constexpr
support- automatic deduction of iterator category
- specialized
std::iterator_traits
for iterators subclassingiterator_facade
- no need to specify any other types unlike
boost::iterator_facade
- propagated
noexcept
- works with sentinels
- possible to wrap contiguous iterators and preserve contiguousness
Copy paste the single header into your project
#include <iterator>
#include <iterator_facade/iterator_facade.hpp>
namespace iterf = iterator_facade;
template <std::input_or_output_iterator Iter>
class my_iterator : public iterf:iterator_facade<my_iterator<Iter>, std::contiguous_iterator<Iter>> {
template <std::input_or_output_iterator>
friend class my_iterator;
public:
using value_type = std::iter_value_t<Iter>;
using reference = std::iter_reference_t<Iter>;
using difference_type = std::iter_difference_t<Iter>;
constexpr my_iterator() noexcept(std::is_nothrow_constructible_v<Iter>) = default;
constexpr my_iterator(Iter iter) noexcept(std::is_nothrow_move_constructible_v<Iter>) : iter_(std::move(iter)) {}
template <class U>
requires(std::constructible_from<Iter, U> && !std::same_as<Iter, U>)
constexpr my_iterator(my_iterator<U> const& other) noexcept(std::is_nothrow_constructible_v<Iter, U>)
: iter_(other.iter_) {}
// Required:
[[nodiscard]] constexpr auto dereference() const noexcept(iterf::nothrow_dereference<Iter>) -> reference { return *iter_; }
constexpr void increment() noexcept(iterf::nothrow_increment<Iter>) { ++iter_; }
// For forward iterators:
template <std::sentinel_for<Iter> S>
[[nodiscard]] constexpr auto equals(my_iterator<S> const& sentinel) const noexcept(iterf::nothrow_equals<Iter, S>)
-> bool requires std::forward_iterator<Iter> {
return iter_ == sentinel.iter_;
}
// For bidirectional iterators:
constexpr void decrement() noexcept(iterf::nothrow_decrement<Iter>) requires std::bidirectional_iterator<Iter> { --iter_; }
// For random access iterators:
constexpr void advance(difference_type n) noexcept(iterf::nothrow_advance<Iter>) requires std::random_access_iterator<Iter> {
iter_ += n;
}
template <std::sized_sentinel_for<Iter> S>
[[nodiscard]] constexpr auto distance_to(my_iterator<S> const& sentinel) const noexcept(iterf::nothrow_distance_to<Iter, S>)
-> difference_type requires std::random_access_iterator<Iter> {
return sentinel.iter_ - iter_;
}
private:
Iter iter_;
};
Namespace can be customized by setting
ITERATOR_FACADE_NS
before including the headermy_iterator::dereference()
is not required to return lvalue references. However, the value returned should not be a reference to a value owned by the iterator itself as it can result in dangling references.my_iterator::advance(difference_type)
will be used in place of my_iterator::increment()
or my_iterator::decrement()
if any of them are not defined.my_iterator::distance_to(T)
will be used in place of my_iterator::equals(T)
if it is not defined.iterator_facade::iterator_facade<T>
will provide operators based on defined subclass methods:
dereference
will enableconstexpr auto T::operator*() const noexcept(...) -> reference
constexpr auto T::operator->() const noexcept(...) -> pointer
(a proxy object ifdereference
returns a temporary)
increment
oradvance
will enableconstexpr auto T::operator++() noexcept(...) -> T&
constexpr auto T::operator++(int) noexcept(...) -> T
equals
ordistance_to
will enableconstexpr friend auto operator==(T const&, sentinel const&) noexcept(...) -> bool
decrement
oradvance
will enableconstexpr auto T::operator--() noexcept(...) -> T&
constexpr auto T::operator--(int) noexcept(...) -> T
distance_to
will additionally enableconstexpr friend auto T::operator-(T const&, sized_sentinel const&) noexcept(...) -> difference_type
constexpr friend auto T::operator-(sized_sentinel const&, T const&) noexcept(...) -> difference_type
constexpr friend auto T::operator<=>(T const&, sentinel const&) noexcept(...)`
advance
will additionally enableconstexpr friend auto T::operator+(T, difference_type) noexcept(...) -> T
constexpr friend auto T::operator+(difference_type, T) noexcept(...) -> T
constexpr friend auto T::operator+=(T&, difference_type) noexcept(...) -> T&
constexpr friend auto T::operator-(T, difference_type) noexcept(...) -> T
constexpr friend auto T::operator-=(T&, difference_type) noexcept(...) -> T&
constexpr auto T::operator[](difference_type) const noexcept(...) -> reference
(will leave a dangling reference if it points to a value owned by the iterator)
This package was created with cookietemple using Cookiecutter.