[iterators.common] # 24 Iterators library [[iterators]](./#iterators) ## 24.5 Iterator adaptors [[predef.iterators]](predef.iterators#iterators.common) ### 24.5.5 Common iterators [iterators.common] #### [24.5.5.1](#common.iterator) Class template common_iterator [[common.iterator]](common.iterator) [1](#common.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5414) 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)[.](#common.iterator-1.sentence-1) It does this by holding either an iterator or a sentinel, and implementing the equality comparison operators appropriately[.](#common.iterator-1.sentence-2) [2](#common.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5421) [*Note [1](#common.iterator-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[.](#common.iterator-2.sentence-1) — *end note*] [3](#common.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5427) [*Example [1](#common.iterator-example-1)*: templatevoid fun(ForwardIterator begin, ForwardIterator end); list s;// populate the list susing CI = common_iterator::iterator>, default_sentinel_t>;// call fun on a range of 10 ints fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel)); — *end example*] [🔗](#lib:common_iterator) namespace std {template<[input_or_output_iterator](iterator.concept.iterator#concept:input_or_output_iterator "24.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") S>requires (![same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]") && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"))class common_iterator {public:constexpr common_iterator() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr common_iterator(I i); constexpr common_iterator(S s); templaterequires [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")constexpr common_iterator(const common_iterator& x); templaterequires [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") &&[assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]") && [assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]")constexpr common_iterator& operator=(const common_iterator& x); constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() constrequires [*dereferenceable*](iterator.synopsis#concept:dereferenceable "24.2 Header  synopsis [iterator.synopsis]"); constexpr auto operator->() constrequires *see below*; constexpr common_iterator& operator++(); constexpr decltype(auto) operator++(int); template S2>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")friend constexpr bool operator==(const common_iterator& x, const common_iterator& y); template S2>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") && [equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")friend constexpr bool operator==(const common_iterator& x, const common_iterator& y); template<[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") I2, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") S2>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")friend constexpr iter_difference_t operator-(const common_iterator& x, const common_iterator& y); friend constexpr decltype(auto) iter_move(const common_iterator& i)noexcept(noexcept(ranges::iter_move(declval())))requires [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]"); template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]") I2, class S2>friend constexpr void iter_swap(const common_iterator& x, const common_iterator& y)noexcept(noexcept(ranges::iter_swap(declval(), declval()))); private: variant v_; // *exposition only*}; templatestruct incrementable_traits> {using difference_type = iter_difference_t; }; template<[input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]") I, class S>struct iterator_traits> {using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = iter_value_t; using difference_type = iter_difference_t; using pointer = *see below*; using reference = iter_reference_t; };} #### [24.5.5.2](#common.iter.types) Associated types [[common.iter.types]](common.iter.types) [1](#common.iter.types-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5513) The nested [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") iterator_category of the specialization of iterator_traits for common_iterator is defined if and only if iter_difference_t is an integral type[.](#common.iter.types-1.sentence-1) In that case,iterator_category denotes forward_iterator_tag if the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") iterator_traits​::​iterator_category is valid and denotes a type that models [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"); otherwise it denotes input_iterator_tag[.](#common.iter.types-1.sentence-2) [2](#common.iter.types-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5524) The remaining nested [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*s* of the specialization ofiterator_traits for common_iterator are defined as follows: - [(2.1)](#common.iter.types-2.1) iterator_concept denotes forward_iterator_tag if I models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"); otherwise it denotes input_iterator_tag[.](#common.iter.types-2.1.sentence-1) - [(2.2)](#common.iter.types-2.2) Let a denote an lvalue of type const common_iterator[.](#common.iter.types-2.2.sentence-1) If the expression a.operator->() is well-formed, then pointer denotes decltype(a.operator->())[.](#common.iter.types-2.2.sentence-2) Otherwise, pointer denotes void[.](#common.iter.types-2.2.sentence-3) #### [24.5.5.3](#common.iter.const) Constructors and conversions [[common.iter.const]](common.iter.const) [🔗](#lib:common_iterator,constructor) `constexpr common_iterator(I i); ` [1](#common.iter.const-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5548) *Effects*: Initializes v_ as if by v_{in_place_type, std​::​move(i)}[.](#common.iter.const-1.sentence-1) [🔗](#lib:common_iterator,constructor_) `constexpr common_iterator(S s); ` [2](#common.iter.const-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5559) *Effects*: Initializes v_ as if byv_{in_place_type, std​::​move(s)}[.](#common.iter.const-2.sentence-1) [🔗](#lib:common_iterator,constructor__) `template requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") constexpr common_iterator(const common_iterator& x); ` [3](#common.iter.const-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5573) *Hardened preconditions*: x.v_.valueless_by_exception() is false[.](#common.iter.const-3.sentence-1) [4](#common.iter.const-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5577) *Effects*: Initializes v_ as if byv_{in_place_index, get(x.v_)}, where i is x.v_.index()[.](#common.iter.const-4.sentence-1) [🔗](#lib:operator=,common_iterator) `template requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && [assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]") && [assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_­from [concept.assignable]") constexpr common_iterator& operator=(const common_iterator& x); ` [5](#common.iter.const-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5593) *Hardened preconditions*: x.v_.valueless_by_exception() is false[.](#common.iter.const-5.sentence-1) [6](#common.iter.const-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5597) *Effects*: Equivalent to: - [(6.1)](#common.iter.const-6.1) If v_.index() == x.v_.index(), thenget(v_) = get(x.v_)[.](#common.iter.const-6.1.sentence-1) - [(6.2)](#common.iter.const-6.2) Otherwise, v_.emplace(get(x.v_))[.](#common.iter.const-6.2.sentence-1) where i is x.v_.index()[.](#common.iter.const-6.sentence-2) [7](#common.iter.const-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5608) *Returns*: *this[.](#common.iter.const-7.sentence-1) #### [24.5.5.4](#common.iter.access) Accessors [[common.iter.access]](common.iter.access) [🔗](#lib:operator*,common_iterator) `constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires [dereferenceable](iterator.synopsis#concept:dereferenceable "24.2 Header  synopsis [iterator.synopsis]"); ` [1](#common.iter.access-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5623) *Hardened preconditions*: holds_alternative(v_) is true[.](#common.iter.access-1.sentence-1) [2](#common.iter.access-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5627) *Effects*: Equivalent to: return *get(v_); [🔗](#lib:operator-%3e,common_iterator) `constexpr auto operator->() const requires see below; ` [3](#common.iter.access-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5639) The expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is equivalent to:[indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2 Concept indirectly_­readable [iterator.concept.readable]") &&(requires(const I& i) { i.operator->(); } || is_reference_v> ||[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]"), iter_reference_t>) [4](#common.iter.access-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5648) *Hardened preconditions*: holds_alternative(v_) is true[.](#common.iter.access-4.sentence-1) [5](#common.iter.access-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5652) *Effects*: - [(5.1)](#common.iter.access-5.1) If I is a pointer type or if the expressionget(v_).operator->() is well-formed, equivalent to: return get(v_); - [(5.2)](#common.iter.access-5.2) Otherwise, if iter_reference_t is a reference type, equivalent to:auto&& tmp = *get(v_);return addressof(tmp); - [(5.3)](#common.iter.access-5.3) Otherwise, equivalent to:return *proxy*(*get(v_)); where*proxy* is the exposition-only class:class *proxy* { iter_value_t keep_; constexpr *proxy*(iter_reference_t&& x): keep_(std::move(x)) {}public:constexpr const iter_value_t* operator->() const noexcept {return addressof(keep_); }}; #### [24.5.5.5](#common.iter.nav) Navigation [[common.iter.nav]](common.iter.nav) [🔗](#lib:operator++,common_iterator) `constexpr common_iterator& operator++(); ` [1](#common.iter.nav-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5693) *Hardened preconditions*: holds_alternative(v_) is true[.](#common.iter.nav-1.sentence-1) [2](#common.iter.nav-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5697) *Effects*: Equivalent to ++get(v_)[.](#common.iter.nav-2.sentence-1) [3](#common.iter.nav-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5701) *Returns*: *this[.](#common.iter.nav-3.sentence-1) [🔗](#lib:operator++,common_iterator_) `constexpr decltype(auto) operator++(int); ` [4](#common.iter.nav-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5712) *Hardened preconditions*: holds_alternative(v_) is true[.](#common.iter.nav-4.sentence-1) [5](#common.iter.nav-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5716) *Effects*: If I models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"), equivalent to:common_iterator tmp = *this;++*this;return tmp; Otherwise, ifrequires(I& i) { { *i++ } -> [*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]"); } is true or[indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2 Concept indirectly_­readable [iterator.concept.readable]") && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]"), iter_reference_t> &&[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")> is false, equivalent to:return get(v_)++; Otherwise, equivalent to:*postfix-proxy* p(**this);++*this;return p; where *postfix-proxy* is the exposition-only class:class *postfix-proxy* { iter_value_t keep_; constexpr *postfix-proxy*(iter_reference_t&& x): keep_(std::forward>(x)) {}public:constexpr const iter_value_t& operator*() const noexcept {return keep_; }}; #### [24.5.5.6](#common.iter.cmp) Comparisons [[common.iter.cmp]](common.iter.cmp) [🔗](#lib:operator==,common_iterator) `template S2> requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") friend constexpr bool operator==( const common_iterator& x, const common_iterator& y); ` [1](#common.iter.cmp-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5767) *Hardened preconditions*: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false[.](#common.iter.cmp-1.sentence-1) [2](#common.iter.cmp-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5772) *Returns*: true if i == j, and otherwise get(x.v_) == get(y.v_), where i is x.v_.index() and j is y.v_.index()[.](#common.iter.cmp-2.sentence-1) [🔗](#lib:operator==,common_iterator_) `template S2> requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") && [equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]") friend constexpr bool operator==( const common_iterator& x, const common_iterator& y); ` [3](#common.iter.cmp-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5788) *Hardened preconditions*: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false[.](#common.iter.cmp-3.sentence-1) [4](#common.iter.cmp-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5793) *Returns*: true if i and j are each 1, and otherwiseget(x.v_) == get(y.v_), wherei is x.v_.index() and j is y.v_.index()[.](#common.iter.cmp-4.sentence-1) [🔗](#lib:operator-,common_iterator) `template<[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") I2, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") S2> requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") friend constexpr iter_difference_t operator-( const common_iterator& x, const common_iterator& y); ` [5](#common.iter.cmp-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5809) *Hardened preconditions*: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false[.](#common.iter.cmp-5.sentence-1) [6](#common.iter.cmp-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5814) *Returns*: 0 if i and j are each 1, and otherwiseget(x.v_) - get(y.v_), wherei is x.v_.index() and j is y.v_.index()[.](#common.iter.cmp-6.sentence-1) #### [24.5.5.7](#common.iter.cust) Customizations [[common.iter.cust]](common.iter.cust) [🔗](#lib:iter_move,common_iterator) `friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval()))) requires [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]"); ` [1](#common.iter.cust-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5831) *Hardened preconditions*: holds_alternative(i.v_) is true[.](#common.iter.cust-1.sentence-1) [2](#common.iter.cust-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5835) *Effects*: Equivalent to: return ranges​::​iter_move(get(i.v_)); [🔗](#lib:iter_swap,common_iterator) `template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]") I2, class S2> friend constexpr void iter_swap(const common_iterator& x, const common_iterator& y) noexcept(noexcept(ranges::iter_swap(declval(), declval()))); ` [3](#common.iter.cust-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5848) *Hardened preconditions*: holds_alternative(x.v_) and holds_alternative(y.v_) are each true[.](#common.iter.cust-3.sentence-1) [4](#common.iter.cust-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5853) *Effects*: Equivalent to ranges​::​iter_swap(get(x.v_), get(y.v_))[.](#common.iter.cust-4.sentence-1)