[range.concat] # 25 Ranges library [[ranges]](./#ranges) ## 25.7 Range adaptors [[range.adaptors]](range.adaptors#range.concat) ### 25.7.18 Concat view [range.concat] #### [25.7.18.1](#overview) Overview [[range.concat.overview]](range.concat.overview) [1](#overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8697) concat_view presents a view that concatenates all the underlying ranges[.](#overview-1.sentence-1) [2](#overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8700) The name views​::​concat denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#overview-2.sentence-1) Given a pack of subexpressions Es..., the expression views​::​concat(Es...) is expression-equivalent to - [(2.1)](#overview-2.1) views​::​all(Es...) if Es is a pack with only one element whose type models [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]"), - [(2.2)](#overview-2.2) otherwise, concat_view(Es...)[.](#overview-2.sentence-2) [*Example [1](#overview-example-1)*: vector v1{1, 2, 3}, v2{4, 5}, v3{}; array a{6, 7, 8};auto s = views::single(9);for (auto&& i : views::concat(v1, v2, v3, a, s)) { print("{} ", i); // prints 1 2 3 4 5 6 7 8 9} — *end example*] #### [25.7.18.2](#view) Class template concat_view [[range.concat.view]](range.concat.view) [🔗](#lib:concat_view) namespace std::ranges {templateusing *concat-reference-t* = common_reference_t...>; // *exposition only*templateusing *concat-value-t* = common_type_t...>; // *exposition only*templateusing *concat-rvalue-reference-t* = // *exposition only* common_reference_t...>; templateconcept [*concat-indirectly-readable*](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]") = *see below*; // *exposition only*templateconcept [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]") = *see below*; // *exposition only*templateconcept [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]") = *see below*; // *exposition only*templateconcept [*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]") = *see below*; // *exposition only*template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")... Views>requires ([view](range.view#concept:view "25.4.5 Views [range.view]") && ...) && (sizeof...(Views) > 0) &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")class concat_view : public view_interface> { tuple *views_*; // *exposition only*// [[range.concat.iterator]](#iterator "25.7.18.3 Class concat_­view​::​iterator"), class template concat_view​::​*iterator*template class *iterator*; // *exposition only*public:constexpr concat_view() = default; constexpr explicit concat_view(Views... views); constexpr *iterator* begin() requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ...)); constexpr *iterator* begin() constrequires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ...) && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"); constexpr auto end() requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ...)); constexpr auto end() constrequires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ...) && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"); constexpr auto size() requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && ...); constexpr auto size() const requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && ...); }; template concat_view(R&&...) -> concat_view...>;} [🔗](#concept:concat-indirectly-readable) `template concept [concat-indirectly-readable](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]") = see below; // exposition only ` [1](#view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8780) The exposition-only [*concat-indirectly-readable*](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]") concept is equivalent to:templateconcept [*concat-indirectly-readable-impl*](#concept:concat-indirectly-readable-impl "25.7.18.2 Class template concat_­view [range.concat.view]") = // *exposition only*requires (const It it) {{ *it } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); { ranges::iter_move(it) } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); }; templateconcept [*concat-indirectly-readable*](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]") = // *exposition only*[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<*concat-reference-t*&&, *concat-value-t*&> &&[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<*concat-reference-t*&&, *concat-rvalue-reference-t*&&> &&[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<*concat-rvalue-reference-t*&&, *concat-value-t* const&> &&([*concat-indirectly-readable-impl*](#concept:concat-indirectly-readable-impl "25.7.18.2 Class template concat_­view [range.concat.view]")<*concat-reference-t*, *concat-rvalue-reference-t*, iterator_t> && ...); [🔗](#concept:concatable) `template concept [concatable](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]") = see below; // exposition only ` [2](#view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8811) The exposition-only [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]") concept is equivalent to:templateconcept [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]") = requires { // *exposition only*typename *concat-reference-t*; typename *concat-value-t*; typename *concat-rvalue-reference-t*; } && [*concat-indirectly-readable*](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]"); [🔗](#concept:concat-is-random-access) `template concept [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]") = see below; // exposition only ` [3](#view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8829) Let Fs be the pack that consists of all elements of Rs except the last element, then *concat-is-random-access* is equivalent to:templateconcept [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]") = // *exposition only*[*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]") &&([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ...); [🔗](#concept:concat-is-bidirectional) `template concept [concat-is-bidirectional](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]") = see below; // exposition only ` [4](#view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8848) Let Fs be the pack that consists of all elements of Rs except the last element, then *concat-is-bidirectional* is equivalent to:templateconcept [*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]") = // *exposition only*[*all-bidirectional*](range.adaptor.helpers#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]") &&([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ...); [🔗](#lib:concat_view,constructor) `constexpr explicit concat_view(Views... views); ` [5](#view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8867) *Effects*: Initializes *views_* with std​::​move(views)...[.](#view-5.sentence-1) [🔗](#lib:begin,concat_view) `constexpr iterator begin() requires (!([simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ...)); constexpr iterator begin() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ...) && [concatable](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [6](#view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8880) *Effects*: Let *is-const* betrue for the const-qualified overload, andfalse otherwise[.](#view-6.sentence-1) Equivalent to:*iterator*<*is-const*> it(this, in_place_index<0>, ranges::begin(std::get<0>(*views_*))); it.template *satisfy*<0>();return it; [🔗](#lib:end,concat_view) `constexpr auto end() requires (!([simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ...)); constexpr auto end() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ...) && [concatable](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [7](#view-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8901) *Effects*: Let *is-const* betrue for the const-qualified overload, andfalse otherwise[.](#view-7.sentence-1) Equivalent to:constexpr auto N = sizeof...(Views);if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<*is-const*, Views...[N - 1]>>) {return *iterator*<*is-const*>(this, in_place_index, ranges::end(std::get(*views_*)));} else {return default_sentinel;} [🔗](#lib:size,concat_view) `constexpr auto size() requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && ...); constexpr auto size() const requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && ...); ` [8](#view-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8925) *Effects*: Equivalent to:return apply([](auto... sizes) {using CT = *make-unsigned-like-t*>; return (CT(sizes) + ...); }, *tuple-transform*(ranges::size, *views_*)); #### [25.7.18.3](#iterator) Class concat_view​::​*iterator* [[range.concat.iterator]](range.concat.iterator) [🔗](#lib:iterator,concat_view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")... Views>requires ([view](range.view#concept:view "25.4.5 Views [range.view]") && ...) && (sizeof...(Views) > 0) &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")templateclass concat_view::*iterator* {public:using iterator_category = *see below*; // not always presentusing iterator_concept = *see below*; using value_type = *concat-value-t*<*maybe-const*...>; using difference_type = common_type_t>...>; private:using *base-iter* = // *exposition only* variant>...>; *maybe-const** *parent_* = nullptr; // *exposition only**base-iter* *it_*; // *exposition only*templateconstexpr void *satisfy*(); // *exposition only*templateconstexpr void *prev*(); // *exposition only*templateconstexpr void *advance-fwd*(difference_type offset, // *exposition only* difference_type steps); templateconstexpr void *advance-bwd*(difference_type offset, // *exposition only* difference_type steps); templateconstexpr explicit *iterator*(*maybe-const** parent, // *exposition only* Args&&... args)requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<*base-iter*, Args&&...>; public:*iterator*() = default; constexpr *iterator*(*iterator* i)requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t> && ...); constexpr decltype(auto) operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int)requires [*all-forward*](range.adaptor.helpers#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); constexpr *iterator*& operator--()requires [*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]"); constexpr *iterator* operator--(int)requires [*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]"); constexpr *iterator*& operator+=(difference_type n)requires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); constexpr *iterator*& operator-=(difference_type n)requires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); constexpr decltype(auto) operator[](difference_type n) constrequires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); friend constexpr bool operator==(const *iterator*& x, const *iterator*& y)requires ([equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")>> && ...); friend constexpr bool operator==(const *iterator*& it, default_sentinel_t); friend constexpr bool operator<(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires ([*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]") &&([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>> && ...)); friend constexpr *iterator* operator+(const *iterator*& it, difference_type n)requires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); friend constexpr *iterator* operator+(difference_type n, const *iterator*& it)requires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); friend constexpr *iterator* operator-(const *iterator*& it, difference_type n)requires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); friend constexpr difference_type operator-(const *iterator*& x, default_sentinel_t)requires *see below*; friend constexpr difference_type operator-(default_sentinel_t, const *iterator*& x)requires *see below*; friend constexpr decltype(auto) iter_move(const *iterator*& it) noexcept(*see below*); friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y) noexcept(*see below*)requires *see below*; };} [1](#iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9035) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#iterator-1.1) If[*concat-is-random-access*](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]") is modeled, then iterator_concept denotes random_access_iterator_tag[.](#iterator-1.1.sentence-1) - [(1.2)](#iterator-1.2) Otherwise, if[*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]") is modeled, then iterator_concept denotes bidirectional_iterator_tag[.](#iterator-1.2.sentence-1) - [(1.3)](#iterator-1.3) Otherwise, if[*all-forward*](range.adaptor.helpers#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled, then iterator_concept denotes forward_iterator_tag[.](#iterator-1.3.sentence-1) - [(1.4)](#iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#iterator-1.4.sentence-1) [2](#iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9054) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") iterator_category is defined if and only if[*all-forward*](range.adaptor.helpers#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled[.](#iterator-2.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(2.1)](#iterator-2.1) Ifis_reference_v<*concat-reference-t*<*maybe-const*...>> is false, then iterator_category denotes input_iterator_tag[.](#iterator-2.1.sentence-1) - [(2.2)](#iterator-2.2) Otherwise, let Cs denote the pack of typesiterator_traits>>​::​iterator_category...[.](#iterator-2.2.sentence-1) * [(2.2.1)](#iterator-2.2.1) If([derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") && ...) && *concat-is-random-access* is true,iterator_category denotes random_access_iterator_tag[.](#iterator-2.2.1.sentence-1) * [(2.2.2)](#iterator-2.2.2) Otherwise, if([derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") && ...) && *concat-is-bidirectional* is true,iterator_category denotes bidirectional_iterator_tag[.](#iterator-2.2.2.sentence-1) * [(2.2.3)](#iterator-2.2.3) Otherwise, if([derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") && ...) is true,iterator_category denotes forward_iterator_tag[.](#iterator-2.2.3.sentence-1) * [(2.2.4)](#iterator-2.2.4) Otherwise, iterator_category denotes input_iterator_tag[.](#iterator-2.2.4.sentence-1) [🔗](#lib:satisfy,concat_view::iterator) `template constexpr void satisfy(); ` [3](#iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9100) *Effects*: Equivalent to:if constexpr (N < (sizeof...(Views) - 1)) {if (std::get(*it_*) == ranges::end(std::get(*parent_*->*views_*))) {*it_*.template emplace(ranges::begin(std::get(*parent_*->*views_*))); *satisfy*(); }} [🔗](#lib:prev,concat_view::iterator) `template constexpr void prev(); ` [4](#iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9120) *Effects*: Equivalent to:if constexpr (N == 0) {--std::get<0>(*it_*);} else {if (std::get(*it_*) == ranges::begin(std::get(*parent_*->*views_*))) {*it_*.template emplace(ranges::end(std::get(*parent_*->*views_*))); *prev*(); } else {--std::get(*it_*); }} [🔗](#lib:advance-fwd,concat_view::iterator) `template constexpr void advance-fwd(difference_type offset, difference_type steps); ` [5](#iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9144) *Effects*: Equivalent to:using underlying_diff_type = iter_difference_t>;if constexpr (N == sizeof...(Views) - 1) { std::get(*it_*) += static_cast(steps);} else {auto n_size = ranges::distance(std::get(*parent_*->*views_*)); if (offset + steps < n_size) { std::get(*it_*) += static_cast(steps); } else {*it_*.template emplace(ranges::begin(std::get(*parent_*->*views_*))); *advance-fwd*(0, offset + steps - n_size); }} [🔗](#lib:advance-bwd,concat_view::iterator) `template constexpr void advance-bwd(difference_type offset, difference_type steps); ` [6](#iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9170) *Effects*: Equivalent to:using underlying_diff_type = iter_difference_t>;if constexpr (N == 0) { std::get(*it_*) -= static_cast(steps);} else {if (offset >= steps) { std::get(*it_*) -= static_cast(steps); } else {auto prev_size = ranges::distance(std::get(*parent_*->*views_*)); *it_*.template emplace(ranges::end(std::get(*parent_*->*views_*))); *advance-bwd*(prev_size, steps - offset); }} [🔗](#lib:concat_view::iterator,constructor) `template constexpr explicit iterator(maybe-const* parent, Args&&... args) requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]"); ` [7](#iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9198) *Effects*: Initializes *parent_* with parent, and initializes *it_* with std​::​forward(args)...[.](#iterator-7.sentence-1) [🔗](#lib:concat_view::iterator,constructor_) `constexpr iterator(iterator it) requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t> && ...); ` [8](#iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9212) *Preconditions*: it.*it_*.valueless_by_exception() is false[.](#iterator-8.sentence-1) [9](#iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9216) *Effects*: Initializes *parent_* with it.*parent_*, and let i be it.*it_*.index(), initializes *it_* with*base-iter*(in_place_index, std​::​get(std​::​move(it.*it_*)))[.](#iterator-9.sentence-1) [🔗](#lib:operator*,concat_view::iterator) `constexpr decltype(auto) operator*() const; ` [10](#iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9230) *Preconditions*: *it_*.valueless_by_exception() is false[.](#iterator-10.sentence-1) [11](#iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9234) *Effects*: Equivalent to:using reference = *concat-reference-t*<*maybe-const*...>;return std::visit([](auto&& it) -> reference { return *it; }, *it_*); [🔗](#lib:operator++,concat_view::iterator) `constexpr iterator& operator++(); ` [12](#iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9250) *Preconditions*: *it_*.valueless_by_exception() is false[.](#iterator-12.sentence-1) [13](#iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9254) *Effects*: Let i be *it_*.index()[.](#iterator-13.sentence-1) Equivalent to:++std::get(*it_*);*satisfy*();return *this; [🔗](#lib:operator++,concat_view::iterator_) `constexpr void operator++(int); ` [14](#iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9271) *Effects*: Equivalent to:++*this; [🔗](#lib:operator++,concat_view::iterator__) `constexpr iterator operator++(int) requires [all-forward](range.adaptor.helpers#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [15](#iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9286) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,concat_view::iterator) `constexpr iterator& operator--() requires [concat-is-bidirectional](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [16](#iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9303) *Preconditions*: *it_*.valueless_by_exception() is false[.](#iterator-16.sentence-1) [17](#iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9307) *Effects*: Let i be *it_*.index()[.](#iterator-17.sentence-1) Equivalent to:*prev*();return *this; [🔗](#lib:operator--,concat_view::iterator_) `constexpr iterator operator--(int) requires [concat-is-bidirectional](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [18](#iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9324) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,concat_view::iterator) `constexpr iterator& operator+=(difference_type n) requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [19](#iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9341) *Preconditions*: *it_*.valueless_by_exception() is false[.](#iterator-19.sentence-1) [20](#iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9345) *Effects*: Let i be *it_*.index()[.](#iterator-20.sentence-1) Equivalent to:if (n > 0) {*advance-fwd*(std::get(*it_*) - ranges::begin(std::get(*parent_*->*views_*)), n);} else if (n < 0) {*advance-bwd*(std::get(*it_*) - ranges::begin(std::get(*parent_*->*views_*)), -n);}return *this; [🔗](#lib:operator-=,concat_view::iterator) `constexpr iterator& operator-=(difference_type n) requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [21](#iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9366) *Effects*: Equivalent to:*this += -n;return *this; [🔗](#lib:operator%5b%5d,concat_view::iterator) `constexpr decltype(auto) operator[](difference_type n) const requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [22](#iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9382) *Effects*: Equivalent to:return *((*this) + n); [🔗](#lib:operator==,concat_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y) requires ([equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")>> && ...); ` [23](#iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9397) *Preconditions*: x.*it_*.valueless_by_exception() andy.*it_*.valueless_by_exception() are each false[.](#iterator-23.sentence-1) [24](#iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9402) *Effects*: Equivalent to:return x.*it_* == y.*it_*; [🔗](#lib:operator==,concat_view::iterator_) `friend constexpr bool operator==(const iterator& it, default_sentinel_t); ` [25](#iterator-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9416) *Preconditions*: it.*it_*.valueless_by_exception() is false[.](#iterator-25.sentence-1) [26](#iterator-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9420) *Effects*: Equivalent to:constexpr auto last_idx = sizeof...(Views) - 1;return it.*it_*.index() == last_idx && std::get(it.*it_*) == ranges::end(std::get(it.*parent_*->*views_*)); [🔗](#lib:operator%3c,concat_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr bool operator>(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires ([all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]") && ([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>> && ...)); ` [27](#iterator-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9446) *Preconditions*: x.*it_*.valueless_by_exception() andy.*it_*.valueless_by_exception() are each false[.](#iterator-27.sentence-1) [28](#iterator-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9451) Let op be the operator[.](#iterator-28.sentence-1) [29](#iterator-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9454) *Effects*: Equivalent to:return x.*it_* op y.*it_*; [🔗](#lib:operator+,concat_view::iterator) `friend constexpr iterator operator+(const iterator& it, difference_type n) requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [30](#iterator-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9469) *Effects*: Equivalent to:auto temp = it; temp += n;return temp; [🔗](#lib:operator+,concat_view::iterator_) `friend constexpr iterator operator+(difference_type n, const iterator& it) requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [31](#iterator-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9486) *Effects*: Equivalent to:return it + n; [🔗](#lib:operator-,concat_view::iterator) `friend constexpr iterator operator-(const iterator& it, difference_type n) requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [32](#iterator-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9501) *Effects*: Equivalent to:auto temp = it; temp -= n;return temp; [🔗](#lib:operator-,concat_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [concat-is-random-access](#concept:concat-is-random-access "25.7.18.2 Class template concat_­view [range.concat.view]"); ` [33](#iterator-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9518) *Preconditions*: x.*it_*.valueless_by_exception() andy.*it_*.valueless_by_exception() are each false[.](#iterator-33.sentence-1) [34](#iterator-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9523) *Effects*: Letix denote x.*it_*.index() andiy denote y.*it_*.index()[.](#iterator-34.sentence-1) - [(34.1)](#iterator-34.1) If ix > iy, letdy beranges​::​distance(std​::​get(y.*it_*), ranges​::​end(std​::​get(y.*parent_*->*views_*))),dx beranges​::​distance(ranges​::​begin(std​::​get(x.*parent_*->*views_*)), std​::​get(x.*it_*)). Let s denote the sum of the sizes of all the rangesstd​::​get(x.*parent_*->*views_*) for every integer i in the range [iy + 1, ix) if there is any, and0 otherwise, of type difference_type, equivalent to:return dy + s + dx; - [(34.2)](#iterator-34.2) otherwise, if ix < iy is true, equivalent to:return -(y - x); - [(34.3)](#iterator-34.3) otherwise, equivalent to:return std::get(x.*it_*) - std::get(y.*it_*); [🔗](#lib:operator-,concat_view::iterator__) `friend constexpr difference_type operator-(const iterator& x, default_sentinel_t) requires see below; ` [35](#iterator-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9571) *Preconditions*: x.*it_*.valueless_by_exception() is false[.](#iterator-35.sentence-1) [36](#iterator-36) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9575) *Effects*: Letix denote x.*it_*.index(),dx beranges​::​distance(std​::​get(x.*it_*), ranges​::​end(std​::​get(x.*parent_*->*views_*)))[.](#iterator-36.sentence-1) Let s denote the sum of the sizes of all the rangesstd​::​get(x.*parent_*->*views_*) for every integer i in the range [ix + 1, sizeof...(Views)) if there is any, and0 otherwise, of type difference_type, equivalent to:return -(dx + s); [37](#iterator-37) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9594) *Remarks*: Let Fs be the pack that consists of all elements of Views except the first element, the expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is equivalent to:([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")>, iterator_t<*maybe-const*>> && ...) &&([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*> && ...) [🔗](#lib:operator-,concat_view::iterator___) `friend constexpr difference_type operator-(default_sentinel_t, const iterator& x) requires see below; ` [38](#iterator-38) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9614) *Effects*: Equivalent to:return -(x - default_sentinel); [39](#iterator-39) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9621) *Remarks*: Let Fs be the pack that consists of all elements of Views except the first element, the expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is equivalent to:([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")>, iterator_t<*maybe-const*>> && ...) &&([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*> && ...) [🔗](#lib:iter_move,concat_view::iterator) `friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below); ` [40](#iterator-40) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9639) *Preconditions*: it.*it_*.valueless_by_exception() is false[.](#iterator-40.sentence-1) [41](#iterator-41) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9643) *Effects*: Equivalent to:return std::visit([](const auto& i)-> *concat-rvalue-reference-t*<*maybe-const*...> {return ranges::iter_move(i); }, it.*it_*); [42](#iterator-42) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9654) *Remarks*: The exception specification is equivalent to:((is_nothrow_invocable_v>&> && is_nothrow_convertible_v>, *concat-rvalue-reference-t*<*maybe-const*...>>) &&...) [🔗](#lib:iter_swap,concat_view::iterator) `friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below) requires see below; ` [43](#iterator-43) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9673) *Preconditions*: x.*it_*.valueless_by_exception() andy.*it_*.valueless_by_exception() are each false[.](#iterator-43.sentence-1) [44](#iterator-44) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9678) *Effects*: Equivalent to:std::visit([&](const auto& it1, const auto& it2) {if constexpr (is_same_v) { ranges::iter_swap(it1, it2); } else { ranges::swap(*x, *y); }}, x.*it_*, y.*it_*); [45](#iterator-45) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9692) *Remarks*: The exception specification is equivalent to(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its))) where its is a pack of lvalues of typeconst iterator_t<*maybe-const*> respectively[.](#iterator-45.sentence-1) The expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is equivalent to[swappable_with](concept.swappable#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]"), iter_reference_t<*iterator*>> &&(... && [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>>)