[common.iterator] (original) (raw)

Class template common_iterator is an iterator/sentinel adaptor that is capable of representing a non-common range of elements (where the types of the iterator and sentinel differ) as a common range (where they are the same).

It does this by holding either an iterator or a sentinel, and implementing the equality comparison operators appropriately.

[Example 1: template<class ForwardIterator> void fun(ForwardIterator begin, ForwardIterator end); list<int> s;using CI = common_iterator<counted_iterator<list<int>::iterator>, default_sentinel_t>; fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel)); — _end example_]

namespace std { template<input_or_output_iterator I, sentinel_for<I> S> requires (same\_as<I, S> && copyable<I>) class common_iterator { public: constexpr common_iterator() requires default_initializable<I> = default;constexpr common_iterator(I i);constexpr common_iterator(S s);template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> && assignable_from<I&, const I2&> && assignable_from<S&, const S2&> constexpr common_iterator& operator=(const common_iterator<I2, S2>& x);constexpr decltype(auto) operator*();constexpr decltype(auto) operator*() const requires dereferenceable<const I>;constexpr auto operator->() const requires see below;constexpr common_iterator& operator++();constexpr decltype(auto) operator++(int);template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> && equality_comparable_with<I, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);template<sized_sentinel_for<I> I2, sized_sentinel_for<I> S2> requires sized_sentinel_for<S, I2> friend constexpr iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y);friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires input_iterator<I>;template<indirectly_swappable<I> I2, class S2> friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));private: variant<I, S> v_; };template<class I, class S> struct incrementable_traits<common_iterator<I, S>> { using difference_type = iter_difference_t<I>;};template<input_iterator I, class S> struct iterator_traits<common_iterator<I, S>> { using iterator_concept = see below;using iterator_category = see below; using value_type = iter_value_t<I>;using difference_type = iter_difference_t<I>;using pointer = see below;using reference = iter_reference_t<I>;};}