[iterators.common] (original) (raw)

23 Iterators library [iterators]

23.5 Iterator adaptors [predef.iterators]

23.5.4 Common iterators [iterators.common]

23.5.4.1 Class template common_­iterator [common.iterator]

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.

[Note 1:

The common_­iterator type is useful for interfacing with legacy code that expects the begin and end of a range to have the same type.

— _end note_]

[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() = 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&> common_iterator& operator=(const common_iterator<I2, S2>& x);decltype(auto) operator*();decltype(auto) operator*() const requires dereferenceable<const I>;decltype(auto) operator->() const requires see below; common_iterator& operator++();decltype(auto) operator++(int);template<class I2, sentinel_­for<I> S2> requires sentinel_­for<S, I2> friend 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 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 iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y);friend iter_rvalue_reference_t<I> 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 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>;};}

23.5.4.2 Associated types [common.iter.types]

The nested typedef-names of the specialization ofiterator_­traits for common_­iterator<I, S> are defined as follows.

23.5.4.3 Constructors and conversions [common.iter.const]

constexpr common_iterator(I i);

Effects: Initializes v_­ as if by v_­{in_­place_­type<I>, std​::​move(i)}.

constexpr common_iterator(S s);

Effects: Initializes v_­ as if byv_­{in_­place_­type<S>, std​::​move(s)}.

template<class I2, class S2> requires [convertible_­to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const I2&, I> && [convertible_­to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);

Preconditions: x.v_­.valueless_­by_­exception() is false.

Effects: Initializes v_­ as if byv_­{in_­place_­index<i>, get<i>(x.v_­)}, where i is x.v_­.index().

Preconditions: x.v_­.valueless_­by_­exception() is false.

Effects: Equivalent to:

where i is x.v_­.index().

23.5.4.4 Accessors [common.iter.access]

decltype(auto) operator*();decltype(auto) operator*() const requires [_dereferenceable_](iterator.synopsis#concept:dereferenceable "23.2 Header <iterator> synopsis [iterator.synopsis]")<const I>;

Preconditions: holds_­alternative<I>(v_­).

Effects: Equivalent to: return *get<I>(v_­);

decltype(auto) operator->() const requires _see below_;

Preconditions: holds_­alternative<I>(v_­).

Effects:

23.5.4.5 Navigation [common.iter.nav]

common_iterator& operator++();

Preconditions: holds_­alternative<I>(v_­).

Effects: Equivalent to ++get<I>(v_­).

decltype(auto) operator++(int);

Preconditions: holds_­alternative<I>(v_­).

Effects: If I models forward_­iterator, equivalent to:common_iterator tmp = *this;++*this;return tmp;

Otherwise, equivalent to: return get<I>(v_­)++;

23.5.4.6 Comparisons [common.iter.cmp]

template<class I2, [sentinel_­for](iterator.concept.sentinel#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S2> requires [sentinel_­for](iterator.concept.sentinel#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);

Preconditions: x.v_­.valueless_­by_­exception() and y.v_­.valueless_­by_­exception()are each false.

Returns: true if i == j, and otherwise get<i>(x.v_­) == get<j>(y.v_­), where i is x.v_­.index() and j is y.v_­.index().

template<class I2, [sentinel_­for](iterator.concept.sentinel#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S2> requires [sentinel_­for](iterator.concept.sentinel#concept:sentinel%5Ffor "23.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I2> && equality_comparable_with<I, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);

Preconditions: x.v_­.valueless_­by_­exception() and y.v_­.valueless_­by_­exception()are each false.

Returns: true if i and j are each 1, and otherwiseget<i>(x.v_­) == get<j>(y.v_­), wherei is x.v_­.index() and j is y.v_­.index().

Preconditions: x.v_­.valueless_­by_­exception() and y.v_­.valueless_­by_­exception()are each false.

Returns: 0 if i and j are each 1, and otherwiseget<i>(x.v_­) - get<j>(y.v_­), wherei is x.v_­.index() and j is y.v_­.index().

23.5.4.7 Customizations [common.iter.cust]

friend iter_rvalue_reference_t<I> iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires [input_­iterator](iterator.concept.input#concept:input%5Fiterator "23.3.4.9 Concept input_­iterator [iterator.concept.input]")<I>;

Preconditions: holds_­alternative<I>(v_­).

Effects: Equivalent to: return ranges​::​iter_­move(get<I>(i.v_­));

template<[indirectly_­swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "23.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<I> I2, class S2> friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));

Preconditions: holds_­alternative<I>(x.v_­) and holds_­alternative<I2>(y.v_­)are each true.

Effects: Equivalent to ranges​::​iter_­swap(get<I>(x.v_­), get<I2>(y.v_­)).