[range.adaptors] # 25 Ranges library [[ranges]](./#ranges) ## 25.7 Range adaptors [range.adaptors] ### [25.7.1](#general) General [[range.adaptors.general]](range.adaptors.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4177) Subclause [range.adaptors] defines [*range adaptors*](#def:range_adaptors), which are utilities that transform a range into a view with custom behaviors[.](#general-1.sentence-1) These adaptors can be chained to create pipelines of range transformations that evaluate lazily as the resulting view is iterated[.](#general-1.sentence-2) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4183) Range adaptors are declared in namespace std​::​ranges​::​views[.](#general-2.sentence-1) [3](#general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4186) The bitwise or operator is overloaded for the purpose of creating adaptor chain pipelines[.](#general-3.sentence-1) The adaptors also support function call syntax with equivalent semantics[.](#general-3.sentence-2) [4](#general-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4191) [*Example [1](#general-example-1)*: vector ints{0,1,2,3,4,5};auto even = [](int i) { return 0 == i % 2; };auto square = [](int i) { return i * i; };for (int i : ints | views::filter(even) | views::transform(square)) { cout << i << ' '; // prints 0 4 16} assert(ranges::equal(ints | views::filter(even), views::filter(ints, even))); — *end example*] ### [25.7.2](#range.adaptor.object) Range adaptor objects [[range.adaptor.object]](range.adaptor.object) [1](#range.adaptor.object-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4206) A [*range adaptor closure object*](#def:range_adaptor_closure_object) is a unary function object that accepts a range argument[.](#range.adaptor.object-1.sentence-1) For a range adaptor closure object C and an expression R such thatdecltype((R)) models [range](range.range#concept:range "25.4.2 Ranges [range.range]"), the following expressions are equivalent:C(R) R | C Given an additional range adaptor closure object D, the expression C | D produces another range adaptor closure object E[.](#range.adaptor.object-1.sentence-3) E is a perfect forwarding call wrapper ([[func.require]](func.require#term.perfect.forwarding.call.wrapper "22.10.4 Requirements")) with the following properties: - [(1.1)](#range.adaptor.object-1.1) Its target object is an object d of type decay_t direct-non-list-initialized with D[.](#range.adaptor.object-1.1.sentence-1) - [(1.2)](#range.adaptor.object-1.2) It has one bound argument entity, an object c of type decay_t direct-non-list-initialized with C[.](#range.adaptor.object-1.2.sentence-1) - [(1.3)](#range.adaptor.object-1.3) Its call pattern is d(c(arg)), where arg is the argument used in a function call expression of E[.](#range.adaptor.object-1.3.sentence-1) The expression C | D is well-formed if and only if the initializations of the state entities of E are all well-formed[.](#range.adaptor.object-1.sentence-5) [2](#range.adaptor.object-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4237) Given an object t of type T, where - [(2.1)](#range.adaptor.object-2.1) t is a unary function object that accepts a range argument, - [(2.2)](#range.adaptor.object-2.2) T models [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")>, - [(2.3)](#range.adaptor.object-2.3) T has no other base classes of type range_adaptor_closure for any other type U, and - [(2.4)](#range.adaptor.object-2.4) T does not model [range](range.range#concept:range "25.4.2 Ranges [range.range]") then the implementation ensures that t is a range adaptor closure object[.](#range.adaptor.object-2.sentence-1) [3](#range.adaptor.object-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4252) The template parameter D for range_adaptor_closure may be an incomplete type[.](#range.adaptor.object-3.sentence-1) If an expression of type cv D is used as an operand to the | operator,D shall be complete and model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")>[.](#range.adaptor.object-3.sentence-2) The behavior of an expression involving an object of type cv D as an operand to the | operator is undefined if overload resolution selects a program-defined operator| function[.](#range.adaptor.object-3.sentence-3) [4](#range.adaptor.object-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4263) If an expression of type cv U is used as an operand to the | operator, where U has a base class of type range_adaptor_closure for some type T other than U, the behavior is undefined[.](#range.adaptor.object-4.sentence-1) [5](#range.adaptor.object-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4269) The behavior of a program that adds a specialization for range_adaptor_closure is undefined[.](#range.adaptor.object-5.sentence-1) [6](#range.adaptor.object-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4273) A [*range adaptor object*](#def:range_adaptor_object) is a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types")) that accepts a [viewable_range](range.refinements#concept:viewable_range "25.4.6 Other range refinements [range.refinements]") as its first argument and returns a view[.](#range.adaptor.object-6.sentence-1) [7](#range.adaptor.object-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4278) If a range adaptor object accepts only one argument, then it is a range adaptor closure object[.](#range.adaptor.object-7.sentence-1) [8](#range.adaptor.object-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4282) If a range adaptor object adaptor accepts more than one argument, then let range be an expression such that decltype((range)) models [viewable_range](range.refinements#concept:viewable_range "25.4.6 Other range refinements [range.refinements]"), let args... be arguments such that adaptor(range, args...) is a well-formed expression as specified in the rest of subclause [range.adaptors], and let BoundArgs be a pack that denotes decay_t...[.](#range.adaptor.object-8.sentence-1) The expression adaptor(args...) produces a range adaptor closure object f that is a perfect forwarding call wrapper ([[func.require]](func.require#term.perfect.forwarding.call.wrapper "22.10.4 Requirements")) with the following properties: - [(8.1)](#range.adaptor.object-8.1) Its target object is a copy of adaptor[.](#range.adaptor.object-8.1.sentence-1) - [(8.2)](#range.adaptor.object-8.2) Its bound argument entities bound_args consist of objects of types BoundArgs... direct-non-list-initialized with std​::​forward(args)..., respectively[.](#range.adaptor.object-8.2.sentence-1) - [(8.3)](#range.adaptor.object-8.3) Its call pattern is adaptor(r, bound_args...), where r is the argument used in a function call expression of f[.](#range.adaptor.object-8.3.sentence-1) The expression adaptor(args...) is well-formed if and only if the initialization of the bound argument entities of the result, as specified above, are all well-formed[.](#range.adaptor.object-8.sentence-3) ### [25.7.3](#range.move.wrap) Movable wrapper [[range.move.wrap]](range.move.wrap) [1](#range.move.wrap-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4308) Many types in this subclause are specified in terms of an exposition-only class template *movable-box*[.](#range.move.wrap-1.sentence-1) *movable-box* behaves exactly like optional with the following differences: - [(1.1)](#range.move.wrap-1.1) *movable-box* constrains its type parameter T with[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") && is_object_v. - [(1.2)](#range.move.wrap-1.2) The default constructor of *movable-box* is equivalent to:constexpr *movable-box*() noexcept(is_nothrow_default_constructible_v)requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]"): *movable-box*{in_place} {} - [(1.3)](#range.move.wrap-1.3) If [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]") is not modeled, the copy assignment operator is equivalent to:constexpr *movable-box*& operator=(const *movable-box*& that)noexcept(is_nothrow_copy_constructible_v)requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") {if (this != addressof(that)) {if (that) emplace(*that); else reset(); }return *this;} - [(1.4)](#range.move.wrap-1.4) If [movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]") is not modeled, the move assignment operator is equivalent to:constexpr *movable-box*& operator=(*movable-box*&& that)noexcept(is_nothrow_move_constructible_v) {if (this != addressof(that)) {if (that) emplace(std::move(*that)); else reset(); }return *this;} [2](#range.move.wrap-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4354) *Recommended practice*: - [(2.1)](#range.move.wrap-2.1) If [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") is true,*movable-box* should store only a T if either T models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"), oris_nothrow_move_constructible_v && is_nothrow_copy_constructible_v is true[.](#range.move.wrap-2.1.sentence-1) - [(2.2)](#range.move.wrap-2.2) Otherwise, *movable-box* should store only a T if either T models [movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]") oris_nothrow_move_constructible_v is true[.](#range.move.wrap-2.2.sentence-1) ### [25.7.4](#range.nonprop.cache) Non-propagating cache [[range.nonprop.cache]](range.nonprop.cache) [1](#range.nonprop.cache-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4371) Some types in [range.adaptors] are specified in terms of an exposition-only class template *non-propagating-​cache*[.](#range.nonprop.cache-1.sentence-1) *non-propagating-cache* behaves exactly like optional with the following differences: - [(1.1)](#range.nonprop.cache-1.1) *non-propagating-cache* constrains its type parameter T with is_object_v. - [(1.2)](#range.nonprop.cache-1.2) The copy constructor is equivalent to:constexpr *non-propagating-cache*(const *non-propagating-cache*&) noexcept {} - [(1.3)](#range.nonprop.cache-1.3) The move constructor is equivalent to:constexpr *non-propagating-cache*(*non-propagating-cache*&& other) noexcept { other.reset();} - [(1.4)](#range.nonprop.cache-1.4) The copy assignment operator is equivalent to:constexpr *non-propagating-cache*& operator=(const *non-propagating-cache*& other) noexcept {if (addressof(other) != this) reset(); return *this;} - [(1.5)](#range.nonprop.cache-1.5) The move assignment operator is equivalent to:constexpr *non-propagating-cache*& operator=(*non-propagating-cache*&& other) noexcept { reset(); other.reset(); return *this;} - [(1.6)](#range.nonprop.cache-1.6) *non-propagating-cache* has an additional member function template specified as follows: [🔗](#range.nonprop.cache-1.6.itemdecl:1) `template constexpr T& emplace-deref(const I& i); // exposition only ` *Mandates*: The declaration T t(*i); is well-formed for some invented variable t[.](#range.nonprop.cache-1.6.sentence-2) [*Note [1](#range.nonprop.cache-note-1)*: If *i is a prvalue of type cv T, there is no requirement that it is movable ([[dcl.init.general]](dcl.init.general "9.5.1 General"))[.](#range.nonprop.cache-1.6.sentence-3) — *end note*] *Effects*: Calls reset()[.](#range.nonprop.cache-1.6.sentence-4) Then direct-non-list-initializes the contained value with *i[.](#range.nonprop.cache-1.6.sentence-5) *Postconditions*: *this contains a value[.](#range.nonprop.cache-1.6.sentence-6) *Returns*: A reference to the new contained value[.](#range.nonprop.cache-1.6.sentence-7) *Throws*: Any exception thrown by the initialization of the contained value[.](#range.nonprop.cache-1.6.sentence-8) *Remarks*: If an exception is thrown during the initialization of T,*this does not contain a value, and the previous value (if any) has been destroyed[.](#range.nonprop.cache-1.6.sentence-9) [2](#range.nonprop.cache-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4449) [*Note [2](#range.nonprop.cache-note-2)*: *non-propagating-cache* enables an input view to temporarily cache values as it is iterated over[.](#range.nonprop.cache-2.sentence-1) — *end note*] ### [25.7.5](#range.adaptor.helpers) Range adaptor helpers [[range.adaptor.helpers]](range.adaptor.helpers) namespace std::ranges {templateconstexpr auto *tuple-transform*(F&& f, Tuple&& t) { // *exposition only*return apply([&](Ts&&... elements) {return tuple...>(invoke(f, std::forward(elements))...); }, std::forward(t)); }templateconstexpr void *tuple-for-each*(F&& f, Tuple&& t) { // *exposition only* apply([&](Ts&&... elements) {(static_cast(invoke(f, std::forward(elements))), ...); }, std::forward(t)); }templateconstexpr T& *as-lvalue*(T&& t) { // *exposition only*return static_cast(t); }templateconcept [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]") = // *exposition only*([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ...); templateconcept [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]") = // *exposition only*([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ...); templateconcept [*all-forward*](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") = // *exposition only*([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ...);} ### [25.7.6](#range.all) All view [[range.all]](range.all) #### [25.7.6.1](#range.all.general) General [[range.all.general]](range.all.general) [1](#range.all.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4494) views​::​all returns a view that includes all elements of its range argument[.](#range.all.general-1.sentence-1) [2](#range.all.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4499) The name views​::​all denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.all.general-2.sentence-1) Given a subexpression E, the expressionviews​::​all(E) is expression-equivalent to: - [(2.1)](#range.all.general-2.1) *decay-copy*(E) if the decayed type of E models [view](range.view#concept:view "25.4.5 Views [range.view]")[.](#range.all.general-2.1.sentence-1) - [(2.2)](#range.all.general-2.2) Otherwise, ref_view{E} if that expression is well-formed[.](#range.all.general-2.2.sentence-1) - [(2.3)](#range.all.general-2.3) Otherwise, owning_view{E}[.](#range.all.general-2.3.sentence-1) #### [25.7.6.2](#range.ref.view) Class template ref_view [[range.ref.view]](range.ref.view) [1](#range.ref.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4515) ref_view is a view of the elements of some other range[.](#range.ref.view-1.sentence-1) [🔗](#lib:ref_view) namespace std::ranges {template<[range](range.range#concept:range "25.4.2 Ranges [range.range]") R>requires is_object_vclass ref_view : public view_interface> {private: R* *r_*; // *exposition only*public:template<[*different-from*](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") T>requires *see below*constexpr ref_view(T&& t); constexpr R& base() const { return **r_*; }constexpr iterator_t begin() const { return ranges::begin(**r_*); }constexpr sentinel_t end() const { return ranges::end(**r_*); }constexpr bool empty() constrequires requires { ranges::empty(**r_*); }{ return ranges::empty(**r_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(**r_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(**r_*); }constexpr auto data() const requires [contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]"){ return ranges::data(**r_*); }}; template ref_view(R&) -> ref_view;} [🔗](#lib:ref_view,constructor) `template<[different-from](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") T> requires see below constexpr ref_view(T&& t); ` [2](#range.ref.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4563) *Effects*: Initializes *r_* withaddressof(static_cast(std​::​forward(t)))[.](#range.ref.view-2.sentence-1) [3](#range.ref.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4568) *Remarks*: Let *FUN* denote the exposition-only functionsvoid *FUN*(R&);void *FUN*(R&&) = delete; The expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is equivalent to:[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") && requires { *FUN*(declval()); } #### [25.7.6.3](#range.owning.view) Class template owning_view [[range.owning.view]](range.owning.view) [1](#range.owning.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4583) owning_view is a move-only view of the elements of some other range[.](#range.owning.view-1.sentence-1) [🔗](#lib:owning_view) namespace std::ranges {template<[range](range.range#concept:range "25.4.2 Ranges [range.range]") R>requires [movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]") && (!*is-initializer-list*) // see [[range.refinements]](range.refinements "25.4.6 Other range refinements")class owning_view : public view_interface> {private: R *r_* = R(); // *exposition only*public: owning_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr owning_view(R&& t); owning_view(owning_view&&) = default; owning_view& operator=(owning_view&&) = default; constexpr R& base() & noexcept { return *r_*; }constexpr const R& base() const & noexcept { return *r_*; }constexpr R&& base() && noexcept { return std::move(*r_*); }constexpr const R&& base() const && noexcept { return std::move(*r_*); }constexpr iterator_t begin() { return ranges::begin(*r_*); }constexpr sentinel_t end() { return ranges::end(*r_*); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"){ return ranges::begin(*r_*); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"){ return ranges::end(*r_*); }constexpr bool empty() requires requires { ranges::empty(*r_*); }{ return ranges::empty(*r_*); }constexpr bool empty() const requires requires { ranges::empty(*r_*); }{ return ranges::empty(*r_*); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*r_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*r_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*r_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*r_*); }constexpr auto data() requires [contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]"){ return ranges::data(*r_*); }constexpr auto data() const requires [contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]"){ return ranges::data(*r_*); }};} [🔗](#lib:owning_view,constructor) `constexpr owning_view(R&& t); ` [2](#range.owning.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4645) *Effects*: Initializes *r_* with std​::​move(t)[.](#range.owning.view-2.sentence-1) ### [25.7.7](#range.as.rvalue) As rvalue view [[range.as.rvalue]](range.as.rvalue) #### [25.7.7.1](#range.as.rvalue.overview) Overview [[range.as.rvalue.overview]](range.as.rvalue.overview) [1](#range.as.rvalue.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4654) as_rvalue_view presents a view of an underlying sequence with the same behavior as the underlying sequence except that its elements are rvalues[.](#range.as.rvalue.overview-1.sentence-1) Some generic algorithms can be called with an as_rvalue_view to replace copying with moving[.](#range.as.rvalue.overview-1.sentence-2) [2](#range.as.rvalue.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4661) The name views​::​as_rvalue denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.as.rvalue.overview-2.sentence-1) Let E be an expression and let T be decltype((E))[.](#range.as.rvalue.overview-2.sentence-2) The expression views​::​as_rvalue(E) is expression-equivalent to: - [(2.1)](#range.as.rvalue.overview-2.1) views​::​all(E) ifT models [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") and[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"), range_reference_t> is true[.](#range.as.rvalue.overview-2.1.sentence-1) - [(2.2)](#range.as.rvalue.overview-2.2) Otherwise, as_rvalue_view(E)[.](#range.as.rvalue.overview-2.2.sentence-1) [3](#range.as.rvalue.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4676) [*Example [1](#range.as.rvalue.overview-example-1)*: vector words = {"the", "quick", "brown", "fox", "ate", "a", "pterodactyl"}; vector new_words; ranges::copy(words | views::as_rvalue, back_inserter(new_words)); // moves each string from words into new_words — *end example*] #### [25.7.7.2](#range.as.rvalue.view) Class template as_rvalue_view [[range.as.rvalue.view]](range.as.rvalue.view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")class [as_rvalue_view](#lib:as_rvalue_view "25.7.7.2 Class template as_­rvalue_­view [range.as.rvalue.view]") : public view_interface> { V *base_* = V(); // *exposition only*public: as_rvalue_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit as_rvalue_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")){ return move_iterator(ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"){ return move_iterator(ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return move_iterator(ranges::end(*base_*)); } else {return move_sentinel(ranges::end(*base_*)); }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return move_iterator(ranges::end(*base_*)); } else {return move_sentinel(ranges::end(*base_*)); }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") { return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") { return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }}; template as_rvalue_view(R&&) -> as_rvalue_view>;} [🔗](#lib:as_rvalue_view,constructor) `constexpr explicit as_rvalue_view(V base); ` [1](#range.as.rvalue.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4742) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.as.rvalue.view-1.sentence-1) ### [25.7.8](#range.filter) Filter view [[range.filter]](range.filter) #### [25.7.8.1](#range.filter.overview) Overview [[range.filter.overview]](range.filter.overview) [1](#range.filter.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4751) filter_view presents a view of the elements of an underlying sequence that satisfy a predicate[.](#range.filter.overview-1.sentence-1) [2](#range.filter.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4755) The name views​::​filter denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.filter.overview-2.sentence-1) Given subexpressions E and P, the expression views​::​filter(E, P) is expression-equivalent tofilter_view(E, P)[.](#range.filter.overview-2.sentence-2) [3](#range.filter.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4763) [*Example [1](#range.filter.overview-example-1)*: vector is{ 0, 1, 2, 3, 4, 5, 6 };auto evens = views::filter(is, [](int i) { return 0 == i % 2; });for (int i : evens) cout << i << ' '; // prints 0 2 4 6 — *end example*] #### [25.7.8.2](#range.filter.view) Class template filter_view [[range.filter.view]](range.filter.view) [🔗](#lib:filter_view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_vclass filter_view : public view_interface> {private: V *base_* = V(); // *exposition only**movable-box* *pred_*; // *exposition only*// [[range.filter.iterator]](#range.filter.iterator "25.7.8.3 Class filter_­view​::​iterator"), class filter_view​::​*iterator*class *iterator*; // *exposition only*// [[range.filter.sentinel]](#range.filter.sentinel "25.7.8.4 Class filter_­view​::​sentinel"), class filter_view​::​*sentinel*class *sentinel*; // *exposition only*public: filter_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit filter_view(V base, Pred pred); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr const Pred& pred() const; constexpr *iterator* begin(); constexpr auto end() {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"))return *iterator*{*this, ranges::end(*base_*)}; elsereturn *sentinel*{*this}; }}; template filter_view(R&&, Pred) -> filter_view, Pred>;} [🔗](#lib:filter_view,constructor) `constexpr explicit filter_view(V base, Pred pred); ` [1](#range.filter.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4822) *Effects*: Initializes *base_* with std​::​move(base) and initializes*pred_* with std​::​move(pred)[.](#range.filter.view-1.sentence-1) [🔗](#lib:pred,filter_view) `constexpr const Pred& pred() const; ` [2](#range.filter.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4834) *Effects*: Equivalent to: return **pred_*; [🔗](#lib:begin,filter_view) `constexpr iterator begin(); ` [3](#range.filter.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4845) *Preconditions*: *pred_*.has_value() is true[.](#range.filter.view-3.sentence-1) [4](#range.filter.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4849) *Returns*: {*this, ranges​::​find_if(*base_*, ref(**pred_*))}[.](#range.filter.view-4.sentence-1) [5](#range.filter.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4853) *Remarks*: In order to provide the amortized constant time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept when filter_view models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), this function caches the result within thefilter_view for use on subsequent calls[.](#range.filter.view-5.sentence-1) #### [25.7.8.3](#range.filter.iterator) Class filter_view​::​*iterator* [[range.filter.iterator]](range.filter.iterator) [🔗](#lib:filter_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_vclass filter_view::*iterator* {private: iterator_t *current_* = iterator_t(); // *exposition only* filter_view* *parent_* = nullptr; // *exposition only*public:using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = range_value_t; using difference_type = range_difference_t; *iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")> = default; constexpr *iterator*(filter_view& parent, iterator_t current); constexpr const iterator_t& base() const & noexcept; constexpr iterator_t base() &&; constexpr range_reference_t operator*() const; constexpr iterator_t operator->() constrequires [*has-arrow*](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]")> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")>; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); 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 range_rvalue_reference_t iter_move(const *iterator*& i)noexcept(noexcept(ranges::iter_move(i.*current_*))); friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)noexcept(noexcept(ranges::iter_swap(x.*current_*, y.*current_*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [1](#range.filter.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4910) Modification of the element a filter_view​::​*iterator* denotes is permitted, but results in undefined behavior if the resulting value does not satisfy the filter predicate[.](#range.filter.iterator-1.sentence-1) [2](#range.filter.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4915) *iterator*​::​iterator_concept is defined as follows: - [(2.1)](#range.filter.iterator-2.1) If V models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), theniterator_concept denotes bidirectional_iterator_tag[.](#range.filter.iterator-2.1.sentence-1) - [(2.2)](#range.filter.iterator-2.2) Otherwise, if V models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), theniterator_concept denotes forward_iterator_tag[.](#range.filter.iterator-2.2.sentence-1) - [(2.3)](#range.filter.iterator-2.3) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.filter.iterator-2.3.sentence-1) [3](#range.filter.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4927) 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 V models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.filter.iterator-3.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(3.1)](#range.filter.iterator-3.1) Let C denote the typeiterator_traits>​::​iterator_category[.](#range.filter.iterator-3.1.sentence-1) - [(3.2)](#range.filter.iterator-3.2) If C models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"), then iterator_category denotes bidirectional_iterator_tag[.](#range.filter.iterator-3.2.sentence-1) - [(3.3)](#range.filter.iterator-3.3) Otherwise, if C models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"), then iterator_category denotes forward_iterator_tag[.](#range.filter.iterator-3.3.sentence-1) - [(3.4)](#range.filter.iterator-3.4) Otherwise, iterator_category denotes C[.](#range.filter.iterator-3.4.sentence-1) [🔗](#lib:filter_view::iterator,constructor) `constexpr iterator(filter_view& parent, iterator_t current); ` [4](#range.filter.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4953) *Effects*: Initializes *current_* with std​::​move(current) and*parent_* with addressof(parent)[.](#range.filter.iterator-4.sentence-1) [🔗](#lib:base,filter_view::iterator) `constexpr const iterator_t& base() const & noexcept; ` [5](#range.filter.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4965) *Effects*: Equivalent to: return *current_*; [🔗](#lib:base,filter_view::iterator_) `constexpr iterator_t base() &&; ` [6](#range.filter.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4976) *Effects*: Equivalent to: return std​::​move(*current_*); [🔗](#lib:operator*,filter_view::iterator) `constexpr range_reference_t operator*() const; ` [7](#range.filter.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4987) *Effects*: Equivalent to: return **current_*; [🔗](#lib:operator-%3e,filter_view::iterator) `constexpr iterator_t operator->() const requires [has-arrow](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]")> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")>; ` [8](#range.filter.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L4999) *Effects*: Equivalent to: return *current_*; [🔗](#lib:operator++,filter_view::iterator) `constexpr iterator& operator++(); ` [9](#range.filter.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5010) *Effects*: Equivalent to:*current_* = ranges::find_if(std::move(++*current_*), ranges::end(*parent_*->*base_*), ref(**parent_*->*pred_*));return *this; [🔗](#lib:operator++,filter_view::iterator_) `constexpr void operator++(int); ` [10](#range.filter.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5026) *Effects*: Equivalent to ++*this[.](#range.filter.iterator-10.sentence-1) [🔗](#lib:operator++,filter_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.filter.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5037) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,filter_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.filter.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5053) *Effects*: Equivalent to:do--*current_*;while (!invoke(**parent_*->*pred_*, **current_*));return *this; [🔗](#lib:operator--,filter_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [13](#range.filter.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5070) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator==,filter_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]")>; ` [14](#range.filter.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5087) *Effects*: Equivalent to: return x.*current_* == y.*current_*; [🔗](#lib:iter_move,filter_view::iterator) `friend constexpr range_rvalue_reference_t iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); ` [15](#range.filter.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5099) *Effects*: Equivalent to: return ranges​::​iter_move(i.*current_*); [🔗](#lib:iter_swap,filter_view::iterator) `friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [16](#range.filter.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5112) *Effects*: Equivalent to ranges​::​iter_swap(x.*current_*, y.*current_*)[.](#range.filter.iterator-16.sentence-1) #### [25.7.8.4](#range.filter.sentinel) Class filter_view​::​*sentinel* [[range.filter.sentinel]](range.filter.sentinel) [🔗](#lib:filter_view::sentinel) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_vclass filter_view::*sentinel* {private: sentinel_t *end_* = sentinel_t(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(filter_view& parent); constexpr sentinel_t base() const; friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); };} [🔗](#lib:filter_view::sentinel,constructor) `constexpr explicit sentinel(filter_view& parent); ` [1](#range.filter.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5146) *Effects*: Initializes *end_* with ranges​::​end(parent.*base_*)[.](#range.filter.sentinel-1.sentence-1) [🔗](#lib:base,filter_view::sentinel) `constexpr sentinel_t base() const; ` [2](#range.filter.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5157) *Effects*: Equivalent to: return *end_*; [🔗](#lib:operator==,filter_view::sentinel) `friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.filter.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5168) *Effects*: Equivalent to: return x.*current_* == y.*end_*; ### [25.7.9](#range.transform) Transform view [[range.transform]](range.transform) #### [25.7.9.1](#range.transform.overview) Overview [[range.transform.overview]](range.transform.overview) [1](#range.transform.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5177) transform_view presents a view of an underlying sequence after applying a transformation function to each element[.](#range.transform.overview-1.sentence-1) [2](#range.transform.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5182) The name views​::​transform denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.transform.overview-2.sentence-1) Given subexpressions E and F, the expressionviews​::​transform(E, F) is expression-equivalent totransform_view(E, F)[.](#range.transform.overview-2.sentence-2) [3](#range.transform.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5190) [*Example [1](#range.transform.overview-example-1)*: vector is{ 0, 1, 2, 3, 4 };auto squares = views::transform(is, [](int i) { return i * i; });for (int i : squares) cout << i << ' '; // prints 0 1 4 9 16 — *end example*] #### [25.7.9.2](#range.transform.view) Class template transform_view [[range.transform.view]](range.transform.view) [🔗](#lib:transform_view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]")>>class transform_view : public view_interface> {private:// [[range.transform.iterator]](#range.transform.iterator "25.7.9.3 Class template transform_­view​::​iterator"), class template transform_view​::​*iterator*template struct *iterator*; // *exposition only*// [[range.transform.sentinel]](#range.transform.sentinel "25.7.9.4 Class template transform_­view​::​sentinel"), class template transform_view​::​*sentinel*template struct *sentinel*; // *exposition only* V *base_* = V(); // *exposition only**movable-box* *fun_*; // *exposition only*public: transform_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit transform_view(V base, F fun); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr *iterator* begin(); constexpr *iterator* begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")>; constexpr *sentinel* end(); constexpr *iterator* end() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr *sentinel* end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")>; constexpr *iterator* end() constrequires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")>; constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") { return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }}; template transform_view(R&&, F) -> transform_view, F>;} [🔗](#lib:transform_view,constructor) `constexpr explicit transform_view(V base, F fun); ` [1](#range.transform.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5264) *Effects*: Initializes *base_* with std​::​move(base) and*fun_* with std​::​move(fun)[.](#range.transform.view-1.sentence-1) [🔗](#lib:begin,transform_view) `constexpr iterator begin(); ` [2](#range.transform.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5276) *Effects*: Equivalent to:return *iterator*{*this, ranges::begin(*base_*)}; [🔗](#lib:begin,transform_view_) `constexpr iterator begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") && [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")>; ` [3](#range.transform.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5292) *Effects*: Equivalent to:return *iterator*{*this, ranges::begin(*base_*)}; [🔗](#lib:end,transform_view) `constexpr sentinel end(); ` [4](#range.transform.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5306) *Effects*: Equivalent to:return *sentinel*{ranges::end(*base_*)}; [🔗](#lib:end,transform_view_) `constexpr iterator end() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); ` [5](#range.transform.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5320) *Effects*: Equivalent to:return *iterator*{*this, ranges::end(*base_*)}; [🔗](#lib:end,transform_view__) `constexpr sentinel end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") && [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")>; ` [6](#range.transform.view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5336) *Effects*: Equivalent to:return *sentinel*{ranges::end(*base_*)}; [🔗](#lib:end,transform_view___) `constexpr iterator end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")>; ` [7](#range.transform.view-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5352) *Effects*: Equivalent to:return *iterator*{*this, ranges::end(*base_*)}; #### [25.7.9.3](#range.transform.iterator) Class template transform_view​::​*iterator* [[range.transform.iterator]](range.transform.iterator) [🔗](#lib:transform_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]")>>templateclass transform_view::*iterator* {private:using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only**Parent** *parent_* = nullptr; // *exposition only*public:using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = remove_cvref_t&, range_reference_t<*Base*>>>; using difference_type = range_difference_t<*Base*>; *iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")> = default; constexpr *iterator*(*Parent*& parent, iterator_t<*Base*> current); constexpr *iterator*(*iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t<*Base*>>; constexpr const iterator_t<*Base*>& base() const & noexcept; constexpr iterator_t<*Base*> base() &&; constexpr decltype(auto) operator*() constnoexcept(noexcept(invoke(**parent_*->*fun_*, **current_*))) {return invoke(**parent_*->*fun_*, **current_*); }constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr decltype(auto) operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> {return invoke(**parent_*->*fun_*, *current_*[n]); }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*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; friend constexpr *iterator* operator+(*iterator* i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, *iterator* i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(*iterator* i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; };} [1](#range.transform.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5441) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.transform.iterator-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), theniterator_concept denotes random_access_iterator_tag[.](#range.transform.iterator-1.1.sentence-1) - [(1.2)](#range.transform.iterator-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), theniterator_concept denotes bidirectional_iterator_tag[.](#range.transform.iterator-1.2.sentence-1) - [(1.3)](#range.transform.iterator-1.3) Otherwise, if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), theniterator_concept denotes forward_iterator_tag[.](#range.transform.iterator-1.3.sentence-1) - [(1.4)](#range.transform.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.transform.iterator-1.4.sentence-1) [2](#range.transform.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5456) 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 *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.transform.iterator-2.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: Let C denote the typeiterator_traits>​::​iterator_category[.](#range.transform.iterator-2.sentence-2) - [(2.1)](#range.transform.iterator-2.1) If is_reference_v&, range_reference_t<*Base*>>> is true, then * [(2.1.1)](#range.transform.iterator-2.1.1) if C models [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"),iterator_category denotes random_access_iterator_tag; * [(2.1.2)](#range.transform.iterator-2.1.2) otherwise,iterator_category denotes C[.](#range.transform.iterator-2.1.sentence-1) - [(2.2)](#range.transform.iterator-2.2) Otherwise, iterator_category denotes input_iterator_tag[.](#range.transform.iterator-2.2.sentence-1) [🔗](#lib:iterator,transform_view::iterator) `constexpr iterator(Parent& parent, iterator_t current); ` [3](#range.transform.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5487) *Effects*: Initializes *current_* with std​::​move(current) and*parent_* with addressof(parent)[.](#range.transform.iterator-3.sentence-1) [🔗](#lib:transform_view::iterator,constructor) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [4](#range.transform.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5500) *Effects*: Initializes *current_* with std​::​move(i.*current_*) and*parent_* with i.*parent_*[.](#range.transform.iterator-4.sentence-1) [🔗](#lib:base,transform_view::iterator) `constexpr const iterator_t& base() const & noexcept; ` [5](#range.transform.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5512) *Effects*: Equivalent to: return *current_*; [🔗](#lib:base,transform_view::iterator_) `constexpr iterator_t base() &&; ` [6](#range.transform.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5523) *Effects*: Equivalent to: return std​::​move(*current_*); [🔗](#lib:operator++,transform_view::iterator) `constexpr iterator& operator++(); ` [7](#range.transform.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5534) *Effects*: Equivalent to:++*current_*;return *this; [🔗](#lib:operator++,transform_view::iterator_) `constexpr void operator++(int); ` [8](#range.transform.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5549) *Effects*: Equivalent to ++*current_*[.](#range.transform.iterator-8.sentence-1) [🔗](#lib:operator++,transform_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [9](#range.transform.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5560) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,transform_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.transform.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5576) *Effects*: Equivalent to:--*current_*;return *this; [🔗](#lib:operator--,transform_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.transform.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5591) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,transform_view::iterator) `constexpr iterator& operator+=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.transform.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5608) *Effects*: Equivalent to:*current_* += n;return *this; [🔗](#lib:operator-=,transform_view::iterator) `constexpr iterator& operator-=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [13](#range.transform.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5624) *Effects*: Equivalent to:*current_* -= n;return *this; [🔗](#lib:operator==,transform_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]")>; ` [14](#range.transform.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5640) *Effects*: Equivalent to: return x.*current_* == y.*current_*; [🔗](#lib:operator%3c,transform_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [15](#range.transform.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5652) *Effects*: Equivalent to: return x.*current_* < y.*current_*; [🔗](#lib:operator%3e,transform_view::iterator) `friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [16](#range.transform.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5664) *Effects*: Equivalent to: return y < x; [🔗](#lib:operator%3c=,transform_view::iterator) `friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [17](#range.transform.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5676) *Effects*: Equivalent to: return !(y < x); [🔗](#lib:operator%3e=,transform_view::iterator) `friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.transform.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5688) *Effects*: Equivalent to: return !(x < y); [🔗](#lib:operator%3c=%3e,transform_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [19](#range.transform.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5700) *Effects*: Equivalent to: return x.*current_* <=> y.*current_*; [🔗](#lib:operator+,transform_view::iterator) `friend constexpr iterator operator+(iterator i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, iterator i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [20](#range.transform.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5714) *Effects*: Equivalent to: return *iterator*{*i.*parent_*, i.*current_* + n}; [🔗](#lib:operator-,transform_view::iterator) `friend constexpr iterator operator-(iterator i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [21](#range.transform.iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5726) *Effects*: Equivalent to: return *iterator*{*i.*parent_*, i.*current_* - n}; [🔗](#lib:operator-,transform_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [22](#range.transform.iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5738) *Effects*: Equivalent to: return x.*current_* - y.*current_*; #### [25.7.9.4](#range.transform.sentinel) Class template transform_view​::​*sentinel* [[range.transform.sentinel]](range.transform.sentinel) [🔗](#lib:transform_view::sentinel) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]")>>templateclass transform_view::*sentinel* {private:using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *sentinel*& y, const *iterator*& x); };} [🔗](#lib:transform_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end); ` [1](#range.transform.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5791) *Effects*: Initializes *end_* with end[.](#range.transform.sentinel-1.sentence-1) [🔗](#lib:transform_view::sentinel,constructor_) `constexpr sentinel(sentinel i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.transform.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5803) *Effects*: Initializes *end_* with std​::​move(i.*end_*)[.](#range.transform.sentinel-2.sentence-1) [🔗](#lib:base,transform_view::sentinel) `constexpr sentinel_t base() const; ` [3](#range.transform.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5814) *Effects*: Equivalent to: return *end_*; [🔗](#lib:operator==,transform_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [4](#range.transform.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5827) *Effects*: Equivalent to: return x.*current_* == y.*end_*; [🔗](#lib:operator-,transform_view::sentinel) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const iterator& x, const sentinel& y); ` [5](#range.transform.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5841) *Effects*: Equivalent to: return x.*current_* - y.*end_*; [🔗](#lib:operator-,transform_view::sentinel_) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const sentinel& y, const iterator& x); ` [6](#range.transform.sentinel-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5855) *Effects*: Equivalent to: return y.*end_* - x.*current_*; ### [25.7.10](#range.take) Take view [[range.take]](range.take) #### [25.7.10.1](#range.take.overview) Overview [[range.take.overview]](range.take.overview) [1](#range.take.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5864) take_view produces a view of the first N elements from another view, or all the elements if the adapted view contains fewer than N[.](#range.take.overview-1.sentence-1) [2](#range.take.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5869) The name views​::​take denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.take.overview-2.sentence-1) Let E and F be expressions, let T be remove_cvref_t, and let D be range_difference_t[.](#range.take.overview-2.sentence-2) If decltype((F)) does not model[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"),views​::​take(E, F) is ill-formed[.](#range.take.overview-2.sentence-3) Otherwise, the expression views​::​take(E, F) is expression-equivalent to: - [(2.1)](#range.take.overview-2.1) If T is a specialization of empty_view ([[range.empty.view]](range.empty.view "25.6.2.2 Class template empty_­view")), then ((void)F, *decay-copy*(E)), except that the evaluations of E and F are indeterminately sequenced[.](#range.take.overview-2.1.sentence-1) - [(2.2)](#range.take.overview-2.2) Otherwise, if T models[random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") and [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") and is a specialization ofspan ([[views.span]](views.span "23.7.2.2 Class template span")),basic_string_view ([[string.view]](string.view "27.3 String view classes")), orsubrange ([[range.subrange]](range.subrange "25.5.4 Sub-ranges")), thenU(ranges​::​begin(E), ranges​::​begin(E) + std​::​min(ranges​::​distance(E), F)), except that E is evaluated only once, where U is a type determined as follows: * [(2.2.1)](#range.take.overview-2.2.1) if T is a specialization of span, then U is span; * [(2.2.2)](#range.take.overview-2.2.2) otherwise, if T is a specialization of basic_string_view, then U is T; * [(2.2.3)](#range.take.overview-2.2.3) otherwise, T is a specialization of subrange, andU is subrange>; - [(2.3)](#range.take.overview-2.3) otherwise, if T is a specialization of iota_view ([[range.iota.view]](range.iota.view "25.6.4.2 Class template iota_­view")) that models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") and [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"), theniota_view(*ranges​::​begin(E),*(ranges​::​begin(E) + std​::​min(ranges​::​distance(E), F))), except that E is evaluated only once[.](#range.take.overview-2.3.sentence-1) - [(2.4)](#range.take.overview-2.4) Otherwise, if T is a specialization of repeat_view ([[range.repeat.view]](range.repeat.view "25.6.5.2 Class template repeat_­view")): * [(2.4.1)](#range.take.overview-2.4.1) if T models [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"), thenviews::repeat(*E.*value_*, std::min(ranges::distance(E), F)) except that E is evaluated only once; * [(2.4.2)](#range.take.overview-2.4.2) otherwise, views​::​repeat(*E.*value_*, static_cast(F))[.](#range.take.overview-2.4.sentence-1) - [(2.5)](#range.take.overview-2.5) Otherwise, take_view(E, F)[.](#range.take.overview-2.5.sentence-1) [3](#range.take.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5938) [*Example [1](#range.take.overview-example-1)*: vector is{0,1,2,3,4,5,6,7,8,9};for (int i : is | views::take(5)) cout << i << ' '; // prints 0 1 2 3 4 — *end example*] #### [25.7.10.2](#range.take.view) Class template take_view [[range.take.view]](range.take.view) [🔗](#lib:take_view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>class take_view : public view_interface> {private: V *base_* = V(); // *exposition only* range_difference_t *count_* = 0; // *exposition only*// [[range.take.sentinel]](#range.take.sentinel "25.7.10.3 Class template take_­view​::​sentinel"), class template take_view​::​*sentinel*template class *sentinel*; // *exposition only*public: take_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit take_view(V base, range_difference_t count); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")) {return ranges::begin(*base_*); } else {auto sz = range_difference_t(size()); return counted_iterator(ranges::begin(*base_*), sz); }} else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>) {auto it = ranges::begin(*base_*); auto sz = std::min(*count_*, ranges::end(*base_*) - it); return counted_iterator(std::move(it), sz); } else {return counted_iterator(ranges::begin(*base_*), *count_*); }}constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")) {return ranges::begin(*base_*); } else {auto sz = range_difference_t(size()); return counted_iterator(ranges::begin(*base_*), sz); }} else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>) {auto it = ranges::begin(*base_*); auto sz = std::min(*count_*, ranges::end(*base_*) - it); return counted_iterator(std::move(it), sz); } else {return counted_iterator(ranges::begin(*base_*), *count_*); }}constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"))return ranges::begin(*base_*) + range_difference_t(size()); elsereturn default_sentinel; } else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>) {return default_sentinel; } else {return *sentinel*{ranges::end(*base_*)}; }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"))return ranges::begin(*base_*) + range_difference_t(size()); elsereturn default_sentinel; } else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>) {return default_sentinel; } else {return *sentinel*{ranges::end(*base_*)}; }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {auto n = ranges::size(*base_*); return ranges::min(n, static_cast(*count_*)); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {auto n = ranges::size(*base_*); return ranges::min(n, static_cast(*count_*)); }constexpr auto reserve_hint() {if constexpr ([approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")) {auto n = static_cast>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(ranges::min(n, *count_*)); }return *to-unsigned-like*(*count_*); }constexpr auto reserve_hint() const {if constexpr ([approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")) {auto n = static_cast>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(ranges::min(n, *count_*)); }return *to-unsigned-like*(*count_*); }}; template take_view(R&&, range_difference_t)-> take_view>;} [🔗](#lib:take_view,constructor) `constexpr explicit take_view(V base, range_difference_t count); ` [1](#range.take.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6071) *Preconditions*: count >= 0 is true[.](#range.take.view-1.sentence-1) [2](#range.take.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6075) *Effects*: Initializes *base_* with std​::​move(base) and*count_* with count[.](#range.take.view-2.sentence-1) #### [25.7.10.3](#range.take.sentinel) Class template take_view​::​*sentinel* [[range.take.sentinel]](range.take.sentinel) [🔗](#lib:take_view::sentinel) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>templateclass take_view::*sentinel* {private:using *Base* = *maybe-const*; // *exposition only*templateusing *CI* = counted_iterator>>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel* s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; friend constexpr bool operator==(const *CI*& y, const *sentinel*& x); templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *CI*& y, const *sentinel*& x); };} [🔗](#lib:take_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end); ` [1](#range.take.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6118) *Effects*: Initializes *end_* with end[.](#range.take.sentinel-1.sentence-1) [🔗](#lib:take_view::sentinel,constructor_) `constexpr sentinel(sentinel s) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.take.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6130) *Effects*: Initializes *end_* with std​::​move(s.*end_*)[.](#range.take.sentinel-2.sentence-1) [🔗](#lib:base,take_view::sentinel) `constexpr sentinel_t base() const; ` [3](#range.take.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6141) *Effects*: Equivalent to: return *end_*; [🔗](#lib:operator==,take_view::sentinel) `friend constexpr bool operator==(const CI& y, const sentinel& x); template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const CI& y, const sentinel& x); ` [4](#range.take.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6156) *Effects*: Equivalent to:return y.count() == 0 || y.base() == x.*end_*; ### [25.7.11](#range.take.while) Take while view [[range.take.while]](range.take.while) #### [25.7.11.1](#range.take.while.overview) Overview [[range.take.while.overview]](range.take.while.overview) [1](#range.take.while.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6166) Given a unary predicate pred and a view r,take_while_view produces a view of the range [ranges​::​begin(r), ranges​::​find_if_not(r, pred))[.](#range.take.while.overview-1.sentence-1) [2](#range.take.while.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6172) The name views​::​take_while denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.take.while.overview-2.sentence-1) Given subexpressions E and F, the expression views​::​take_while(E, F) is expression-equivalent to take_while_view(E, F)[.](#range.take.while.overview-2.sentence-2) [3](#range.take.while.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6180) [*Example [1](#range.take.while.overview-example-1)*: auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};auto small = [](const auto x) noexcept { return x < 5; };auto small_ints = views::istream(input) | views::take_while(small);for (const auto i : small_ints) { cout << i << ' '; // prints 0 1 2 3 4}auto i = 0; input >> i; cout << i; // prints 6 — *end example*] #### [25.7.11.2](#range.take.while.view) Class template take_while_view [[range.take.while.view]](range.take.while.view) [🔗](#lib:take_while_view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V, class Pred>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") && is_object_v &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")>class take_while_view : public view_interface> {// [[range.take.while.sentinel]](#range.take.while.sentinel "25.7.11.3 Class template take_­while_­view​::​sentinel"), class template take_while_view​::​*sentinel*template class *sentinel*; // *exposition only* V *base_* = V(); // *exposition only**movable-box* *pred_*; // *exposition only*public: take_while_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit take_while_view(V base, Pred pred); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr const Pred& pred() const; constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")){ return ranges::begin(*base_*); }constexpr auto begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")>{ return ranges::begin(*base_*); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")){ return *sentinel*(ranges::end(*base_*), addressof(**pred_*)); }constexpr auto end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")>{ return *sentinel*(ranges::end(*base_*), addressof(**pred_*)); }}; template take_while_view(R&&, Pred) -> take_while_view, Pred>;} [🔗](#lib:take_while_view,constructor) `constexpr explicit take_while_view(V base, Pred pred); ` [1](#range.take.while.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6250) *Effects*: Initializes *base_* with std​::​move(base) and*pred_* with std​::​move(pred)[.](#range.take.while.view-1.sentence-1) [🔗](#lib:pred,take_while_view) `constexpr const Pred& pred() const; ` [2](#range.take.while.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6262) *Effects*: Equivalent to: return **pred_*; #### [25.7.11.3](#range.take.while.sentinel) Class template take_while_view​::​*sentinel* [[range.take.while.sentinel]](range.take.while.sentinel) [🔗](#lib:take_while_view::sentinel) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V, class Pred>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") && is_object_v &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")>templateclass take_while_view::*sentinel* {using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*const Pred* *pred_* = nullptr; // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end, const Pred* pred); constexpr *sentinel*(*sentinel* s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const { return *end_*; }friend constexpr bool operator==(const iterator_t<*Base*>& x, const *sentinel*& y); templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const iterator_t<*maybe-const*>& x, const *sentinel*& y); };} [🔗](#lib:take_while_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end, const Pred* pred); ` [1](#range.take.while.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6306) *Effects*: Initializes *end_* with end and *pred_* with pred[.](#range.take.while.sentinel-1.sentence-1) [🔗](#lib:take_while_view::sentinel,constructor_) `constexpr sentinel(sentinel s) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.take.while.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6318) *Effects*: Initializes *end_* with std​::​move(s.*end_*) and*pred_* with s.*pred_*[.](#range.take.while.sentinel-2.sentence-1) [🔗](#lib:operator==,take_while_view::sentinel) `friend constexpr bool operator==(const iterator_t& x, const sentinel& y); template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator_t>& x, const sentinel& y); ` [3](#range.take.while.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6335) *Effects*: Equivalent to:return y.*end_* == x || !invoke(*y.*pred_*, *x); ### [25.7.12](#range.drop) Drop view [[range.drop]](range.drop) #### [25.7.12.1](#range.drop.overview) Overview [[range.drop.overview]](range.drop.overview) [1](#range.drop.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6345) drop_view produces a view excluding the first N elements from another view, or an empty range if the adapted view contains fewer than N elements[.](#range.drop.overview-1.sentence-1) [2](#range.drop.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6350) The name views​::​drop denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.drop.overview-2.sentence-1) Let E and F be expressions, let T be remove_cvref_t, and let D be range_difference_t[.](#range.drop.overview-2.sentence-2) If decltype((F)) does not model[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"),views​::​drop(E, F) is ill-formed[.](#range.drop.overview-2.sentence-3) Otherwise, the expression views​::​drop(E, F) is expression-equivalent to: - [(2.1)](#range.drop.overview-2.1) If T is a specialization ofempty_view ([[range.empty.view]](range.empty.view "25.6.2.2 Class template empty_­view")), then ((void)F, *decay-copy*(E)), except that the evaluations of E and F are indeterminately sequenced[.](#range.drop.overview-2.1.sentence-1) - [(2.2)](#range.drop.overview-2.2) Otherwise, if T models[random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") and [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") and is * [(2.2.1)](#range.drop.overview-2.2.1) a specialization of span ([[views.span]](views.span "23.7.2.2 Class template span")), * [(2.2.2)](#range.drop.overview-2.2.2) a specialization of basic_string_view ([[string.view]](string.view "27.3 String view classes")), * [(2.2.3)](#range.drop.overview-2.2.3) a specialization of iota_view ([[range.iota.view]](range.iota.view "25.6.4.2 Class template iota_­view")), or * [(2.2.4)](#range.drop.overview-2.2.4) a specialization of subrange ([[range.subrange]](range.subrange "25.5.4 Sub-ranges")) where T​::​*StoreSize* is false, then U(ranges​::​begin(E) + std​::​min(ranges​::​distance(E), F), ranges​::​end(E)), except that E is evaluated only once, where U is span if T is a specialization of span and T otherwise[.](#range.drop.overview-2.2.sentence-1) - [(2.3)](#range.drop.overview-2.3) Otherwise, if T is a specialization of subrange that models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") and [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"), thenT(ranges​::​begin(E) + std​::​min(ranges​::​distance(E), F), ranges​::​end(E),*to-unsigned-like*(ranges​::​distance(E) - std​::​min(ranges​::​distance(E), F))), except that E and F are each evaluated only once[.](#range.drop.overview-2.3.sentence-1) - [(2.4)](#range.drop.overview-2.4) Otherwise, if T is a specialization of repeat_view ([[range.repeat.view]](range.repeat.view "25.6.5.2 Class template repeat_­view")): * [(2.4.1)](#range.drop.overview-2.4.1) if T models [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"), thenviews::repeat(*E.*value_*, ranges::distance(E) - std::min(ranges::distance(E), F)) except that E is evaluated only once; * [(2.4.2)](#range.drop.overview-2.4.2) otherwise, ((void)F, *decay-copy*(E)), except that the evaluations of E and F are indeterminately sequenced[.](#range.drop.overview-2.4.sentence-1) - [(2.5)](#range.drop.overview-2.5) Otherwise, drop_view(E, F)[.](#range.drop.overview-2.5.sentence-1) [3](#range.drop.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6417) [*Example [1](#range.drop.overview-example-1)*: auto ints = views::iota(0) | views::take(10);for (auto i : ints | views::drop(5)) { cout << i << ' '; // prints 5 6 7 8 9} — *end example*] #### [25.7.12.2](#range.drop.view) Class template drop_view [[range.drop.view]](range.drop.view) [🔗](#lib:drop_view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>class drop_view : public view_interface> {public: drop_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit drop_view(V base, range_difference_t count); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin()requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") &&[random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))); constexpr auto begin() constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"); constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")){ return ranges::end(*base_*); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"){ return ranges::end(*base_*); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {const auto s = ranges::size(*base_*); const auto c = static_cast(*count_*); return s < c ? 0 : s - c; }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {const auto s = ranges::size(*base_*); const auto c = static_cast(*count_*); return s < c ? 0 : s - c; }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {const auto s = static_cast>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(s < *count_* ? 0 : s - *count_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {const auto s = static_cast>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(s < *count_* ? 0 : s - *count_*); }private: V *base_* = V(); // *exposition only* range_difference_t *count_* = 0; // *exposition only*}; template drop_view(R&&, range_difference_t) -> drop_view>;} [🔗](#lib:drop_view,constructor) `constexpr explicit drop_view(V base, range_difference_t count); ` [1](#range.drop.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6494) *Preconditions*: count >= 0 is true[.](#range.drop.view-1.sentence-1) [2](#range.drop.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6498) *Effects*: Initializes *base_* with std​::​move(base) and*count_* with count[.](#range.drop.view-2.sentence-1) [🔗](#lib:begin,drop_view) `constexpr auto begin() requires (!([simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))); constexpr auto begin() const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"); ` [3](#range.drop.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6514) *Returns*: ranges​::​next(ranges​::​begin(*base_*), *count_*, ranges​::​end(*base_*))[.](#range.drop.view-3.sentence-1) [4](#range.drop.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6518) *Remarks*: In order to provide the amortized constant-time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept when drop_view models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), the first overload caches the result within the drop_view for use on subsequent calls[.](#range.drop.view-4.sentence-1) [*Note [1](#range.drop.view-note-1)*: Without this, applying a reverse_view over a drop_view would have quadratic iteration complexity[.](#range.drop.view-4.sentence-2) — *end note*] ### [25.7.13](#range.drop.while) Drop while view [[range.drop.while]](range.drop.while) #### [25.7.13.1](#range.drop.while.overview) Overview [[range.drop.while.overview]](range.drop.while.overview) [1](#range.drop.while.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6536) Given a unary predicate pred and a view r,drop_while_view produces a view of the range [ranges​::​find_if_not(r, pred), ranges​::​end(r))[.](#range.drop.while.overview-1.sentence-1) [2](#range.drop.while.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6541) The name views​::​drop_while denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.drop.while.overview-2.sentence-1) Given subexpressions E and F, the expression views​::​drop_while(E, F) is expression-equivalent to drop_while_view(E, F)[.](#range.drop.while.overview-2.sentence-2) [3](#range.drop.while.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6549) [*Example [1](#range.drop.while.overview-example-1)*: constexpr auto source = " \t \t \t hello there"sv;auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };auto skip_ws = views::drop_while(source, is_invisible);for (auto c : skip_ws) { cout << c; // prints hello there with no leading space} — *end example*] #### [25.7.13.2](#range.drop.while.view) Class template drop_while_view [[range.drop.while.view]](range.drop.while.view) [🔗](#lib:drop_while_view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V, class Pred>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") && is_object_v &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")>class drop_while_view : public view_interface> {public: drop_while_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit drop_while_view(V base, Pred pred); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr const Pred& pred() const; constexpr auto begin(); constexpr auto end() { return ranges::end(*base_*); }private: V *base_* = V(); // *exposition only**movable-box* *pred_*; // *exposition only*}; template drop_while_view(R&&, Pred) -> drop_while_view, Pred>;} [🔗](#lib:drop_while_view,constructor) `constexpr explicit drop_while_view(V base, Pred pred); ` [1](#range.drop.while.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6601) *Effects*: Initializes *base_* with std​::​move(base) and*pred_* with std​::​move(pred)[.](#range.drop.while.view-1.sentence-1) [🔗](#lib:pred,drop_while_view) `constexpr const Pred& pred() const; ` [2](#range.drop.while.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6613) *Effects*: Equivalent to: return **pred_*; [🔗](#lib:begin,drop_while_view) `constexpr auto begin(); ` [3](#range.drop.while.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6624) *Preconditions*: *pred_*.has_value() is true[.](#range.drop.while.view-3.sentence-1) [4](#range.drop.while.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6628) *Returns*: ranges​::​find_if_not(*base_*, cref(**pred_*))[.](#range.drop.while.view-4.sentence-1) [5](#range.drop.while.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6632) *Remarks*: In order to provide the amortized constant-time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept when drop_while_view models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), the first call caches the result within the drop_while_view for use on subsequent calls[.](#range.drop.while.view-5.sentence-1) [*Note [1](#range.drop.while.view-note-1)*: Without this, applying a reverse_view over a drop_while_view would have quadratic iteration complexity[.](#range.drop.while.view-5.sentence-2) — *end note*] ### [25.7.14](#range.join) Join view [[range.join]](range.join) #### [25.7.14.1](#range.join.overview) Overview [[range.join.overview]](range.join.overview) [1](#range.join.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6650) join_view flattens a view of ranges into a view[.](#range.join.overview-1.sentence-1) [2](#range.join.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6653) The name views​::​join denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.join.overview-2.sentence-1) Given a subexpression E, the expressionviews​::​join(E) is expression-equivalent tojoin_view>{E}[.](#range.join.overview-2.sentence-2) [3](#range.join.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6661) [*Example [1](#range.join.overview-example-1)*: vector ss{"hello", " ", "world", "!"};for (char ch : ss | views::join) cout << ch; // prints hello world! — *end example*] #### [25.7.14.2](#range.join.view) Class template join_view [[range.join.view]](range.join.view) [🔗](#lib:join_view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>class join_view : public view_interface> {private:using *InnerRng* = range_reference_t; // *exposition only*// [[range.join.iterator]](#range.join.iterator "25.7.14.3 Class template join_­view​::​iterator"), class template join_view​::​*iterator*templatestruct *iterator*; // *exposition only*// [[range.join.sentinel]](#range.join.sentinel "25.7.14.4 Class template join_­view​::​sentinel"), class template join_view​::​*sentinel*templatestruct *sentinel*; // *exposition only* V *base_* = V(); // *exposition only**non-propagating-cache*> *outer_*; // *exposition only*, present only// when ![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")*non-propagating-cache*> *inner_*; // *exposition only*, present only// if is_reference_v<*InnerRng*> is falsepublic: join_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit join_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")) {constexpr bool use_const = [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && is_reference_v<*InnerRng*>; return *iterator*{*this, ranges::begin(*base_*)}; } else {*outer_* = ranges::begin(*base_*); return *iterator*{*this}; }}constexpr auto begin() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && is_reference_v> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>{ return *iterator*{*this, ranges::begin(*base_*)}; }constexpr auto end() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && is_reference_v<*InnerRng*> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*InnerRng*> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*InnerRng*>)return *iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")>{*this}; }constexpr auto end() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && is_reference_v> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")> {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")>)return *iterator*{*this, ranges::end(*base_*)}; elsereturn *sentinel*{*this}; }}; templateexplicit join_view(R&&) -> join_view>;} [🔗](#lib:join_view,constructor) `constexpr explicit join_view(V base); ` [1](#range.join.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6756) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.join.view-1.sentence-1) #### [25.7.14.3](#range.join.iterator) Class template join_view​::​*iterator* [[range.join.iterator]](range.join.iterator) [🔗](#lib:join_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>templatestruct join_view::*iterator* {private:using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only*using *OuterIter* = iterator_t<*Base*>; // *exposition only*using *InnerIter* = iterator_t>; // *exposition only*static constexpr bool *ref-is-glvalue* = // *exposition only* is_reference_v>; *OuterIter* *outer_* = *OuterIter*(); // *exposition only*, present only// if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") optional<*InnerIter*> *inner_*; // *exposition only**Parent** *parent_* = nullptr; // *exposition only*constexpr void *satisfy*(); // *exposition only*constexpr *OuterIter*& *outer*(); // *exposition only*constexpr const *OuterIter*& *outer*() const; // *exposition only*constexpr *iterator*(*Parent*& parent, *OuterIter* outer)requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; // *exposition only*constexpr explicit *iterator*(*Parent*& parent)requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>); // *exposition only*public:using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = range_value_t>; using difference_type = *see below*; *iterator*() = default; constexpr *iterator*(*iterator* i)requires Const &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), *OuterIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), *InnerIter*>; constexpr decltype(auto) operator*() const { return ***inner_*; }constexpr *InnerIter* operator->() constrequires [*has-arrow*](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]")<*InnerIter*> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<*InnerIter*>; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int)requires *ref-is-glvalue* && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")>; constexpr *iterator*& operator--()requires *ref-is-glvalue* && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")>; constexpr *iterator* operator--(int)requires *ref-is-glvalue* && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y)requires *ref-is-glvalue* && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")>>; friend constexpr decltype(auto) iter_move(const *iterator*& i)noexcept(noexcept(ranges::iter_move(*i.*inner_*))) {return ranges::iter_move(*i.*inner_*); }friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)noexcept(noexcept(ranges::iter_swap(*x.*inner_*, *y.*inner_*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<*InnerIter*>; };} [1](#range.join.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6843) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.join.iterator-1.1) If *ref-is-glvalue* is true, *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), and range_reference_t<*Base*> models both [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") and [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.join.iterator-1.1.sentence-1) - [(1.2)](#range.join.iterator-1.2) Otherwise, if *ref-is-glvalue* is true and *Base* and range_reference_t<*Base*> each model [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes forward_iterator_tag[.](#range.join.iterator-1.2.sentence-1) - [(1.3)](#range.join.iterator-1.3) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.join.iterator-1.3.sentence-1) [2](#range.join.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6858) 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 *ref-is-glvalue* is true,*Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), andrange_reference_t<*Base*> models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.join.iterator-2.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(2.1)](#range.join.iterator-2.1) Let *OUTERC* denote iterator_traits>​::​iterator_category, and let *INNERC* denote iterator_traits>>​::​iterator_category[.](#range.join.iterator-2.1.sentence-1) - [(2.2)](#range.join.iterator-2.2) If *OUTERC* and *INNERC* each model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") and range_reference_t<*Base*> models [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"), iterator_category denotes bidirectional_iterator_tag[.](#range.join.iterator-2.2.sentence-1) - [(2.3)](#range.join.iterator-2.3) Otherwise, if *OUTERC* and *INNERC* each model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"), iterator_category denotes forward_iterator_tag[.](#range.join.iterator-2.3.sentence-1) - [(2.4)](#range.join.iterator-2.4) Otherwise, iterator_category denotes input_iterator_tag[.](#range.join.iterator-2.4.sentence-1) [3](#range.join.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6883) *iterator*​::​difference_type denotes the type:common_type_t< range_difference_t<*Base*>, range_difference_t>> [4](#range.join.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6891) join_view iterators use the *satisfy* function to skip over empty inner ranges[.](#range.join.iterator-4.sentence-1) [🔗](#lib:outer,join_view::iterator) `constexpr OuterIter& outer(); constexpr const OuterIter& outer() const; ` [5](#range.join.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6902) *Returns*: *outer_* if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); otherwise, **parent_*->*outer_*[.](#range.join.iterator-5.sentence-1) [🔗](#lib:satisfy,join_view::iterator) `constexpr void satisfy(); ` [6](#range.join.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6914) *Effects*: Equivalent to:auto update_inner = [this](const iterator_t<*Base*>& x) -> auto&& {if constexpr (*ref-is-glvalue*) // *x is a referencereturn *x; elsereturn *parent_*->*inner_*.*emplace-deref*(x);}; for (; *outer*() != ranges::end(*parent_*->*base_*); ++*outer*()) {auto&& inner = update_inner(*outer*()); *inner_* = ranges::begin(inner); if (**inner_* != ranges::end(inner))return;}if constexpr (*ref-is-glvalue*)*inner_*.reset(); [🔗](#lib:join_view::iterator,constructor) `constexpr iterator(Parent& parent, OuterIter outer) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [7](#range.join.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6943) *Effects*: Initializes *outer_* with std​::​move(outer) and*parent_* with addressof(parent); then calls *satisfy*()[.](#range.join.iterator-7.sentence-1) [🔗](#lib:join_view::iterator,constructor_) `constexpr explicit iterator(Parent& parent) requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")); ` [8](#range.join.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6956) *Effects*: Initializes *parent_* with addressof(parent); then calls *satisfy*()[.](#range.join.iterator-8.sentence-1) [🔗](#lib:join_view::iterator,constructor__) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), OuterIter> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), InnerIter>; ` [9](#range.join.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6971) *Effects*: Initializes *outer_* with std​::​move(i.*outer_*),*inner_* with std​::​move(i.*inner_*), and*parent_* with i.*parent_*[.](#range.join.iterator-9.sentence-1) [10](#range.join.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6977) [*Note [1](#range.join.iterator-note-1)*: Const can only be true when *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.join.iterator-10.sentence-1) — *end note*] [🔗](#lib:operator-%3e,join_view::iterator) `constexpr InnerIter operator->() const requires [has-arrow](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]") && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"); ` [11](#range.join.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6991) *Effects*: Equivalent to: return **inner_*; [🔗](#lib:operator++,join_view::iterator) `constexpr iterator& operator++(); ` [12](#range.join.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7002) Let *inner-range* be: - [(12.1)](#range.join.iterator-12.1) If *ref-is-glvalue* is true, **outer*()[.](#range.join.iterator-12.1.sentence-1) - [(12.2)](#range.join.iterator-12.2) Otherwise, **parent_*->*inner_*[.](#range.join.iterator-12.2.sentence-1) [13](#range.join.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7009) *Effects*: Equivalent to:if (++**inner_* == ranges::end(*as-lvalue*(*inner-range*))) {++*outer*(); *satisfy*();}return *this; [🔗](#lib:operator++,join_view::iterator_) `constexpr void operator++(int); ` [14](#range.join.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7027) *Effects*: Equivalent to: ++*this[.](#range.join.iterator-14.sentence-1) [🔗](#lib:operator++,join_view::iterator__) `constexpr iterator operator++(int) requires ref-is-glvalue && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")>; ` [15](#range.join.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7040) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,join_view::iterator) `constexpr iterator& operator--() requires ref-is-glvalue && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")>; ` [16](#range.join.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7059) *Effects*: Equivalent to:if (*outer_* == ranges::end(*parent_*->*base_*))*inner_* = ranges::end(*as-lvalue*(*--*outer_*));while (**inner_* == ranges::begin(*as-lvalue*(**outer_*)))**inner_* = ranges::end(*as-lvalue*(*--*outer_*));--**inner_*;return *this; [🔗](#lib:operator--,join_view::iterator_) `constexpr iterator operator--(int) requires ref-is-glvalue && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")>; ` [17](#range.join.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7081) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator==,join_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref-is-glvalue && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")>>; ` [18](#range.join.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7099) *Effects*: Equivalent to:return x.*outer_* == y.*outer_* && x.*inner_* == y.*inner_*; [🔗](#lib:iter_swap,join_view::iterator) `friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]"); ` [19](#range.join.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7113) *Effects*: Equivalent to: ranges​::​iter_swap(*x.*inner_*, *y.*inner_*); #### [25.7.14.4](#range.join.sentinel) Class template join_view​::​*sentinel* [[range.join.sentinel]](range.join.sentinel) [🔗](#lib:join_view::sentinel) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>templatestruct join_view::*sentinel* {private:using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(*Parent*& parent); constexpr *sentinel*(*sentinel* s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); };} [🔗](#lib:join_view::sentinel,constructor) `constexpr explicit sentinel(Parent& parent); ` [1](#range.join.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7152) *Effects*: Initializes *end_* with ranges​::​end(parent.*base_*)[.](#range.join.sentinel-1.sentence-1) [🔗](#lib:join_view::sentinel,constructor_) `constexpr sentinel(sentinel s) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.join.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7164) *Effects*: Initializes *end_* with std​::​move(s.*end_*)[.](#range.join.sentinel-2.sentence-1) [🔗](#lib:operator==,join_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.join.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7177) *Effects*: Equivalent to: return x.*outer*() == y.*end_*; ### [25.7.15](#range.join.with) Join with view [[range.join.with]](range.join.with) #### [25.7.15.1](#range.join.with.overview) Overview [[range.join.with.overview]](range.join.with.overview) [1](#range.join.with.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7186) join_with_view takes a view and a delimiter, and flattens the view, inserting every element of the delimiter in between elements of the view[.](#range.join.with.overview-1.sentence-1) The delimiter can be a single element or a view of elements[.](#range.join.with.overview-1.sentence-2) [2](#range.join.with.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7193) The name views​::​join_with denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.join.with.overview-2.sentence-1) Given subexpressions E and F, the expression views​::​join_with(E, F) is expression-equivalent tojoin_with_view(E, F)[.](#range.join.with.overview-2.sentence-2) [3](#range.join.with.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7201) [*Example [1](#range.join.with.overview-example-1)*: vector vs = {"the", "quick", "brown", "fox"};for (char c : vs | views::join_with('-')) { cout << c;}// The above prints the-quick-brown-fox — *end example*] #### [25.7.15.2](#range.join.with.view) Class template join_with_view [[range.join.with.view]](range.join.with.view) [🔗](#lib:join_with_view) namespace std::ranges {templateconcept [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]") = [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); // *exposition only*template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>&& [view](range.view#concept:view "25.4.5 Views [range.view]")&& [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"), Pattern>class join_with_view : public view_interface> {using *InnerRng* = range_reference_t; // *exposition only* V *base_* = V(); // *exposition only**non-propagating-cache*> *outer_it_*; // *exposition only*, present only// when ![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")*non-propagating-cache*> *inner_*; // *exposition only*, present only// if is_reference_v<*InnerRng*> is false Pattern *pattern_* = Pattern(); // *exposition only*// [[range.join.with.iterator]](#range.join.with.iterator "25.7.15.3 Class template join_­with_­view​::​iterator"), class template join_with_view​::​*iterator*template struct *iterator*; // *exposition only*// [[range.join.with.sentinel]](#range.join.with.sentinel "25.7.15.4 Class template join_­with_­view​::​sentinel"), class template join_with_view​::​*sentinel*template struct *sentinel*; // *exposition only*public: join_with_view()requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit join_with_view(V base, Pattern pattern); template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>>constexpr explicit join_with_view(R&& r, range_value_t<*InnerRng*> e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")) {constexpr bool use_const =[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && is_reference_v<*InnerRng*> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]"); return *iterator*{*this, ranges::begin(*base_*)}; }else {*outer_it_* = ranges::begin(*base_*); return *iterator*{*this}; }}constexpr auto begin() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") &&[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && is_reference_v> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")> &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"), const Pattern> {return *iterator*{*this, ranges::begin(*base_*)}; }constexpr auto end() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && is_reference_v<*InnerRng*> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*InnerRng*> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*InnerRng*>)return *iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")>{*this}; }constexpr auto end() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && is_reference_v> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")> &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"), const Pattern> {using InnerConstRng = range_reference_t; if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"))return *iterator*{*this, ranges::end(*base_*)}; elsereturn *sentinel*{*this}; }}; template join_with_view(R&&, P&&) -> join_with_view, views::all_t

>; template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> join_with_view(R&&, range_value_t>)-> join_with_view, single_view>>>;} [🔗](#lib:join_with_view,constructor) `constexpr explicit join_with_view(V base, Pattern pattern); ` [1](#range.join.with.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7311) *Effects*: Initializes *base_* with std​::​move(base) and*pattern_* with std​::​move(pattern)[.](#range.join.with.view-1.sentence-1) [🔗](#lib:join_with_view,constructor_) `template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>> constexpr explicit join_with_view(R&& r, range_value_t e); ` [2](#range.join.with.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7326) *Effects*: Initializes *base_* with views​::​all(std​::​forward(r)) and*pattern_* with views​::​single(std​::​move(e))[.](#range.join.with.view-2.sentence-1) #### [25.7.15.3](#range.join.with.iterator) Class template join_with_view​::​*iterator* [[range.join.with.iterator]](range.join.with.iterator) [🔗](#lib:join_with_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>&& [view](range.view#concept:view "25.4.5 Views [range.view]") && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"), Pattern>templateclass join_with_view::*iterator* {using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only*using *InnerBase* = range_reference_t<*Base*>; // *exposition only*using *PatternBase* = *maybe-const*; // *exposition only*using *OuterIter* = iterator_t<*Base*>; // *exposition only*using *InnerIter* = iterator_t<*InnerBase*>; // *exposition only*using *PatternIter* = iterator_t<*PatternBase*>; // *exposition only*static constexpr bool *ref-is-glvalue* = is_reference_v<*InnerBase*>; // *exposition only**Parent** *parent_* = nullptr; // *exposition only**OuterIter* *outer_it_* = *OuterIter*(); // *exposition only*, present only// if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") variant<*PatternIter*, *InnerIter*> *inner_it_*; // *exposition only*constexpr *iterator*(*Parent*& parent, *OuterIter* outer)requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; // *exposition only*constexpr explicit *iterator*(*Parent*& parent)requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>); // *exposition only*constexpr *OuterIter*& *outer*(); // *exposition only*constexpr const *OuterIter*& *outer*() const; // *exposition only*constexpr auto& *update-inner*(); // *exposition only*constexpr auto& *get-inner*(); // *exposition only*constexpr void *satisfy*(); // *exposition only*public:using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = *see below*; using difference_type = *see below*; *iterator*() = default; constexpr *iterator*(*iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), *OuterIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), *InnerIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), *PatternIter*>; constexpr decltype(auto) operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int)requires *ref-is-glvalue* && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]")<*OuterIter*> &&[forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]")<*InnerIter*>; constexpr *iterator*& operator--()requires *ref-is-glvalue* && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]")<*InnerBase*> && [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]")<*PatternBase*>; constexpr *iterator* operator--(int)requires *ref-is-glvalue* && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]")<*InnerBase*> && [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]")<*PatternBase*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y)requires *ref-is-glvalue* && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<*InnerIter*>; friend constexpr decltype(auto) iter_move(const *iterator*& x) {using rvalue_reference = common_reference_t< iter_rvalue_reference_t<*InnerIter*>, iter_rvalue_reference_t<*PatternIter*>>; return visit(ranges::iter_move, x.*inner_it_*); }friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<*InnerIter*, *PatternIter*> { visit(ranges::iter_swap, x.*inner_it_*, y.*inner_it_*); }};} [1](#range.join.with.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7414) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.join.with.iterator-1.1) If *ref-is-glvalue* is true,*Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), and*InnerBase* and *PatternBase* each model [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.join.with.iterator-1.1.sentence-1) - [(1.2)](#range.join.with.iterator-1.2) Otherwise, if *ref-is-glvalue* is true and*Base* and *InnerBase* each model [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes forward_iterator_tag[.](#range.join.with.iterator-1.2.sentence-1) - [(1.3)](#range.join.with.iterator-1.3) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.join.with.iterator-1.3.sentence-1) [2](#range.join.with.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7431) 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 *ref-is-glvalue* is true, and*Base* and *InnerBase* each model [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.join.with.iterator-2.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(2.1)](#range.join.with.iterator-2.1) Let *OUTERC* denoteiterator_traits<*OuterIter*>​::​iterator_category, let *INNERC* denoteiterator_traits<*InnerIter*>​::​iterator_category, and let *PATTERNC* denoteiterator_traits<*PatternIter*>​::​iterator_category[.](#range.join.with.iterator-2.1.sentence-1) - [(2.2)](#range.join.with.iterator-2.2) Ifis_reference_v, iter_reference_t<*PatternIter*>>> is false,iterator_category denotes input_iterator_tag[.](#range.join.with.iterator-2.2.sentence-1) - [(2.3)](#range.join.with.iterator-2.3) Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") and *InnerBase* and *PatternBase* each model [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"),iterator_category denotes bidirectional_iterator_tag[.](#range.join.with.iterator-2.3.sentence-1) - [(2.4)](#range.join.with.iterator-2.4) Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"),iterator_category denotes forward_iterator_tag[.](#range.join.with.iterator-2.4.sentence-1) - [(2.5)](#range.join.with.iterator-2.5) Otherwise, iterator_category denotes input_iterator_tag[.](#range.join.with.iterator-2.5.sentence-1) [3](#range.join.with.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7469) *iterator*​::​value_type denotes the type:common_type_t, iter_value_t<*PatternIter*>> [4](#range.join.with.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7475) *iterator*​::​difference_type denotes the type:common_type_t< iter_difference_t<*OuterIter*>, iter_difference_t<*InnerIter*>, iter_difference_t<*PatternIter*>> [🔗](#lib:outer,join_with_view::iterator) `constexpr OuterIter& outer(); constexpr const OuterIter& outer() const; ` [5](#range.join.with.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7491) *Returns*: *outer_it_* if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); otherwise, **parent_*->*outer_it_*[.](#range.join.with.iterator-5.sentence-1) [🔗](#lib:update-inner,join_with_view::iterator) `constexpr auto& update-inner(); ` [6](#range.join.with.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7503) *Effects*: Equivalent to:if constexpr (*ref-is-glvalue*)return *as-lvalue*(**outer*());elsereturn *parent_*->*inner_*.*emplace-deref*(*outer*()); [🔗](#lib:get-inner,join_with_view::iterator) `constexpr auto& get-inner(); ` [7](#range.join.with.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7520) *Effects*: Equivalent to:if constexpr (*ref-is-glvalue*)return *as-lvalue*(**outer*());elsereturn **parent_*->*inner_*; [🔗](#lib:satisfy,join_with_view::iterator) `constexpr void satisfy(); ` [8](#range.join.with.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7537) *Effects*: Equivalent to:while (true) {if (*inner_it_*.index() == 0) {if (std::get<0>(*inner_it_*) != ranges::end(*parent_*->*pattern_*))break; *inner_it_*.template emplace<1>(ranges::begin(*update-inner*())); } else {if (std::get<1>(*inner_it_*) != ranges::end(*get-inner*()))break; if (++*outer*() == ranges::end(*parent_*->*base_*)) {if constexpr (*ref-is-glvalue*)*inner_it_*.template emplace<0>(); break; }*inner_it_*.template emplace<0>(ranges::begin(*parent_*->*pattern_*)); }} [*Note [1](#range.join.with.iterator-note-1)*: join_with_view iterators use the *satisfy* function to skip over empty inner ranges[.](#range.join.with.iterator-8.sentence-2) — *end note*] [🔗](#lib:join_with_view::iterator,constructor) `constexpr iterator(Parent& parent, OuterIter outer) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); constexpr explicit iterator(Parent& parent) requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")); ` [9](#range.join.with.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7574) *Effects*: Initializes *parent_* with addressof(parent)[.](#range.join.with.iterator-9.sentence-1) For the first overload, also initializes*outer_it_* with std​::​move(outer)[.](#range.join.with.iterator-9.sentence-2) Then, equivalent to:if (*outer*() != ranges::end(*parent_*->*base_*)) {*inner_it_*.template emplace<1>(ranges::begin(*update-inner*())); *satisfy*();} [🔗](#lib:join_with_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), OuterIter> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), InnerIter> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), PatternIter>; ` [10](#range.join.with.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7597) *Effects*: Initializes *outer_it_* withstd​::​move(i.*outer_it_*) and*parent_* with i.*parent_*[.](#range.join.with.iterator-10.sentence-1) Then, equivalent to:if (i.*inner_it_*.index() == 0)*inner_it_*.template emplace<0>(std::get<0>(std::move(i.*inner_it_*)));else*inner_it_*.template emplace<1>(std::get<1>(std::move(i.*inner_it_*))); [11](#range.join.with.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7610) [*Note [2](#range.join.with.iterator-note-2)*: Const can only be true when *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.join.with.iterator-11.sentence-1) — *end note*] [🔗](#lib:operator--,join_with_view::iterator) `constexpr decltype(auto) operator*() const; ` [12](#range.join.with.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7623) *Effects*: Equivalent to:using reference = common_reference_t, iter_reference_t<*PatternIter*>>;return visit([](auto& it) -> reference { return *it; }, *inner_it_*); [🔗](#lib:operator++,join_with_view::iterator) `constexpr iterator& operator++(); ` [13](#range.join.with.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7639) *Effects*: Equivalent to:visit([](auto& it){ ++it; }, *inner_it_*);*satisfy*();return *this; [🔗](#lib:operator++,join_with_view::iterator_) `constexpr void operator++(int); ` [14](#range.join.with.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7655) *Effects*: Equivalent to ++*this[.](#range.join.with.iterator-14.sentence-1) [🔗](#lib:operator++,join_with_view::iterator__) `constexpr iterator operator++(int) requires ref-is-glvalue && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]") && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"); ` [15](#range.join.with.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7667) *Effects*: Equivalent to:*iterator* tmp = *this;++*this;return tmp; [🔗](#lib:operator--,join_with_view::iterator_) `constexpr iterator& operator--() requires ref-is-glvalue && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]") && [bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]"); ` [16](#range.join.with.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7685) *Effects*: Equivalent to:if (*outer_it_* == ranges::end(*parent_*->*base_*)) {auto&& inner = *--*outer_it_*; *inner_it_*.template emplace<1>(ranges::end(inner));}while (true) {if (*inner_it_*.index() == 0) {auto& it = std::get<0>(*inner_it_*); if (it == ranges::begin(*parent_*->*pattern_*)) {auto&& inner = *--*outer_it_*; *inner_it_*.template emplace<1>(ranges::end(inner)); } else {break; }} else {auto& it = std::get<1>(*inner_it_*); auto&& inner = **outer_it_*; if (it == ranges::begin(inner)) {*inner_it_*.template emplace<0>(ranges::end(*parent_*->*pattern_*)); } else {break; }}} visit([](auto& it){ --it; }, *inner_it_*);return *this; [🔗](#lib:operator--,join_with_view::iterator__) `constexpr iterator operator--(int) requires ref-is-glvalue && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]") && [bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_­with_­view [range.join.with.view]"); ` [17](#range.join.with.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7726) *Effects*: Equivalent to:*iterator* tmp = *this;--*this;return tmp; [🔗](#lib:operator==,join_with_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref-is-glvalue && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]"); ` [18](#range.join.with.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7744) *Effects*: Equivalent to:return x.*outer_it_* == y.*outer_it_* && x.*inner_it_* == y.*inner_it_*; #### [25.7.15.4](#range.join.with.sentinel) Class template join_with_view​::​*sentinel* [[range.join.with.sentinel]](range.join.with.sentinel) [🔗](#lib:join_with_view::sentinel) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")>&& [view](range.view#concept:view "25.4.5 Views [range.view]") && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]"), Pattern>templateclass join_with_view::*sentinel* {using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*constexpr explicit *sentinel*(*Parent*& parent); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel* s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); };} [🔗](#lib:join_with_view::sentinel,constructor) `constexpr explicit sentinel(Parent& parent); ` [1](#range.join.with.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7786) *Effects*: Initializes *end_* with ranges​::​end(parent.*base_*)[.](#range.join.with.sentinel-1.sentence-1) [🔗](#lib:join_with_view::sentinel,constructor_) `constexpr sentinel(sentinel s) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.join.with.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7798) *Effects*: Initializes *end_* with std​::​move(s.*end_*)[.](#range.join.with.sentinel-2.sentence-1) [🔗](#lib:operator==,join_with_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.join.with.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7811) *Effects*: Equivalent to: return x.*outer*() == y.*end_*; ### [25.7.16](#range.lazy.split) Lazy split view [[range.lazy.split]](range.lazy.split) #### [25.7.16.1](#range.lazy.split.overview) Overview [[range.lazy.split.overview]](range.lazy.split.overview) [1](#range.lazy.split.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7820) lazy_split_view takes a view and a delimiter, and splits the view into subranges on the delimiter[.](#range.lazy.split.overview-1.sentence-1) The delimiter can be a single element or a view of elements[.](#range.lazy.split.overview-1.sentence-2) [2](#range.lazy.split.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7825) The name views​::​lazy_split denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.lazy.split.overview-2.sentence-1) Given subexpressions E and F, the expression views​::​lazy_split(E, F) is expression-equivalent tolazy_split_view(E, F)[.](#range.lazy.split.overview-2.sentence-2) [3](#range.lazy.split.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7833) [*Example [1](#range.lazy.split.overview-example-1)*: string str{"the quick brown fox"};for (auto word : str | views::lazy_split(' ')) {for (char ch : word) cout << ch; cout << '*';}// The above prints the*quick*brown*fox* — *end example*] #### [25.7.16.2](#range.lazy.split.view) Class template lazy_split_view [[range.lazy.split.view]](range.lazy.split.view) [🔗](#lib:lazy_split_view) namespace std::ranges {template struct *require-constant*; // *exposition only*templateconcept [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]") = // *exposition only*[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") &&requires { typename *require-constant*::size()>; } &&(remove_reference_t::size() <= 1); template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]"))class lazy_split_view : public view_interface> {private: V *base_* = V(); // *exposition only* Pattern *pattern_* = Pattern(); // *exposition only**non-propagating-cache*> *current_*; // *exposition only*, present only// if [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") is false// [[range.lazy.split.outer]](#range.lazy.split.outer "25.7.16.3 Class template lazy_­split_­view​::​outer-iterator"), class template lazy_split_view​::​*outer-iterator*template struct *outer-iterator*; // *exposition only*// [[range.lazy.split.inner]](#range.lazy.split.inner "25.7.16.5 Class template lazy_­split_­view​::​inner-iterator"), class template lazy_split_view​::​*inner-iterator*template struct *inner-iterator*; // *exposition only*public: lazy_split_view()requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit lazy_split_view(V base, Pattern pattern); template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>>constexpr explicit lazy_split_view(R&& r, range_value_t e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")) {return *outer-iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")>{*this, ranges::begin(*base_*)}; } else {*current_* = ranges::begin(*base_*); return *outer-iterator*{*this}; }}constexpr auto begin() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") {return *outer-iterator*{*this, ranges::begin(*base_*)}; }constexpr auto end() requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") {return *outer-iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")>{*this, ranges::end(*base_*)}; }constexpr auto end() const {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"))return *outer-iterator*{*this, ranges::end(*base_*)}; elsereturn default_sentinel; }}; template lazy_split_view(R&&, P&&) -> lazy_split_view, views::all_t

>; template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> lazy_split_view(R&&, range_value_t)-> lazy_split_view, single_view>>;} [🔗](#lib:lazy_split_view,constructor) `constexpr explicit lazy_split_view(V base, Pattern pattern); ` [1](#range.lazy.split.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7935) *Effects*: Initializes *base_* with std​::​move(base), and*pattern_* with std​::​move(pattern)[.](#range.lazy.split.view-1.sentence-1) [🔗](#lib:lazy_split_view,constructor_) `template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>> constexpr explicit lazy_split_view(R&& r, range_value_t e); ` [2](#range.lazy.split.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7950) *Effects*: Initializes *base_* with views​::​all(std​::​forward(r)), and*pattern_* with views​::​single(std​::​move(e))[.](#range.lazy.split.view-2.sentence-1) #### [25.7.16.3](#range.lazy.split.outer) Class template lazy_split_view​::​*outer-iterator* [[range.lazy.split.outer]](range.lazy.split.outer) [🔗](#lib:lazy_split_view::outer-iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]"))templatestruct lazy_split_view::*outer-iterator* {private:using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only**Parent** *parent_* = nullptr; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only*, present only// if V models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")bool *trailing_empty_* = false; // *exposition only*public:using iterator_concept = conditional_t<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>, forward_iterator_tag, input_iterator_tag>; using iterator_category = input_iterator_tag; // present only if *Base*// models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")// [[range.lazy.split.outer.value]](#range.lazy.split.outer.value "25.7.16.4 Class lazy_­split_­view​::​outer-iterator​::​value_­type"), class lazy_split_view​::​*outer-iterator*​::​value_typestruct value_type; using difference_type = range_difference_t<*Base*>; *outer-iterator*() = default; constexpr explicit *outer-iterator*(*Parent*& parent)requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>); constexpr *outer-iterator*(*Parent*& parent, iterator_t<*Base*> current)requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *outer-iterator*(*outer-iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t<*Base*>>; constexpr value_type operator*() const; constexpr *outer-iterator*& operator++(); constexpr decltype(auto) operator++(int) {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>) {auto tmp = *this; ++*this; return tmp; } else++*this; }friend constexpr bool operator==(const *outer-iterator*& x, const *outer-iterator*& y)requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator==(const *outer-iterator*& x, default_sentinel_t); };} [1](#range.lazy.split.outer-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8016) Many of the specifications in [[range.lazy.split]](#range.lazy.split "25.7.16 Lazy split view") refer to the notional member*current* of *outer-iterator*[.](#range.lazy.split.outer-1.sentence-1) *current* is equivalent to *current_* if V models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), and **parent_*->*current_* otherwise[.](#range.lazy.split.outer-1.sentence-2) [🔗](#lib:lazy_split_view::outer-iterator,constructor) `constexpr explicit outer-iterator(Parent& parent) requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")); ` [2](#range.lazy.split.outer-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8029) *Effects*: Initializes *parent_* with addressof(parent)[.](#range.lazy.split.outer-2.sentence-1) [🔗](#lib:lazy_split_view::outer-iterator,constructor_) `constexpr outer-iterator(Parent& parent, iterator_t current) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [3](#range.lazy.split.outer-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8041) *Effects*: Initializes *parent_* with addressof(parent) and *current_* with std​::​move(current)[.](#range.lazy.split.outer-3.sentence-1) [🔗](#lib:lazy_split_view::outer-iterator,constructor__) `constexpr outer-iterator(outer-iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [4](#range.lazy.split.outer-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8054) *Effects*: Initializes *parent_* with i.*parent_*,*current_* with std​::​move(i.*current_*), and*trailing_empty_* with i.*trailing_empty_*[.](#range.lazy.split.outer-4.sentence-1) [🔗](#lib:operator*,lazy_split_view::outer-iterator) `constexpr value_type operator*() const; ` [5](#range.lazy.split.outer-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8067) *Effects*: Equivalent to: return value_type{*this}; [🔗](#lib:operator++,lazy_split_view::outer-iterator) `constexpr outer-iterator& operator++(); ` [6](#range.lazy.split.outer-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8078) *Effects*: Equivalent to:const auto end = ranges::end(*parent_*->*base_*);if (*current* == end) {*trailing_empty_* = false; return *this;}const auto [pbegin, pend] = subrange{*parent_*->*pattern_*};if (pbegin == pend) ++*current*;else if constexpr ([*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]")) {*current* = ranges::find(std::move(*current*), end, *pbegin); if (*current* != end) {++*current*; if (*current* == end)*trailing_empty_* = true; }}else {do {auto [b, p] = ranges::mismatch(*current*, end, pbegin, pend); if (p == pend) {*current* = b; if (*current* == end)*trailing_empty_* = true; break; // The pattern matched; skip it}} while (++*current* != end);}return *this; [🔗](#lib:operator==,lazy_split_view::outer-iterator) `friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [7](#range.lazy.split.outer-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8119) *Effects*: Equivalent to:return x.*current_* == y.*current_* && x.*trailing_empty_* == y.*trailing_empty_*; [🔗](#lib:operator==,lazy_split_view::outer-iterator_) `friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t); ` [8](#range.lazy.split.outer-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8133) *Effects*: Equivalent to:return x.*current* == ranges::end(x.*parent_*->*base_*) && !x.*trailing_empty_*; #### [25.7.16.4](#range.lazy.split.outer.value) Class lazy_split_view​::​*outer-iterator*​::​value_type [[range.lazy.split.outer.value]](range.lazy.split.outer.value) [🔗](#lib:lazy_split_view::outer-iterator::value_type) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]"))templatestruct lazy_split_view::*outer-iterator*::value_type : view_interface {private:*outer-iterator* *i_* = *outer-iterator*(); // *exposition only*constexpr explicit value_type(*outer-iterator* i); // *exposition only*public:constexpr *inner-iterator* begin() const; constexpr default_sentinel_t end() const noexcept; };} [🔗](#lib:lazy_split_view::outer-iterator::value_type,constructor) `constexpr explicit value_type(outer-iterator i); ` [1](#range.lazy.split.outer.value-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8171) *Effects*: Initializes *i_* with std​::​move(i)[.](#range.lazy.split.outer.value-1.sentence-1) [🔗](#lib:begin,lazy_split_view::outer-iterator::value_type) `constexpr inner-iterator begin() const; ` [2](#range.lazy.split.outer.value-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8182) *Effects*: Equivalent to: return *inner-iterator*{*i_*}; [🔗](#lib:end,lazy_split_view::outer-iterator::value_type) `constexpr default_sentinel_t end() const noexcept; ` [3](#range.lazy.split.outer.value-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8193) *Effects*: Equivalent to: return default_sentinel; #### [25.7.16.5](#range.lazy.split.inner) Class template lazy_split_view​::​*inner-iterator* [[range.lazy.split.inner]](range.lazy.split.inner) [🔗](#lib:lazy_split_view::inner-iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]"))templatestruct lazy_split_view::*inner-iterator* {private:using *Base* = *maybe-const*; // *exposition only**outer-iterator* *i_* = *outer-iterator*(); // *exposition only*bool *incremented_* = false; // *exposition only*public:using iterator_concept = typename *outer-iterator*::iterator_concept; using iterator_category = *see below*; // present only if *Base*// models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")using value_type = range_value_t<*Base*>; using difference_type = range_difference_t<*Base*>; *inner-iterator*() = default; constexpr explicit *inner-iterator*(*outer-iterator* i); constexpr const iterator_t<*Base*>& base() const & noexcept; constexpr iterator_t<*Base*> base() && requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); constexpr decltype(auto) operator*() const { return **i_*.*current*; }constexpr *inner-iterator*& operator++(); constexpr decltype(auto) operator++(int) {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>) {auto tmp = *this; ++*this; return tmp; } else++*this; }friend constexpr bool operator==(const *inner-iterator*& x, const *inner-iterator*& y)requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator==(const *inner-iterator*& x, default_sentinel_t); friend constexpr decltype(auto) iter_move(const *inner-iterator*& i)noexcept(noexcept(ranges::iter_move(i.*i_*.*current*))) {return ranges::iter_move(i.*i_*.*current*); }friend constexpr void iter_swap(const *inner-iterator*& x, const *inner-iterator*& y)noexcept(noexcept(ranges::iter_swap(x.*i_*.*current*, y.*i_*.*current*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [1](#range.lazy.split.inner-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8257) If *Base* does not model [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") there is no member iterator_category[.](#range.lazy.split.inner-1.sentence-1) Otherwise, the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") iterator_category denotes: - [(1.1)](#range.lazy.split.inner-1.1) forward_iterator_tag ifiterator_traits>​::​iterator_category models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"); - [(1.2)](#range.lazy.split.inner-1.2) otherwise, iterator_traits>​::​iterator_category[.](#range.lazy.split.inner-1.sentence-2) [🔗](#lib:lazy_split_view::inner-iterator,constructor) `constexpr explicit inner-iterator(outer-iterator i); ` [2](#range.lazy.split.inner-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8275) *Effects*: Initializes *i_* with std​::​move(i)[.](#range.lazy.split.inner-2.sentence-1) [🔗](#lib:base,lazy_split_view::inner-iterator) `constexpr const iterator_t& base() const & noexcept; ` [3](#range.lazy.split.inner-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8286) *Effects*: Equivalent to: return *i_*.*current*; [🔗](#lib:base,lazy_split_view::inner-iterator_) `constexpr iterator_t base() && requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [4](#range.lazy.split.inner-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8297) *Effects*: Equivalent to: return std​::​move(*i_*.*current*); [🔗](#lib:operator++,lazy_split_view::inner-iterator) `constexpr inner-iterator& operator++(); ` [5](#range.lazy.split.inner-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8308) *Effects*: Equivalent to:*incremented_* = true;if constexpr (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>) {if constexpr (Pattern::size() == 0) {return *this; }}++*i_*.*current*;return *this; [🔗](#lib:operator==,lazy_split_view::inner-iterator) `friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [6](#range.lazy.split.inner-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8330) *Effects*: Equivalent to: return x.*i_*.*current* == y.*i_*.*current*; [🔗](#lib:operator==,lazy_split_view::inner-iterator_) `friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t); ` [7](#range.lazy.split.inner-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8341) *Effects*: Equivalent to:auto [pcur, pend] = subrange{x.*i_*.*parent_*->*pattern_*};auto end = ranges::end(x.*i_*.*parent_*->*base_*);if constexpr ([*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]")) {const auto & cur = x.*i_*.*current*; if (cur == end) return true; if (pcur == pend) return x.*incremented_*; return *cur == *pcur;} else {auto cur = x.*i_*.*current*; if (cur == end) return true; if (pcur == pend) return x.*incremented_*; do {if (*cur != *pcur) return false; if (++pcur == pend) return true; } while (++cur != end); return false;} [🔗](#lib:iter_swap,lazy_split_view::inner-iterator) `friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [8](#range.lazy.split.inner-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8373) *Effects*: Equivalent toranges​::​iter_swap(x.*i_*.*current*, y.*i_*.*current*)[.](#range.lazy.split.inner-8.sentence-1) ### [25.7.17](#range.split) Split view [[range.split]](range.split) #### [25.7.17.1](#range.split.overview) Overview [[range.split.overview]](range.split.overview) [1](#range.split.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8383) split_view takes a view and a delimiter, and splits the view into subranges on the delimiter[.](#range.split.overview-1.sentence-1) The delimiter can be a single element or a view of elements[.](#range.split.overview-1.sentence-2) [2](#range.split.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8388) The name views​::​split denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.split.overview-2.sentence-1) Given subexpressions E and F, the expression views​::​split(E, F) is expression-equivalent tosplit_view(E, F)[.](#range.split.overview-2.sentence-2) [3](#range.split.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8395) [*Example [1](#range.split.overview-example-1)*: string str{"the quick brown fox"};for (auto word : views::split(str, ' ')) { cout << string_view(word) << '*';}// The above prints the*quick*brown*fox* — *end example*] #### [25.7.17.2](#range.split.view) Class template split_view [[range.split.view]](range.split.view) [🔗](#lib:split_view) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to>class split_view : public view_interface> {private: V *base_* = V(); // *exposition only* Pattern *pattern_* = Pattern(); // *exposition only*// [[range.split.iterator]](#range.split.iterator "25.7.17.3 Class split_­view​::​iterator"), class split_view​::​*iterator*struct *iterator*; // *exposition only*// [[range.split.sentinel]](#range.split.sentinel "25.7.17.4 Class split_­view​::​sentinel"), class split_view​::​*sentinel*struct *sentinel*; // *exposition only*public: split_view()requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit split_view(V base, Pattern pattern); template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>>constexpr explicit split_view(R&& r, range_value_t e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr *iterator* begin(); constexpr auto end() {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*{*this, ranges::end(*base_*), {}}; } else {return *sentinel*{*this}; }}constexpr subrange> *find-next*(iterator_t); // *exposition only*}; template split_view(R&&, P&&) -> split_view, views::all_t

>; template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R> split_view(R&&, range_value_t)-> split_view, single_view>>;} [🔗](#lib:split_view,constructor) `constexpr explicit split_view(V base, Pattern pattern); ` [1](#range.split.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8466) *Effects*: Initializes *base_* with std​::​move(base), and*pattern_* with std​::​move(pattern)[.](#range.split.view-1.sentence-1) [🔗](#lib:split_view,constructor_) `template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R> requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>> constexpr explicit split_view(R&& r, range_value_t e); ` [2](#range.split.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8481) *Effects*: Initializes *base_* with views​::​all(std​::​forward(r)), and*pattern_* with views​::​single(std​::​move(e))[.](#range.split.view-2.sentence-1) [🔗](#lib:begin,split_view) `constexpr iterator begin(); ` [3](#range.split.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8493) *Returns*: {*this, ranges​::​begin(*base_*), *find-next*(ranges​::​begin(*base_*))}[.](#range.split.view-3.sentence-1) [4](#range.split.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8497) *Remarks*: In order to provide the amortized constant time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept, this function caches the result within the split_view for use on subsequent calls[.](#range.split.view-4.sentence-1) [🔗](#lib:find-next,split_view) `constexpr subrange> find-next(iterator_t it); ` [5](#range.split.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8511) *Effects*: Equivalent to:auto [b, e] = ranges::search(subrange(it, ranges::end(*base_*)), *pattern_*);if (b != ranges::end(*base_*) && ranges::empty(*pattern_*)) {++b; ++e;}return {b, e}; #### [25.7.17.3](#range.split.iterator) Class split_view​::​*iterator* [[range.split.iterator]](range.split.iterator) [🔗](#lib:split_view::iterator) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to>class split_view::*iterator* {private: split_view* *parent_* = nullptr; // *exposition only* iterator_t *cur_* = iterator_t(); // *exposition only* subrange> *next_* = subrange>(); // *exposition only*bool *trailing_empty_* = false; // *exposition only*public:using iterator_concept = forward_iterator_tag; using iterator_category = input_iterator_tag; using value_type = subrange>; using difference_type = range_difference_t; *iterator*() = default; constexpr *iterator*(split_view& parent, iterator_t current, subrange> next); constexpr iterator_t base() const; constexpr value_type operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); };} [🔗](#lib:split_view::iterator,constructor) `constexpr iterator(split_view& parent, iterator_t current, subrange> next); ` [1](#range.split.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8565) *Effects*: Initializes *parent_* with addressof(parent),*cur_* with std​::​move(current), and*next_* with std​::​move(next)[.](#range.split.iterator-1.sentence-1) [🔗](#lib:base,split_view::iterator) `constexpr iterator_t base() const; ` [2](#range.split.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8578) *Effects*: Equivalent to: return *cur_*; [🔗](#lib:operator*,split_view::iterator) `constexpr value_type operator*() const; ` [3](#range.split.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8589) *Effects*: Equivalent to: return {*cur_*, *next_*.begin()}; [🔗](#lib:operator++,split_view::iterator) `constexpr iterator& operator++(); ` [4](#range.split.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8600) *Effects*: Equivalent to:*cur_* = *next_*.begin();if (*cur_* != ranges::end(*parent_*->*base_*)) {*cur_* = *next_*.end(); if (*cur_* == ranges::end(*parent_*->*base_*)) {*trailing_empty_* = true; *next_* = {*cur_*, *cur_*}; } else {*next_* = *parent_*->*find-next*(*cur_*); }} else {*trailing_empty_* = false;}return *this; [🔗](#lib:operator++,split_view::iterator_) `constexpr iterator operator++(int); ` [5](#range.split.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8626) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator==,split_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y); ` [6](#range.split.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8642) *Effects*: Equivalent to:return x.*cur_* == y.*cur_* && x.*trailing_empty_* == y.*trailing_empty_*; #### [25.7.17.4](#range.split.sentinel) Class split_view​::​*sentinel* [[range.split.sentinel]](range.split.sentinel) [🔗](#lib:split_view::sentinel) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to>struct split_view::*sentinel* {private: sentinel_t *end_* = sentinel_t(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(split_view& parent); friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); };} [🔗](#lib:split_view::sentinel,constructor) `constexpr explicit sentinel(split_view& parent); ` [1](#range.split.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8677) *Effects*: Initializes *end_* with ranges​::​end(parent.*base_*)[.](#range.split.sentinel-1.sentence-1) [🔗](#lib:operator==,split_view::sentinel) `friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [2](#range.split.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8688) *Effects*: Equivalent to: return x.*cur_* == y.*end_* && !x.*trailing_empty_*; ### [25.7.18](#range.concat) Concat view [[range.concat]](range.concat) #### [25.7.18.1](#range.concat.overview) Overview [[range.concat.overview]](range.concat.overview) [1](#range.concat.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8697) concat_view presents a view that concatenates all the underlying ranges[.](#range.concat.overview-1.sentence-1) [2](#range.concat.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"))[.](#range.concat.overview-2.sentence-1) Given a pack of subexpressions Es..., the expression views​::​concat(Es...) is expression-equivalent to - [(2.1)](#range.concat.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)](#range.concat.overview-2.2) otherwise, concat_view(Es...)[.](#range.concat.overview-2.sentence-2) [*Example [1](#range.concat.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](#range.concat.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]](#range.concat.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](#range.concat.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](#range.concat.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](#range.concat.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*](#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](#range.concat.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*](#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](#range.concat.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8867) *Effects*: Initializes *views_* with std​::​move(views)...[.](#range.concat.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](#range.concat.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[.](#range.concat.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](#range.concat.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[.](#range.concat.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](#range.concat.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](#range.concat.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*](#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*](#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*](#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*](#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*](#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*](#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](#range.concat.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9035) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.concat.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[.](#range.concat.iterator-1.1.sentence-1) - [(1.2)](#range.concat.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[.](#range.concat.iterator-1.2.sentence-1) - [(1.3)](#range.concat.iterator-1.3) Otherwise, if[*all-forward*](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled, then iterator_concept denotes forward_iterator_tag[.](#range.concat.iterator-1.3.sentence-1) - [(1.4)](#range.concat.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.concat.iterator-1.4.sentence-1) [2](#range.concat.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*](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled[.](#range.concat.iterator-2.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(2.1)](#range.concat.iterator-2.1) Ifis_reference_v<*concat-reference-t*<*maybe-const*...>> is false, then iterator_category denotes input_iterator_tag[.](#range.concat.iterator-2.1.sentence-1) - [(2.2)](#range.concat.iterator-2.2) Otherwise, let Cs denote the pack of typesiterator_traits>>​::​iterator_category...[.](#range.concat.iterator-2.2.sentence-1) * [(2.2.1)](#range.concat.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[.](#range.concat.iterator-2.2.1.sentence-1) * [(2.2.2)](#range.concat.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[.](#range.concat.iterator-2.2.2.sentence-1) * [(2.2.3)](#range.concat.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[.](#range.concat.iterator-2.2.3.sentence-1) * [(2.2.4)](#range.concat.iterator-2.2.4) Otherwise, iterator_category denotes input_iterator_tag[.](#range.concat.iterator-2.2.4.sentence-1) [🔗](#lib:satisfy,concat_view::iterator) `template constexpr void satisfy(); ` [3](#range.concat.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](#range.concat.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](#range.concat.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](#range.concat.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](#range.concat.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)...[.](#range.concat.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](#range.concat.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9212) *Preconditions*: it.*it_*.valueless_by_exception() is false[.](#range.concat.iterator-8.sentence-1) [9](#range.concat.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_*)))[.](#range.concat.iterator-9.sentence-1) [🔗](#lib:operator*,concat_view::iterator) `constexpr decltype(auto) operator*() const; ` [10](#range.concat.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9230) *Preconditions*: *it_*.valueless_by_exception() is false[.](#range.concat.iterator-10.sentence-1) [11](#range.concat.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](#range.concat.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9250) *Preconditions*: *it_*.valueless_by_exception() is false[.](#range.concat.iterator-12.sentence-1) [13](#range.concat.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9254) *Effects*: Let i be *it_*.index()[.](#range.concat.iterator-13.sentence-1) Equivalent to:++std::get(*it_*);*satisfy*();return *this; [🔗](#lib:operator++,concat_view::iterator_) `constexpr void operator++(int); ` [14](#range.concat.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](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [15](#range.concat.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](#range.concat.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9303) *Preconditions*: *it_*.valueless_by_exception() is false[.](#range.concat.iterator-16.sentence-1) [17](#range.concat.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9307) *Effects*: Let i be *it_*.index()[.](#range.concat.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](#range.concat.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](#range.concat.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9341) *Preconditions*: *it_*.valueless_by_exception() is false[.](#range.concat.iterator-19.sentence-1) [20](#range.concat.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9345) *Effects*: Let i be *it_*.index()[.](#range.concat.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](#range.concat.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](#range.concat.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](#range.concat.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[.](#range.concat.iterator-23.sentence-1) [24](#range.concat.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](#range.concat.iterator-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9416) *Preconditions*: it.*it_*.valueless_by_exception() is false[.](#range.concat.iterator-25.sentence-1) [26](#range.concat.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](#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](#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](#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](#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](#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](#range.concat.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[.](#range.concat.iterator-27.sentence-1) [28](#range.concat.iterator-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9451) Let op be the operator[.](#range.concat.iterator-28.sentence-1) [29](#range.concat.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](#range.concat.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](#range.concat.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](#range.concat.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](#range.concat.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[.](#range.concat.iterator-33.sentence-1) [34](#range.concat.iterator-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9523) *Effects*: Letix denote x.*it_*.index() andiy denote y.*it_*.index()[.](#range.concat.iterator-34.sentence-1) - [(34.1)](#range.concat.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)](#range.concat.iterator-34.2) otherwise, if ix < iy is true, equivalent to:return -(y - x); - [(34.3)](#range.concat.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](#range.concat.iterator-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9571) *Preconditions*: x.*it_*.valueless_by_exception() is false[.](#range.concat.iterator-35.sentence-1) [36](#range.concat.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_*)))[.](#range.concat.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](#range.concat.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](#range.concat.iterator-38) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9614) *Effects*: Equivalent to:return -(x - default_sentinel); [39](#range.concat.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](#range.concat.iterator-40) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9639) *Preconditions*: it.*it_*.valueless_by_exception() is false[.](#range.concat.iterator-40.sentence-1) [41](#range.concat.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](#range.concat.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](#range.concat.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[.](#range.concat.iterator-43.sentence-1) [44](#range.concat.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](#range.concat.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[.](#range.concat.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]")>>) ### [25.7.19](#range.counted) Counted view [[range.counted]](range.counted) [1](#range.counted-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9712) A counted view presents a view of the elements of the counted range ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General")) i+[0, n) for an iterator i and non-negative integer n[.](#range.counted-1.sentence-1) [2](#range.counted-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9718) The name views​::​counted denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#range.counted-2.sentence-1) Let E and F be expressions, let T be decay_t, and let D be iter_difference_t[.](#range.counted-2.sentence-2) If decltype((F)) does not model[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"),views​::​counted(E, F) is ill-formed[.](#range.counted-2.sentence-3) [*Note [1](#range.counted-note-1)*: This case can result in substitution failure when views​::​counted(E, F) appears in the immediate context of a template instantiation[.](#range.counted-2.sentence-4) — *end note*] Otherwise, views​::​counted(E, F) is expression-equivalent to: - [(2.1)](#range.counted-2.1) If T models [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]"), then span(to_address(E), static_cast(static_cast(F)))[.](#range.counted-2.1.sentence-1) - [(2.2)](#range.counted-2.2) Otherwise, if T models [random_access_iterator](iterator.concept.random.access#concept:random_access_iterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]"), then subrange(E, E + static_cast(F)), except that E is evaluated only once[.](#range.counted-2.2.sentence-1) - [(2.3)](#range.counted-2.3) Otherwise,subrange(counted_iterator(E, F), default_sentinel)[.](#range.counted-2.3.sentence-1) ### [25.7.20](#range.common) Common view [[range.common]](range.common) #### [25.7.20.1](#range.common.overview) Overview [[range.common.overview]](range.common.overview) [1](#range.common.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9754) common_view takes a view which has different types for its iterator and sentinel and turns it into a view of the same elements with an iterator and sentinel of the same type[.](#range.common.overview-1.sentence-1) [2](#range.common.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9759) [*Note [1](#range.common.overview-note-1)*: common_view is useful for calling legacy algorithms that expect a range's iterator and sentinel types to be the same[.](#range.common.overview-2.sentence-1) — *end note*] [3](#range.common.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9765) The name views​::​common denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.common.overview-3.sentence-1) Given a subexpression E, the expression views​::​common(E) is expression-equivalent to: - [(3.1)](#range.common.overview-3.1) views​::​all(E), if decltype((E)) models [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") and views​::​all(E) is a well-formed expression[.](#range.common.overview-3.1.sentence-1) - [(3.2)](#range.common.overview-3.2) Otherwise, common_view{E}[.](#range.common.overview-3.2.sentence-1) [4](#range.common.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9779) [*Example [1](#range.common.overview-example-1)*: // Legacy algorithm:template size_t count(ForwardIterator first, ForwardIterator last); template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R>void my_algo(R&& r) {auto&& common = views::common(r); auto cnt = count(common.begin(), common.end()); // ...} — *end example*] #### [25.7.20.2](#range.common.view) Class template common_view [[range.common.view]](range.common.view) [🔗](#lib:common_view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires (![common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")>)class common_view : public view_interface> {private: V *base_* = V(); // *exposition only*public: common_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit common_view(V r); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return ranges::begin(*base_*); elsereturn common_iterator, sentinel_t>(ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return ranges::begin(*base_*); elsereturn common_iterator, sentinel_t>(ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return ranges::begin(*base_*) + ranges::distance(*base_*); elsereturn common_iterator, sentinel_t>(ranges::end(*base_*)); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return ranges::begin(*base_*) + ranges::distance(*base_*); elsereturn common_iterator, sentinel_t>(ranges::end(*base_*)); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {return ranges::reserve_hint(*base_*); }}; template common_view(R&&) -> common_view>;} [🔗](#lib:common_view,constructor) `constexpr explicit common_view(V base); ` [1](#range.common.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9872) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.common.view-1.sentence-1) ### [25.7.21](#range.reverse) Reverse view [[range.reverse]](range.reverse) #### [25.7.21.1](#range.reverse.overview) Overview [[range.reverse.overview]](range.reverse.overview) [1](#range.reverse.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9881) reverse_view takes a bidirectional view and produces another view that iterates the same elements in reverse order[.](#range.reverse.overview-1.sentence-1) [2](#range.reverse.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9885) The name views​::​reverse denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.reverse.overview-2.sentence-1) Given a subexpression E, the expressionviews​::​reverse(E) is expression-equivalent to: - [(2.1)](#range.reverse.overview-2.1) If the type of E is a (possibly cv-qualified) specialization of reverse_view, then E.base()[.](#range.reverse.overview-2.1.sentence-1) - [(2.2)](#range.reverse.overview-2.2) Otherwise, if the type of E is cv subrange, reverse_iterator, K> for some iterator type I and value K of type subrange_kind, * [(2.2.1)](#range.reverse.overview-2.2.1) if K is subrange_kind​::​sized, thensubrange(E.end().base(), E.begin().base(), E.size()); * [(2.2.2)](#range.reverse.overview-2.2.2) otherwise, subrange(E.end().base(), E.begin().base())[.](#range.reverse.overview-2.2.sentence-1) However, in either case E is evaluated only once[.](#range.reverse.overview-2.2.sentence-2) - [(2.3)](#range.reverse.overview-2.3) Otherwise, reverse_view{E}[.](#range.reverse.overview-2.3.sentence-1) [3](#range.reverse.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9912) [*Example [1](#range.reverse.overview-example-1)*: vector is {0,1,2,3,4};for (int i : is | views::reverse) cout << i << ' '; // prints 4 3 2 1 0 — *end example*] #### [25.7.21.2](#range.reverse.view) Class template reverse_view [[range.reverse.view]](range.reverse.view) [🔗](#lib:reverse_view) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")class reverse_view : public view_interface> {private: V *base_* = V(); // *exposition only*public: reverse_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit reverse_view(V r); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr reverse_iterator> begin(); constexpr reverse_iterator> begin() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr auto begin() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr reverse_iterator> end(); constexpr auto end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {return ranges::reserve_hint(*base_*); }}; template reverse_view(R&&) -> reverse_view>;} [🔗](#lib:reverse_view,constructor) `constexpr explicit reverse_view(V base); ` [1](#range.reverse.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9976) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.reverse.view-1.sentence-1) [🔗](#lib:begin,reverse_view) `constexpr reverse_iterator> begin(); ` [2](#range.reverse.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9987) *Returns*: make_reverse_iterator(ranges::next(ranges::begin(*base_*), ranges::end(*base_*))) [3](#range.reverse.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L9993) *Remarks*: In order to provide the amortized constant time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept, this function caches the result within thereverse_view for use on subsequent calls[.](#range.reverse.view-3.sentence-1) [🔗](#lib:begin,reverse_view_) `constexpr reverse_iterator> begin() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr auto begin() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); ` [4](#range.reverse.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10007) *Effects*: Equivalent to: return make_reverse_iterator(ranges​::​end(*base_*)); [🔗](#lib:end,reverse_view) `constexpr reverse_iterator> end(); constexpr auto end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); ` [5](#range.reverse.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10019) *Effects*: Equivalent to: return make_reverse_iterator(ranges​::​begin(*base_*)); ### [25.7.22](#range.as.const) As const view [[range.as.const]](range.as.const) #### [25.7.22.1](#range.as.const.overview) Overview [[range.as.const.overview]](range.as.const.overview) [1](#range.as.const.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10028) as_const_view presents a view of an underlying sequence as constant[.](#range.as.const.overview-1.sentence-1) That is, the elements of an as_const_view cannot be modified[.](#range.as.const.overview-1.sentence-2) [2](#range.as.const.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10032) The name views​::​as_const denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.as.const.overview-2.sentence-1) Let E be an expression, let T be decltype((E)), and let U be remove_cvref_t[.](#range.as.const.overview-2.sentence-2) The expression views​::​as_const(E) is expression-equivalent to: - [(2.1)](#range.as.const.overview-2.1) If views​::​all_t models [constant_range](range.refinements#concept:constant_range "25.4.6 Other range refinements [range.refinements]"), then views​::​all(E)[.](#range.as.const.overview-2.1.sentence-1) - [(2.2)](#range.as.const.overview-2.2) Otherwise, if U denotes empty_view for some type X, then auto(views​::​empty)[.](#range.as.const.overview-2.2.sentence-1) - [(2.3)](#range.as.const.overview-2.3) Otherwise, if U denotes span for some type X and some extent Extent, then span(E)[.](#range.as.const.overview-2.3.sentence-1) - [(2.4)](#range.as.const.overview-2.4) Otherwise, if U denotes ref_view for some type X andconst X models [constant_range](range.refinements#concept:constant_range "25.4.6 Other range refinements [range.refinements]"), then ref_view(static_cast(E.base()))[.](#range.as.const.overview-2.4.sentence-1) - [(2.5)](#range.as.const.overview-2.5) Otherwise, if E is an lvalue,const U models [constant_range](range.refinements#concept:constant_range "25.4.6 Other range refinements [range.refinements]"), andU does not model [view](range.view#concept:view "25.4.5 Views [range.view]"), then ref_view(static_cast(E))[.](#range.as.const.overview-2.5.sentence-1) - [(2.6)](#range.as.const.overview-2.6) Otherwise, as_const_view(E)[.](#range.as.const.overview-2.6.sentence-1) [3](#range.as.const.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10067) [*Example [1](#range.as.const.overview-example-1)*: template<[constant_range](range.refinements#concept:constant_range "25.4.6 Other range refinements [range.refinements]") R>void cant_touch_this(R&&); vector hammer = {'m', 'c'}; span beat = hammer; cant_touch_this(views::as_const(beat)); // will not modify the elements of hammer — *end example*] #### [25.7.22.2](#range.as.const.view) Class template as_const_view [[range.as.const.view]](range.as.const.view) [🔗](#lib:as_const_view::iterator) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")class as_const_view : public view_interface> { V *base_* = V(); // *exposition only*public: as_const_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit as_const_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) { return ranges::cbegin(*base_*); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") { return ranges::cbegin(*base_*); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) { return ranges::cend(*base_*); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") { return ranges::cend(*base_*); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") { return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") { return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }}; template as_const_view(R&&) -> as_const_view>;} [🔗](#lib:as_const_view::iterator,constructor) `constexpr explicit as_const_view(V base); ` [1](#range.as.const.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10122) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.as.const.view-1.sentence-1) ### [25.7.23](#range.elements) Elements view [[range.elements]](range.elements) #### [25.7.23.1](#range.elements.overview) Overview [[range.elements.overview]](range.elements.overview) [1](#range.elements.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10131) elements_view takes a view of tuple-like values and a size_t, and produces a view with a value-type of the Nth element of the adapted view's value-type[.](#range.elements.overview-1.sentence-1) [2](#range.elements.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10137) The name views​::​elements denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.elements.overview-2.sentence-1) Given a subexpression E and constant expression N, the expression views​::​elements(E) is expression-equivalent toelements_view, N>{E}[.](#range.elements.overview-2.sentence-2) [*Example [1](#range.elements.overview-example-1)*: auto historical_figures = map{ pair{"Lovelace"sv, 1815}, {"Turing"sv, 1912}, {"Babbage"sv, 1791}, {"Hamilton"sv, 1936}}; auto names = historical_figures | views::elements<0>;for (auto&& name : names) { cout << name << ' '; // prints Babbage Hamilton Lovelace Turing }auto birth_years = historical_figures | views::elements<1>;for (auto&& born : birth_years) { cout << born << ' '; // prints 1791 1936 1815 1912 } — *end example*] [3](#range.elements.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10166) keys_view is an alias for elements_view, and is useful for extracting keys from associative containers[.](#range.elements.overview-3.sentence-1) [*Example [2](#range.elements.overview-example-2)*: auto names = historical_figures | views::keys;for (auto&& name : names) { cout << name << ' '; // prints Babbage Hamilton Lovelace Turing } — *end example*] [4](#range.elements.overview-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10179) values_view is an alias for elements_view, and is useful for extracting values from associative containers[.](#range.elements.overview-4.sentence-1) [*Example [3](#range.elements.overview-example-3)*: auto is_even = [](const auto x) { return x % 2 == 0; }; cout << ranges::count_if(historical_figures | views::values, is_even); // prints 2 — *end example*] #### [25.7.23.2](#range.elements.view) Class template elements_view [[range.elements.view]](range.elements.view) [🔗](#lib:elements_view) namespace std::ranges {templateconcept [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]") = // *exposition only*[*tuple-like*](tuple.like#concept:tuple-like "22.4.3 Concept tuple-like [tuple.like]") && N < tuple_size_v; templateconcept [*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]") = // *exposition only* is_reference_v || [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")>; template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]"), N> &&[*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")>, N> &&[*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]"), N>class elements_view : public view_interface> {public: elements_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit elements_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")){ return *iterator*(ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"){ return *iterator*(ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ![common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")){ return *sentinel*{ranges::end(*base_*)}; }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")){ return *iterator*{ranges::end(*base_*)}; }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"){ return *sentinel*{ranges::end(*base_*)}; }constexpr auto end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"){ return *iterator*{ranges::end(*base_*)}; }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }private:// [[range.elements.iterator]](#range.elements.iterator "25.7.23.3 Class template elements_­view​::​iterator"), class template elements_view​::​*iterator*template class *iterator*; // *exposition only*// [[range.elements.sentinel]](#range.elements.sentinel "25.7.23.4 Class template elements_­view​::​sentinel"), class template elements_view​::​*sentinel*template class *sentinel*; // *exposition only* V *base_* = V(); // *exposition only*};} [🔗](#lib:elements_view,constructor) `constexpr explicit elements_view(V base); ` [1](#range.elements.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10267) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.elements.view-1.sentence-1) #### [25.7.23.3](#range.elements.iterator) Class template elements_view​::​*iterator* [[range.elements.iterator]](range.elements.iterator) [🔗](#lib:elements_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]"), N> &&[*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")>, N> &&[*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]"), N>templateclass elements_view::*iterator* {using *Base* = *maybe-const*; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only*static constexpr decltype(auto) *get-element*(const iterator_t<*Base*>& i); // *exposition only*public:using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = remove_cvref_t>>; using difference_type = range_difference_t<*Base*>; *iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")> = default; constexpr explicit *iterator*(iterator_t<*Base*> current); constexpr *iterator*(*iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t<*Base*>>; constexpr const iterator_t<*Base*>& base() const & noexcept; constexpr iterator_t<*Base*> base() &&; constexpr decltype(auto) operator*() const{ return *get-element*(*current_*); }constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr decltype(auto) operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>{ return *get-element*(*current_* + n); }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*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; friend constexpr *iterator* operator+(const *iterator*& x, difference_type y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& x, difference_type y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; };} [1](#range.elements.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10348) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") iterator_concept is defined as follows: - [(1.1)](#range.elements.iterator-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes random_access_iterator_tag[.](#range.elements.iterator-1.1.sentence-1) - [(1.2)](#range.elements.iterator-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.elements.iterator-1.2.sentence-1) - [(1.3)](#range.elements.iterator-1.3) Otherwise, if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes forward_iterator_tag[.](#range.elements.iterator-1.3.sentence-1) - [(1.4)](#range.elements.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.elements.iterator-1.4.sentence-1) [2](#range.elements.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10365) 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 *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.elements.iterator-2.sentence-1) In that case, iterator_category is defined as follows: Let C denote the typeiterator_traits>​::​iterator_category[.](#range.elements.iterator-2.sentence-2) - [(2.1)](#range.elements.iterator-2.1) If std​::​get(**current_*) is an rvalue,iterator_category denotes input_iterator_tag[.](#range.elements.iterator-2.1.sentence-1) - [(2.2)](#range.elements.iterator-2.2) Otherwise, if C models [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"),iterator_category denotes random_access_iterator_tag[.](#range.elements.iterator-2.2.sentence-1) - [(2.3)](#range.elements.iterator-2.3) Otherwise, iterator_category denotes C[.](#range.elements.iterator-2.3.sentence-1) [🔗](#lib:get-element,elements_view::iterator) `static constexpr decltype(auto) get-element(const iterator_t& i); ` [3](#range.elements.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10388) *Effects*: Equivalent to:if constexpr (is_reference_v>) {return std::get(*i);} else {using E = remove_cv_t>>; return static_cast(std::get(*i));} [🔗](#lib:elements_view::iterator,constructor) `constexpr explicit iterator(iterator_t current); ` [4](#range.elements.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10407) *Effects*: Initializes *current_* with std​::​move(current)[.](#range.elements.iterator-4.sentence-1) [🔗](#lib:elements_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [5](#range.elements.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10419) *Effects*: Initializes *current_* with std​::​move(i.*current_*)[.](#range.elements.iterator-5.sentence-1) [🔗](#lib:base,elements_view::iterator) `constexpr const iterator_t& base() const & noexcept; ` [6](#range.elements.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10430) *Effects*: Equivalent to: return *current_*; [🔗](#lib:base,elements_view::iterator_) `constexpr iterator_t base() &&; ` [7](#range.elements.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10441) *Effects*: Equivalent to: return std​::​move(*current_*); [🔗](#lib:operator++,elements_view::iterator) `constexpr iterator& operator++(); ` [8](#range.elements.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10452) *Effects*: Equivalent to:++*current_*;return *this; [🔗](#lib:operator++,elements_view::iterator_) `constexpr void operator++(int); ` [9](#range.elements.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10467) *Effects*: Equivalent to: ++*current_*[.](#range.elements.iterator-9.sentence-1) [🔗](#lib:operator++,elements_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.elements.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10478) *Effects*: Equivalent to:auto temp = *this;++*current_*;return temp; [🔗](#lib:operator--,elements_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.elements.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10494) *Effects*: Equivalent to:--*current_*;return *this; [🔗](#lib:operator--,elements_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.elements.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10509) *Effects*: Equivalent to:auto temp = *this;--*current_*;return temp; [🔗](#lib:operator+=,elements_view::iterator) `constexpr iterator& operator+=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [13](#range.elements.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10526) *Effects*: Equivalent to:*current_* += n;return *this; [🔗](#lib:operator-=,elements_view::iterator) `constexpr iterator& operator-=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [14](#range.elements.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10542) *Effects*: Equivalent to:*current_* -= n;return *this; [🔗](#lib:operator==,elements_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]"); ` [15](#range.elements.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10558) *Effects*: Equivalent to: return x.*current_* == y.*current_*; [🔗](#lib:operator%3c,elements_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [16](#range.elements.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10570) *Effects*: Equivalent to: return x.*current_* < y.*current_*; [🔗](#lib:operator%3e,elements_view::iterator) `friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [17](#range.elements.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10582) *Effects*: Equivalent to: return y < x; [🔗](#lib:operator%3c=,elements_view::iterator) `friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.elements.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10594) *Effects*: Equivalent to: return !(y < x); [🔗](#lib:operator%3e=,elements_view::iterator) `friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [19](#range.elements.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10606) *Effects*: Equivalent to: return !(x < y); [🔗](#lib:operator%3c=%3e,elements_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [20](#range.elements.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10618) *Effects*: Equivalent to: return x.*current_* <=> y.*current_*; [🔗](#lib:operator+,elements_view::iterator) `friend constexpr iterator operator+(const iterator& x, difference_type y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [21](#range.elements.iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10630) *Effects*: Equivalent to: return *iterator*{x} += y; [🔗](#lib:operator+,elements_view::iterator_) `friend constexpr iterator operator+(difference_type x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [22](#range.elements.iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10642) *Effects*: Equivalent to: return y + x; [🔗](#lib:operator-,elements_view::iterator) `friend constexpr iterator operator-(const iterator& x, difference_type y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [23](#range.elements.iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10654) *Effects*: Equivalent to: return *iterator*{x} -= y; [🔗](#lib:operator-,elements_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [24](#range.elements.iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10666) *Effects*: Equivalent to: return x.*current_* - y.*current_*; #### [25.7.23.4](#range.elements.sentinel) Class template elements_view​::​*sentinel* [[range.elements.sentinel]](range.elements.sentinel) [🔗](#lib:elements_view::sentinel) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]"), N> &&[*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")>, N> &&[*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]"), N>templateclass elements_view::*sentinel* {private:using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel* other)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *sentinel*& x, const *iterator*& y); };} [🔗](#lib:elements_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end); ` [1](#range.elements.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10717) *Effects*: Initializes *end_* with end[.](#range.elements.sentinel-1.sentence-1) [🔗](#lib:elements_view::sentinel,constructor_) `constexpr sentinel(sentinel other) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.elements.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10729) *Effects*: Initializes *end_* with std​::​move(other.*end_*)[.](#range.elements.sentinel-2.sentence-1) [🔗](#lib:base,elements_view::sentinel) `constexpr sentinel_t base() const; ` [3](#range.elements.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10740) *Effects*: Equivalent to: return *end_*; [🔗](#lib:operator==,elements_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [4](#range.elements.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10753) *Effects*: Equivalent to: return x.*current_* == y.*end_*; [🔗](#lib:operator-,elements_view::sentinel) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const iterator& x, const sentinel& y); ` [5](#range.elements.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10767) *Effects*: Equivalent to: return x.*current_* - y.*end_*; [🔗](#lib:operator-,elements_view::sentinel_) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const sentinel& x, const iterator& y); ` [6](#range.elements.sentinel-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10781) *Effects*: Equivalent to: return x.*end_* - y.*current_*; ### [25.7.24](#range.enumerate) Enumerate view [[range.enumerate]](range.enumerate) #### [25.7.24.1](#range.enumerate.overview) Overview [[range.enumerate.overview]](range.enumerate.overview) [1](#range.enumerate.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10790) enumerate_view is a view whose elements represent both the position and value from a sequence of elements[.](#range.enumerate.overview-1.sentence-1) [2](#range.enumerate.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10796) The name views​::​enumerate denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.enumerate.overview-2.sentence-1) Given a subexpression E, the expression views​::​enumerate(E) is expression-equivalent toenumerate_view>(E)[.](#range.enumerate.overview-2.sentence-2) [*Example [1](#range.enumerate.overview-example-1)*: vector vec{ 1, 2, 3 };for (auto [index, value] : views::enumerate(vec)) cout << index << ":" << value << ' '; // prints 0:1 1:2 2:3 — *end example*] #### [25.7.24.2](#range.enumerate.view) Class template enumerate_view [[range.enumerate.view]](range.enumerate.view) [🔗](#lib:enumerate_view_) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [*range-with-movable-references*](range.utility.helpers#concept:range-with-movable-references "25.5.2 Helper concepts [range.utility.helpers]")class enumerate_view : public view_interface> { V *base_* = V(); // *exposition only*// [[range.enumerate.iterator]](#range.enumerate.iterator "25.7.24.3 Class template enumerate_­view​::​iterator"), class template enumerate_view​::​*iterator*templateclass *iterator*; // *exposition only*// [[range.enumerate.sentinel]](#range.enumerate.sentinel "25.7.24.4 Class template enumerate_­view​::​sentinel"), class template enumerate_view​::​*sentinel*templateclass *sentinel*; // *exposition only*public:constexpr enumerate_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit enumerate_view(V base); constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")){ return *iterator*(ranges::begin(*base_*), 0); }constexpr auto begin() const requires [*range-with-movable-references*](range.utility.helpers#concept:range-with-movable-references "25.5.2 Helper concepts [range.utility.helpers]"){ return *iterator*(ranges::begin(*base_*), 0); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return *iterator*(ranges::end(*base_*), ranges::distance(*base_*)); elsereturn *sentinel*(ranges::end(*base_*)); }constexpr auto end() const requires [*range-with-movable-references*](range.utility.helpers#concept:range-with-movable-references "25.5.2 Helper concepts [range.utility.helpers]") {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return *iterator*(ranges::end(*base_*), ranges::distance(*base_*)); elsereturn *sentinel*(ranges::end(*base_*)); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"){ return ranges::size(*base_*); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"){ return ranges::reserve_hint(*base_*); }constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }}; template enumerate_view(R&&) -> enumerate_view>;} [🔗](#lib:enumerate_view,constructor) `constexpr explicit enumerate_view(V base); ` [1](#range.enumerate.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10878) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.enumerate.view-1.sentence-1) #### [25.7.24.3](#range.enumerate.iterator) Class template enumerate_view​::​*iterator* [[range.enumerate.iterator]](range.enumerate.iterator) [🔗](#lib:enumerate_view::iterator) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [*range-with-movable-references*](range.utility.helpers#concept:range-with-movable-references "25.5.2 Helper concepts [range.utility.helpers]")templateclass enumerate_view::*iterator* {using *Base* = *maybe-const*; // *exposition only*public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using difference_type = range_difference_t<*Base*>; using value_type = tuple>; private:using *reference-type* = // *exposition only* tuple>; iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only* difference_type *pos_* = 0; // *exposition only*constexpr explicit*iterator*(iterator_t<*Base*> current, difference_type pos); // *exposition only*public:*iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")> = default; constexpr *iterator*(*iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t<*Base*>>; constexpr const iterator_t<*Base*>& base() const & noexcept; constexpr iterator_t<*Base*> base() &&; constexpr difference_type index() const noexcept; constexpr auto operator*() const {return *reference-type*(*pos_*, **current_*); }constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr auto operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>{ return *reference-type*(*pos_* + n, *current_*[n]); }friend constexpr bool operator==(const *iterator*& x, const *iterator*& y) noexcept; friend constexpr strong_ordering operator<=>(const *iterator*& x, const *iterator*& y) noexcept; friend constexpr *iterator* operator+(const *iterator*& x, difference_type y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& x, difference_type y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y) noexcept; friend constexpr auto iter_move(const *iterator*& i)noexcept(noexcept(ranges::iter_move(i.*current_*)) && is_nothrow_move_constructible_v>) {return tuple>(i.*pos_*, ranges::iter_move(i.*current_*)); }};} [1](#range.enumerate.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10960) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.enumerate.iterator-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes random_access_iterator_tag[.](#range.enumerate.iterator-1.1.sentence-1) - [(1.2)](#range.enumerate.iterator-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.enumerate.iterator-1.2.sentence-1) - [(1.3)](#range.enumerate.iterator-1.3) Otherwise, if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes forward_iterator_tag[.](#range.enumerate.iterator-1.3.sentence-1) - [(1.4)](#range.enumerate.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.enumerate.iterator-1.4.sentence-1) [🔗](#lib:enumerate_view::iterator,constructor) `constexpr explicit iterator(iterator_t current, difference_type pos); ` [2](#range.enumerate.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10984) *Effects*: Initializes *current_* with std​::​move(current) and*pos_* with pos[.](#range.enumerate.iterator-2.sentence-1) [🔗](#lib:enumerate_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [3](#range.enumerate.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L10997) *Effects*: Initializes *current_* with std​::​move(i.*current_*) and*pos_* with i.*pos_*[.](#range.enumerate.iterator-3.sentence-1) [🔗](#lib:base,enumerate_view::iterator) `constexpr const iterator_t& base() const & noexcept; ` [4](#range.enumerate.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11009) *Effects*: Equivalent to: return *current_*; [🔗](#lib:base,enumerate_view::iterator_) `constexpr iterator_t base() &&; ` [5](#range.enumerate.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11020) *Effects*: Equivalent to: return std​::​move(*current_*); [🔗](#lib:index,enumerate_view::iterator) `constexpr difference_type index() const noexcept; ` [6](#range.enumerate.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11031) *Effects*: Equivalent to: return *pos_*; [🔗](#lib:operator++,enumerate_view::iterator) `constexpr iterator& operator++(); ` [7](#range.enumerate.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11042) *Effects*: Equivalent to:++*current_*;++*pos_*;return *this; [🔗](#lib:operator++,enumerate_view::iterator_) `constexpr void operator++(int); ` [8](#range.enumerate.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11058) *Effects*: Equivalent to ++*this[.](#range.enumerate.iterator-8.sentence-1) [🔗](#lib:operator++,enumerate_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [9](#range.enumerate.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11069) *Effects*: Equivalent to:auto temp = *this;++*this;return temp; [🔗](#lib:operator--,enumerate_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.enumerate.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11085) *Effects*: Equivalent to:--*current_*;--*pos_*;return *this; [🔗](#lib:operator--,enumerate_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.enumerate.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11101) *Effects*: Equivalent to:auto temp = *this;--*this;return temp; [🔗](#lib:operator+=,enumerate_view::iterator) `constexpr iterator& operator+=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.enumerate.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11118) *Effects*: Equivalent to:*current_* += n;*pos_* += n;return *this; [🔗](#lib:operator-=,enumerate_view::iterator) `constexpr iterator& operator-=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [13](#range.enumerate.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11135) *Effects*: Equivalent to:*current_* -= n;*pos_* -= n;return *this; [🔗](#lib:operator==,enumerate_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept; ` [14](#range.enumerate.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11151) *Effects*: Equivalent to: return x.*pos_* == y.*pos_*; [🔗](#lib:operator%3c=%3e,enumerate_view::iterator) `friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept; ` [15](#range.enumerate.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11162) *Effects*: Equivalent to: return x.*pos_* <=> y.*pos_*; [🔗](#lib:operator+,enumerate_view::iterator) `friend constexpr iterator operator+(const iterator& x, difference_type y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [16](#range.enumerate.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11174) *Effects*: Equivalent to:auto temp = x; temp += y;return temp; [🔗](#lib:operator+,enumerate_view::iterator_) `friend constexpr iterator operator+(difference_type x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [17](#range.enumerate.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11191) *Effects*: Equivalent to: return y + x; [🔗](#lib:operator-,enumerate_view::iterator) `friend constexpr iterator operator-(const iterator& x, difference_type y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.enumerate.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11203) *Effects*: Equivalent to:auto temp = x; temp -= y;return temp; [🔗](#lib:operator-,enumerate_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept; ` [19](#range.enumerate.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11219) *Effects*: Equivalent to: return x.*pos_* - y.*pos_*; #### [25.7.24.4](#range.enumerate.sentinel) Class template enumerate_view​::​*sentinel* [[range.enumerate.sentinel]](range.enumerate.sentinel) [🔗](#lib:enumerate_view::sentinel) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [*range-with-movable-references*](range.utility.helpers#concept:range-with-movable-references "25.5.2 Helper concepts [range.utility.helpers]")templateclass enumerate_view::*sentinel* {using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*constexpr explicit *sentinel*(sentinel_t<*Base*> end); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel* other)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *sentinel*& x, const *iterator*& y); };} [🔗](#lib:enumerate_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end); ` [1](#range.enumerate.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11267) *Effects*: Initializes *end_* with std​::​move(end)[.](#range.enumerate.sentinel-1.sentence-1) [🔗](#lib:enumerate_view::sentinel,constructor_) `constexpr sentinel(sentinel other) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.enumerate.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11279) *Effects*: Initializes *end_* with std​::​move(other.*end_*)[.](#range.enumerate.sentinel-2.sentence-1) [🔗](#lib:base,enumerate_view::sentinel) `constexpr sentinel_t base() const; ` [3](#range.enumerate.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11290) *Effects*: Equivalent to: return *end_*; [🔗](#lib:operator==,enumerate_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [4](#range.enumerate.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11303) *Effects*: Equivalent to: return x.*current_* == y.*end_*; [🔗](#lib:operator-,enumerate_view::sentinel) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const iterator& x, const sentinel& y); ` [5](#range.enumerate.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11317) *Effects*: Equivalent to: return x.*current_* - y.*end_*; [🔗](#lib:operator-,enumerate_view::sentinel_) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const sentinel& x, const iterator& y); ` [6](#range.enumerate.sentinel-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11331) *Effects*: Equivalent to: return x.*end_* - y.*current_*; ### [25.7.25](#range.zip) Zip view [[range.zip]](range.zip) #### [25.7.25.1](#range.zip.overview) Overview [[range.zip.overview]](range.zip.overview) [1](#range.zip.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11340) zip_view takes any number of views and produces a view of tuples of references to the corresponding elements of the constituent views[.](#range.zip.overview-1.sentence-1) [2](#range.zip.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11346) The name views​::​zip denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#range.zip.overview-2.sentence-1) Given a pack of subexpressions Es..., the expression views​::​zip(Es...) is expression-equivalent to - [(2.1)](#range.zip.overview-2.1) auto(views​::​empty>) if Es is an empty pack, - [(2.2)](#range.zip.overview-2.2) otherwise, zip_view...>(Es...)[.](#range.zip.overview-2.sentence-2) [*Example [1](#range.zip.overview-example-1)*: vector v = {1, 2}; list l = {'a', 'b', 'c'}; auto z = views::zip(v, l); range_reference_t f = z.front(); // f is a tuple// that refers to the first element of v and lfor (auto&& [x, y] : z) { cout << '(' << x << ", " << y << ") "; // prints (1, a) (2, b)} — *end example*] #### [25.7.25.2](#range.zip.view) Class template zip_view [[range.zip.view]](range.zip.view) [🔗](#lib:zip_view_) namespace std::ranges {templateconcept [*zip-is-common*](#concept:zip-is-common "25.7.25.2 Class template zip_­view [range.zip.view]") = // *exposition only*(sizeof...(Rs) == 1 && ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && ...)) ||(!([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && ...) && ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && ...)) ||(([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && ...) && ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && ...)); 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)class zip_view : public view_interface> { tuple *views_*; // *exposition only*// [[range.zip.iterator]](#range.zip.iterator "25.7.25.3 Class template zip_­view​::​iterator"), class template zip_view​::​*iterator*template class *iterator*; // *exposition only*// [[range.zip.sentinel]](#range.zip.sentinel "25.7.25.4 Class template zip_­view​::​sentinel"), class template zip_view​::​*sentinel*template class *sentinel*; // *exposition only*public: zip_view() = default; constexpr explicit zip_view(Views... views); constexpr auto begin() requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ...)) {return *iterator*(*tuple-transform*(ranges::begin, *views_*)); }constexpr auto begin() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ...) {return *iterator*(*tuple-transform*(ranges::begin, *views_*)); }constexpr auto end() requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && ...)) {if constexpr (![*zip-is-common*](#concept:zip-is-common "25.7.25.2 Class template zip_­view [range.zip.view]")) {return *sentinel*(*tuple-transform*(ranges::end, *views_*)); } else if constexpr (([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && ...)) {return begin() + iter_difference_t<*iterator*>(size()); } else {return *iterator*(*tuple-transform*(ranges::end, *views_*)); }}constexpr auto end() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ...) {if constexpr (![*zip-is-common*](#concept:zip-is-common "25.7.25.2 Class template zip_­view [range.zip.view]")) {return *sentinel*(*tuple-transform*(ranges::end, *views_*)); } else if constexpr (([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && ...)) {return begin() + iter_difference_t<*iterator*>(size()); } else {return *iterator*(*tuple-transform*(ranges::end, *views_*)); }}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 zip_view(Rs&&...) -> zip_view...>;} [1](#range.zip.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11439) Two zip_view objects have the same underlying sequence if and only if the corresponding elements of *views_* are equal ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) and have the same underlying sequence[.](#range.zip.view-1.sentence-1) [*Note [1](#range.zip.view-note-1)*: In particular, comparison of iterators obtained from zip_view objects that do not have the same underlying sequence is not required to produce meaningful results ([[iterator.concept.forward]](iterator.concept.forward "24.3.4.11 Concept forward_­iterator"))[.](#range.zip.view-1.sentence-2) — *end note*] [🔗](#lib:zip_view,constructor) `constexpr explicit zip_view(Views... views); ` [2](#range.zip.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11455) *Effects*: Initializes *views_* with std​::​move(views)...[.](#range.zip.view-2.sentence-1) [🔗](#lib:size,zip_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]") && ...); ` [3](#range.zip.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11467) *Effects*: Equivalent to:return apply([](auto... sizes) {using CT = *make-unsigned-like-t*>; return ranges::min({CT(sizes)...});}, *tuple-transform*(ranges::size, *views_*)); #### [25.7.25.3](#range.zip.iterator) Class template zip_view​::​*iterator* [[range.zip.iterator]](range.zip.iterator) [🔗](#lib:zip_view::iterator) 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)templateclass zip_view::*iterator* { tuple>...> *current_*; // *exposition only*constexpr explicit *iterator*(tuple>...>); // *exposition only*public:using iterator_category = input_iterator_tag; // not always presentusing iterator_concept = *see below*; using value_type = tuple>...>; using difference_type = common_type_t>...>; *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 auto operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [*all-forward*](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); constexpr *iterator*& operator--() requires [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); constexpr *iterator* operator--(int) requires [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); constexpr *iterator*& operator+=(difference_type x)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); constexpr *iterator*& operator-=(difference_type x)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); constexpr auto operator[](difference_type n) constrequires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); 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 auto operator<=>(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires ([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*>> && ...); friend constexpr auto iter_move(const *iterator*& i) noexcept(*see below*); friend constexpr void iter_swap(const *iterator*& l, const *iterator*& r) noexcept(*see below*)requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>> && ...); };} [1](#range.zip.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11540) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.zip.iterator-1.1) If [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled, then iterator_concept denotes random_access_iterator_tag[.](#range.zip.iterator-1.1.sentence-1) - [(1.2)](#range.zip.iterator-1.2) Otherwise, if [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled, then iterator_concept denotes bidirectional_iterator_tag[.](#range.zip.iterator-1.2.sentence-1) - [(1.3)](#range.zip.iterator-1.3) Otherwise, if [*all-forward*](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled, then iterator_concept denotes forward_iterator_tag[.](#range.zip.iterator-1.3.sentence-1) - [(1.4)](#range.zip.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.zip.iterator-1.4.sentence-1) [2](#range.zip.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11558) *iterator*​::​iterator_category is present if and only if [*all-forward*](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is modeled[.](#range.zip.iterator-2.sentence-1) [3](#range.zip.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11562) If the invocation of any non-const member function of *iterator* exits via an exception, the iterator acquires a singular value[.](#range.zip.iterator-3.sentence-1) [🔗](#lib:zip_view::iterator,constructor) `constexpr explicit iterator(tuple>...> current); ` [4](#range.zip.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11573) *Effects*: Initializes *current_* with std​::​move(current)[.](#range.zip.iterator-4.sentence-1) [🔗](#lib:zip_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t> && ...); ` [5](#range.zip.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11585) *Effects*: Initializes *current_* with std​::​move(i.*current_*)[.](#range.zip.iterator-5.sentence-1) [🔗](#lib:operator*,izip_view::iterator) `constexpr auto operator*() const; ` [6](#range.zip.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11596) *Effects*: Equivalent to:return *tuple-transform*([](auto& i) -> decltype(auto) { return *i; }, *current_*); [🔗](#lib:operator++,izip_view::iterator) `constexpr iterator& operator++(); ` [7](#range.zip.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11610) *Effects*: Equivalent to:*tuple-for-each*([](auto& i) { ++i; }, *current_*);return *this; [🔗](#lib:operator++,izip_view::iterator_) `constexpr void operator++(int); ` [8](#range.zip.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11625) *Effects*: Equivalent to ++*this[.](#range.zip.iterator-8.sentence-1) [🔗](#lib:operator++,izip_view::iterator__) `constexpr iterator operator++(int) requires [all-forward](#concept:all-forward "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [9](#range.zip.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11636) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,izip_view::iterator) `constexpr iterator& operator--() requires [all-bidirectional](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [10](#range.zip.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11652) *Effects*: Equivalent to:*tuple-for-each*([](auto& i) { --i; }, *current_*);return *this; [🔗](#lib:operator--,izip_view::iterator_) `constexpr iterator operator--(int) requires [all-bidirectional](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [11](#range.zip.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11667) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,izip_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [12](#range.zip.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11684) *Effects*: Equivalent to:*tuple-for-each*([&](I& i) { i += iter_difference_t(x); }, *current_*);return *this; [🔗](#lib:operator-=,izip_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [13](#range.zip.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11700) *Effects*: Equivalent to:*tuple-for-each*([&](I& i) { i -= iter_difference_t(x); }, *current_*);return *this; [🔗](#lib:operator%5b%5d,izip_view::iterator) `constexpr auto operator[](difference_type n) const requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [14](#range.zip.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11716) *Effects*: Equivalent to:return *tuple-transform*([&](I& i) -> decltype(auto) {return i[iter_difference_t(n)];}, *current_*); [🔗](#lib:operator==,izip_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]")>> && ...); ` [15](#range.zip.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11733) *Returns*: - [(15.1)](#range.zip.iterator-15.1) x.*current_* == y.*current_* if [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]") is true[.](#range.zip.iterator-15.1.sentence-1) - [(15.2)](#range.zip.iterator-15.2) Otherwise, true if there exists an integer 0≤i(x.*current_*) == std​::​get(y.*current_*)) is true[.](#range.zip.iterator-15.2.sentence-1) [*Note [1](#range.zip.iterator-note-1)*: This allows zip_view to model [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") when all constituent views model [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")[.](#range.zip.iterator-15.2.sentence-2) — *end note*] - [(15.3)](#range.zip.iterator-15.3) Otherwise, false[.](#range.zip.iterator-15.3.sentence-1) [🔗](#lib:operator%3c=%3e,izip_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [16](#range.zip.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11760) *Returns*: x.*current_* <=> y.*current_*[.](#range.zip.iterator-16.sentence-1) [🔗](#lib:operator+,izip_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [17](#range.zip.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11774) *Effects*: Equivalent to:auto r = i; r += n;return r; [🔗](#lib:operator-,izip_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [18](#range.zip.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11791) *Effects*: Equivalent to:auto r = i; r -= n;return r; [🔗](#lib:operator-,izip_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")>, iterator_t>> && ...); ` [19](#range.zip.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11809) Let *DIST*(i) be difference_type(std​::​get(x.*current_*) - std​::​get(y.*current_*))[.](#range.zip.iterator-19.sentence-1) [20](#range.zip.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11812) *Returns*: The value with the smallest absolute value among *DIST*(n) for all integers 0≤n>&>())) && ...) &&(is_nothrow_move_constructible_v>> && ...) [🔗](#lib:iter_swap,izip_view::iterator) `friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>> && ...); ` [23](#range.zip.iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11849) *Effects*: For every integer 0≤i(l.*current_*), std::get(r.*current_*)) [24](#range.zip.iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11857) *Remarks*: The exception specification is equivalent to the logical and of the following expressions:noexcept(ranges::iter_swap(std::get(l.*current_*), std::get(r.*current_*))) for every integer 0≤irequires ([view](range.view#concept:view "25.4.5 Views [range.view]") && ...) && (sizeof...(Views) > 0)templateclass zip_view::*sentinel* { tuple>...> *end_*; // *exposition only*constexpr explicit *sentinel*(tuple>...> end); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel* i)requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t> && ...); templaterequires ([sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")>, iterator_t<*maybe-const*>> && ...)friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires ([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*>> && ...)friend constexpr common_type_t>...>operator-(const *iterator*& x, const *sentinel*& y); templaterequires ([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*>> && ...)friend constexpr common_type_t>...>operator-(const *sentinel*& y, const *iterator*& x); };} [🔗](#lib:zip_view::sentinel,constructor) `constexpr explicit sentinel(tuple>...> end); ` [1](#range.zip.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11910) *Effects*: Initializes *end_* with end[.](#range.zip.sentinel-1.sentence-1) [🔗](#lib:zip_view::sentinel,constructor_) `constexpr sentinel(sentinel i) requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t> && ...); ` [2](#range.zip.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11922) *Effects*: Initializes *end_* with std​::​move(i.*end_*)[.](#range.zip.sentinel-2.sentence-1) [🔗](#lib:operator==,zip_view::sentinel) `template requires ([sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")>, iterator_t>> && ...) friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.zip.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11936) *Returns*: true if there exists an integer 0≤i(x.​*current_*) == std​::​get(y.*end_*)) is true[.](#range.zip.sentinel-3.sentence-1) Otherwise, false[.](#range.zip.sentinel-3.sentence-2) [🔗](#lib:operator-,zip_view::sentinel) `template requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")>, iterator_t>> && ...) friend constexpr common_type_t>...> operator-(const iterator& x, const sentinel& y); ` [4](#range.zip.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11954) Let D be the return type[.](#range.zip.sentinel-4.sentence-1) Let *DIST*(i) beD(std​::​get(x.*current_*) - std​::​get(y.*end_*))[.](#range.zip.sentinel-4.sentence-2) [5](#range.zip.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11959) *Returns*: The value with the smallest absolute value among *DIST*(n) for all integers 0≤n requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")>, iterator_t>> && ...) friend constexpr common_type_t>...> operator-(const sentinel& y, const iterator& x); ` [6](#range.zip.sentinel-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11975) *Effects*: Equivalent to: return -(x - y); ### [25.7.26](#range.zip.transform) Zip transform view [[range.zip.transform]](range.zip.transform) #### [25.7.26.1](#range.zip.transform.overview) Overview [[range.zip.transform.overview]](range.zip.transform.overview) [1](#range.zip.transform.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11984) zip_transform_view takes an invocable object and any number of views and produces a view whose Mth element is the result of applying the invocable object to the Mth elements of all views[.](#range.zip.transform.overview-1.sentence-1) [2](#range.zip.transform.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11993) The name views​::​zip_transform denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#range.zip.transform.overview-2.sentence-1) Let F be a subexpression, and let Es... be a pack of subexpressions[.](#range.zip.transform.overview-2.sentence-2) - [(2.1)](#range.zip.transform.overview-2.1) If Es is an empty pack, let FD be decay_t[.](#range.zip.transform.overview-2.1.sentence-1) * [(2.1.1)](#range.zip.transform.overview-2.1.1) If [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]") is false, or if decay_t> is not an object type,views​::​zip_transform(F, Es...) is ill-formed. * [(2.1.2)](#range.zip.transform.overview-2.1.2) Otherwise, the expression views​::​zip_transform(F, Es...) is expression-equivalent to((void)F, auto(views::empty>>)) - [(2.2)](#range.zip.transform.overview-2.2) Otherwise, the expression views​::​zip_transform(F, Es...) is expression-equivalent to zip_transform_view(F, Es...)[.](#range.zip.transform.overview-2.2.sentence-1) [3](#range.zip.transform.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12021) [*Example [1](#range.zip.transform.overview-example-1)*: vector v1 = {1, 2}; vector v2 = {4, 5, 6}; for (auto i : views::zip_transform(plus(), v1, v2)) { cout << i << ' '; // prints 5 7} — *end example*] #### [25.7.26.2](#range.zip.transform.view) Class template zip_transform_view [[range.zip.transform.view]](range.zip.transform.view) [🔗](#lib:zip_transform_view_) namespace std::ranges {template<[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F, [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) && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]")...>>class zip_transform_view : public view_interface> {*movable-box* *fun_*; // *exposition only* zip_view *zip_*; // *exposition only*using *InnerView* = zip_view; // *exposition only*templateusing *ziperator* = iterator_t<*maybe-const*>; // *exposition only*templateusing *zentinel* = sentinel_t<*maybe-const*>; // *exposition only*// [[range.zip.transform.iterator]](#range.zip.transform.iterator "25.7.26.3 Class template zip_­transform_­view​::​iterator"), class template zip_transform_view​::​*iterator*template class *iterator*; // *exposition only*// [[range.zip.transform.sentinel]](#range.zip.transform.sentinel "25.7.26.4 Class template zip_­transform_­view​::​sentinel"), class template zip_transform_view​::​*sentinel*template class *sentinel*; // *exposition only*public: zip_transform_view() = default; constexpr explicit zip_transform_view(F fun, Views... views); constexpr auto begin() { return *iterator*(*this, *zip_*.begin()); }constexpr auto begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")...> {return *iterator*(*this, *zip_*.begin()); }constexpr auto end() {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*InnerView*>) {return *iterator*(*this, *zip_*.end()); } else {return *sentinel*(*zip_*.end()); }}constexpr auto end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")...> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(*this, *zip_*.end()); } else {return *sentinel*(*zip_*.end()); }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*InnerView*> {return *zip_*.size(); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {return *zip_*.size(); }}; template zip_transform_view(F, Rs&&...) -> zip_transform_view...>;} [🔗](#lib:zip_transform_view,constructor) `constexpr explicit zip_transform_view(F fun, Views... views); ` [1](#range.zip.transform.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12112) *Effects*: Initializes *fun_* with std​::​move(fun) and*zip_* with std​::​move(views)...[.](#range.zip.transform.view-1.sentence-1) #### [25.7.26.3](#range.zip.transform.iterator) Class template zip_transform_view​::​*iterator* [[range.zip.transform.iterator]](range.zip.transform.iterator) [🔗](#lib:zip_transform_view::iterator) namespace std::ranges {template<[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F, [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) && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]")...>>templateclass zip_transform_view::*iterator* {using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only**Parent** *parent_* = nullptr; // *exposition only**ziperator* *inner_*; // *exposition only*constexpr *iterator*(*Parent*& parent, *ziperator* inner); // *exposition only*public:using iterator_category = *see below*; // not always presentusing iterator_concept = typename *ziperator*::iterator_concept; using value_type = remove_cvref_t&, range_reference_t<*maybe-const*>...>>; using difference_type = range_difference_t<*Base*>; *iterator*() = default; constexpr *iterator*(*iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*ziperator*, *ziperator*>; constexpr decltype(auto) operator*() const noexcept(*see below*); constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr decltype(auto) operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; 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]")<*ziperator*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*ziperator*, *ziperator*>; };} [1](#range.zip.transform.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12180) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*iterator*​::​iterator_category is defined if and only if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.zip.transform.iterator-1.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(1.1)](#range.zip.transform.iterator-1.1) Ifinvoke_result_t<*maybe-const*&, range_reference_t<*maybe-const*>...> is not a reference,iterator_category denotes input_iterator_tag. - [(1.2)](#range.zip.transform.iterator-1.2) Otherwise, let Cs denote the pack of typesiterator_traits>>​::​iterator_category.... * [(1.2.1)](#range.zip.transform.iterator-1.2.1) If ([derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") && ...) is true,iterator_category denotes random_access_iterator_tag[.](#range.zip.transform.iterator-1.2.1.sentence-1) * [(1.2.2)](#range.zip.transform.iterator-1.2.2) Otherwise, if ([derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") && ...) is true,iterator_category denotes bidirectional_iterator_tag[.](#range.zip.transform.iterator-1.2.2.sentence-1) * [(1.2.3)](#range.zip.transform.iterator-1.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[.](#range.zip.transform.iterator-1.2.3.sentence-1) * [(1.2.4)](#range.zip.transform.iterator-1.2.4) Otherwise, iterator_category denotes input_iterator_tag[.](#range.zip.transform.iterator-1.2.4.sentence-1) [🔗](#lib:zip_transform_view::iterator,constructor) `constexpr iterator(Parent& parent, ziperator inner); ` [2](#range.zip.transform.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12223) *Effects*: Initializes *parent_* with addressof(parent) and*inner_* with std​::​move(inner)[.](#range.zip.transform.iterator-2.sentence-1) [🔗](#lib:zip_transform_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), ziperator>; ` [3](#range.zip.transform.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12236) *Effects*: Initializes *parent_* with i.*parent_* and*inner_* with std​::​move(i.*inner_*)[.](#range.zip.transform.iterator-3.sentence-1) [🔗](#lib:operator*,zip_transform_view::iterator) `constexpr decltype(auto) operator*() const noexcept(see below); ` [4](#range.zip.transform.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12248) *Effects*: Equivalent to:return apply([&](const auto&... iters) -> decltype(auto) {return invoke(**parent_*->*fun_*, *iters...);}, *inner_*.*current_*); [5](#range.zip.transform.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12257) *Remarks*: Let Is be the pack 0, 1, …, (sizeof...(Views) - 1)[.](#range.zip.transform.iterator-5.sentence-1) The exception specification is equivalent to:noexcept(invoke(**parent_*->*fun_*, *std​::​get(*inner_*.*current_*)...))[.](#range.zip.transform.iterator-5.sentence-2) [🔗](#lib:operator++,zip_transform_view::iterator) `constexpr iterator& operator++(); ` [6](#range.zip.transform.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12270) *Effects*: Equivalent to:++*inner_*;return *this; [🔗](#lib:operator++,zip_transform_view::iterator_) `constexpr void operator++(int); ` [7](#range.zip.transform.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12285) *Effects*: Equivalent to: ++*this[.](#range.zip.transform.iterator-7.sentence-1) [🔗](#lib:operator++,zip_transform_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [8](#range.zip.transform.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12296) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,zip_transform_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [9](#range.zip.transform.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12312) *Effects*: Equivalent to:--*inner_*;return *this; [🔗](#lib:operator--,zip_transform_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.zip.transform.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12327) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,zip_transform_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.zip.transform.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12344) *Effects*: Equivalent to:*inner_* += x;return *this; [🔗](#lib:operator+=,zip_transform_view::iterator_) `constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.zip.transform.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12360) *Effects*: Equivalent to:*inner_* -= x;return *this; [🔗](#lib:operator%5b%5d,zip_transform_view::iterator) `constexpr decltype(auto) operator[](difference_type n) const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [13](#range.zip.transform.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12376) *Effects*: Equivalent to:return apply([&](const Is&... iters) -> decltype(auto) {return invoke(**parent_*->*fun_*, iters[iter_difference_t(n)]...);}, *inner_*.*current_*); [🔗](#lib:operator==,zip_transform_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]")>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [14](#range.zip.transform.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12395) Let *op* be the operator[.](#range.zip.transform.iterator-14.sentence-1) [15](#range.zip.transform.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12398) *Effects*: Equivalent to:return x.*inner_* *op* y.*inner_*; [🔗](#lib:operator+,zip_transform_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [16](#range.zip.transform.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12413) *Effects*: Equivalent to:return *iterator*(*i.*parent_*, i.*inner_* + n); [🔗](#lib:operator-,zip_transform_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [17](#range.zip.transform.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12426) *Effects*: Equivalent to:return *iterator*(*i.*parent_*, i.*inner_* - n); [🔗](#lib:operator-,zip_transform_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), ziperator>; ` [18](#range.zip.transform.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12439) *Effects*: Equivalent to:return x.*inner_* - y.*inner_*; #### [25.7.26.4](#range.zip.transform.sentinel) Class template zip_transform_view​::​*sentinel* [[range.zip.transform.sentinel]](range.zip.transform.sentinel) [🔗](#lib:zip_transform_view::sentinel) namespace std::ranges {template<[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F, [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) && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]")...>>templateclass zip_transform_view::*sentinel* {*zentinel* *inner_*; // *exposition only*constexpr explicit *sentinel*(*zentinel* inner); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*zentinel*, *zentinel*>; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<*zentinel*, *ziperator*>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*zentinel*, *ziperator*>friend constexpr range_difference_t<*maybe-const*>operator-(const *iterator*& x, const *sentinel*& y); templaterequires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*zentinel*, *ziperator*>friend constexpr range_difference_t<*maybe-const*>operator-(const *sentinel*& x, const *iterator*& y); };} [🔗](#lib:zip_transform_view::sentinel,constructor) `constexpr explicit sentinel(zentinel inner); ` [1](#range.zip.transform.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12487) *Effects*: Initializes *inner_* with inner[.](#range.zip.transform.sentinel-1.sentence-1) [🔗](#lib:zip_transform_view::sentinel,constructor_) `constexpr sentinel(sentinel i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), zentinel>; ` [2](#range.zip.transform.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12499) *Effects*: Initializes *inner_* with std​::​move(i.*inner_*)[.](#range.zip.transform.sentinel-2.sentence-1) [🔗](#lib:operator==,zip_transform_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), ziperator> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.zip.transform.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12512) *Effects*: Equivalent to: return x.*inner_* == y.*inner_*; [🔗](#lib:operator-,zip_transform_view::sentinel) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), ziperator> friend constexpr range_difference_t> operator-(const iterator& x, const sentinel& y); template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), ziperator> friend constexpr range_difference_t> operator-(const sentinel& x, const iterator& y); ` [4](#range.zip.transform.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12530) *Effects*: Equivalent to: return x.*inner_* - y.*inner_*; ### [25.7.27](#range.adjacent) Adjacent view [[range.adjacent]](range.adjacent) #### [25.7.27.1](#range.adjacent.overview) Overview [[range.adjacent.overview]](range.adjacent.overview) [1](#range.adjacent.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12539) adjacent_view takes a view and produces a view whose Mth element is a tuple of references to the Mth through (M+N−1)th elements of the original view[.](#range.adjacent.overview-1.sentence-1) If the original view has fewer than N elements, the resulting view is empty[.](#range.adjacent.overview-1.sentence-2) [2](#range.adjacent.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12547) The name views​::​adjacent denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.adjacent.overview-2.sentence-1) Given a subexpression E and a constant expression N, the expression views​::​adjacent(E) is expression-equivalent to - [(2.1)](#range.adjacent.overview-2.1) ((void)E, auto(views​::​empty>)) if N is equal to 0 anddecltype((E)) models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), - [(2.2)](#range.adjacent.overview-2.2) otherwise, adjacent_view, N>(E)[.](#range.adjacent.overview-2.sentence-2) [*Example [1](#range.adjacent.overview-example-1)*: vector v = {1, 2, 3, 4}; for (auto i : v | views::adjacent<2>) { cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints (1, 2) (2, 3) (3, 4)} — *end example*] [3](#range.adjacent.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12572) Define *REPEAT*(T, N) as a pack of N types, each of which denotes the same type as T[.](#range.adjacent.overview-3.sentence-1) #### [25.7.27.2](#range.adjacent.view) Class template adjacent_view [[range.adjacent.view]](range.adjacent.view) [🔗](#lib:adjacent_view) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && (N > 0)class adjacent_view : public view_interface> { V *base_* = V(); // *exposition only*// [[range.adjacent.iterator]](#range.adjacent.iterator "25.7.27.3 Class template adjacent_­view​::​iterator"), class template adjacent_view​::​*iterator*template class *iterator*; // *exposition only*// [[range.adjacent.sentinel]](#range.adjacent.sentinel "25.7.27.4 Class template adjacent_­view​::​sentinel"), class template adjacent_view​::​*sentinel*template class *sentinel*; // *exposition only*struct *as-sentinel*{}; // *exposition only*public: adjacent_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit adjacent_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {return *iterator*(ranges::begin(*base_*), ranges::end(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {return *iterator*(ranges::begin(*base_*), ranges::end(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(*as-sentinel*{}, ranges::begin(*base_*), ranges::end(*base_*)); } else {return *sentinel*(ranges::end(*base_*)); }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(*as-sentinel*{}, ranges::begin(*base_*), ranges::end(*base_*)); } else {return *sentinel*(ranges::end(*base_*)); }}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]"); constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); };} [🔗](#lib:adjacent_view,constructor) `constexpr explicit adjacent_view(V base); ` [1](#range.adjacent.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12642) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.adjacent.view-1.sentence-1) [🔗](#lib:size,adjacent_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]"); ` [2](#range.adjacent.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12654) *Effects*: Equivalent to:using ST = decltype(ranges::size(*base_*));using CT = common_type_t;auto sz = static_cast(ranges::size(*base_*)); sz -= std::min(sz, N - 1);return static_cast(sz); [🔗](#lib:reserve_hint,adjacent_view) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [3](#range.adjacent.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12673) *Effects*: Equivalent to:using DT = range_difference_t;using CT = common_type_t;auto sz = static_cast(ranges::reserve_hint(*base_*)); sz -= std::min(sz, N - 1);return *to-unsigned-like*(sz); #### [25.7.27.3](#range.adjacent.iterator) Class template adjacent_view​::​*iterator* [[range.adjacent.iterator]](range.adjacent.iterator) [🔗](#lib:adjacent_view::iterator) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && (N > 0)templateclass adjacent_view::*iterator* {using *Base* = *maybe-const*; // *exposition only* array, N> *current_* = array, N>(); // *exposition only*constexpr *iterator*(iterator_t<*Base*> first, sentinel_t<*Base*> last); // *exposition only*constexpr *iterator*(*as-sentinel*, iterator_t<*Base*> first, iterator_t<*Base*> last); // *exposition only*public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = tuple<*REPEAT*(range_value_t<*Base*>, N)...>; using difference_type = range_difference_t<*Base*>; *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<*Base*>>; constexpr auto operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr auto operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); friend constexpr bool operator<(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr auto iter_move(const *iterator*& i) noexcept(*see below*); friend constexpr void iter_swap(const *iterator*& l, const *iterator*& r) noexcept(*see below*)requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [1](#range.adjacent.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12753) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.adjacent.iterator-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes random_access_iterator_tag[.](#range.adjacent.iterator-1.1.sentence-1) - [(1.2)](#range.adjacent.iterator-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.adjacent.iterator-1.2.sentence-1) - [(1.3)](#range.adjacent.iterator-1.3) Otherwise, iterator_concept denotes forward_iterator_tag[.](#range.adjacent.iterator-1.3.sentence-1) [2](#range.adjacent.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12766) If the invocation of any non-const member function of *iterator* exits via an exception, the *iterator* acquires a singular value[.](#range.adjacent.iterator-2.sentence-1) [🔗](#lib:adjacent_view::iterator,constructor) `constexpr iterator(iterator_t first, sentinel_t last); ` [3](#range.adjacent.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12776) *Postconditions*: *current_*[0] == first is true, and for every integer 1≤i first, iterator_t last); ` [4](#range.adjacent.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12790) *Postconditions*: If *Base* does not model [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), each element of *current_* is equal to *last*[.](#range.adjacent.iterator-4.sentence-1) Otherwise, *current_*[N-1] == last is true, and for every integer 0≤i<(N−1),*current_*[i] == ranges​::​prev(*current_*[i+1], 1, first) is true[.](#range.adjacent.iterator-4.sentence-2) [🔗](#lib:adjacent_view::iterator,constructor__) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [5](#range.adjacent.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12807) *Effects*: Initializes each element of *current_* with the corresponding element of i.*current_* as an xvalue[.](#range.adjacent.iterator-5.sentence-1) [🔗](#lib:operator*,adjacent_view::iterator) `constexpr auto operator*() const; ` [6](#range.adjacent.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12819) *Effects*: Equivalent to:return *tuple-transform*([](auto& i) -> decltype(auto) { return *i; }, *current_*); [🔗](#lib:operator++,adjacent_view::iterator) `constexpr iterator& operator++(); ` [7](#range.adjacent.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12833) *Preconditions*: *current_*.back() is incrementable[.](#range.adjacent.iterator-7.sentence-1) [8](#range.adjacent.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12837) *Postconditions*: Each element of *current_* is equal to ranges​::​next(i), where i is the value of that element before the call[.](#range.adjacent.iterator-8.sentence-1) [9](#range.adjacent.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12842) *Returns*: *this[.](#range.adjacent.iterator-9.sentence-1) [🔗](#lib:operator++,adjacent_view::iterator_) `constexpr iterator operator++(int); ` [10](#range.adjacent.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12853) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,adjacent_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.adjacent.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12869) *Preconditions*: *current_*.front() is decrementable[.](#range.adjacent.iterator-11.sentence-1) [12](#range.adjacent.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12873) *Postconditions*: Each element of *current_* is equal to ranges​::​prev(i), where i is the value of that element before the call[.](#range.adjacent.iterator-12.sentence-1) [13](#range.adjacent.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12878) *Returns*: *this[.](#range.adjacent.iterator-13.sentence-1) [🔗](#lib:operator--,adjacent_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [14](#range.adjacent.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12889) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,adjacent_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [15](#range.adjacent.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12906) *Preconditions*: *current_*.back() + x has well-defined behavior[.](#range.adjacent.iterator-15.sentence-1) [16](#range.adjacent.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12910) *Postconditions*: Each element of *current_* is equal to i + x, where i is the value of that element before the call[.](#range.adjacent.iterator-16.sentence-1) [17](#range.adjacent.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12915) *Returns*: *this[.](#range.adjacent.iterator-17.sentence-1) [🔗](#lib:operator-=,adjacent_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.adjacent.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12927) *Preconditions*: *current_*.front() - x has well-defined behavior[.](#range.adjacent.iterator-18.sentence-1) [19](#range.adjacent.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12931) *Postconditions*: Each element of *current_* is equal to i - x, where i is the value of that element before the call[.](#range.adjacent.iterator-19.sentence-1) [20](#range.adjacent.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12936) *Returns*: *this[.](#range.adjacent.iterator-20.sentence-1) [🔗](#lib:operator%5b%5d,adjacent_view::iterator) `constexpr auto operator[](difference_type n) const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [21](#range.adjacent.iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12948) *Effects*: Equivalent to:return *tuple-transform*([&](auto& i) -> decltype(auto) { return i[n]; }, *current_*); [🔗](#lib:operator==,adjacent_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y); ` [22](#range.adjacent.iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12962) *Returns*: x.*current_*.back() == y.*current_*.back()[.](#range.adjacent.iterator-22.sentence-1) [🔗](#lib:operator%3c,adjacent_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [23](#range.adjacent.iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12974) *Returns*: x.*current_*.back() < y.*current_*.back()[.](#range.adjacent.iterator-23.sentence-1) [🔗](#lib:operator%3e,adjacent_view::iterator) `friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [24](#range.adjacent.iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12986) *Effects*: Equivalent to: return y < x; [🔗](#lib:operator%3c=,adjacent_view::iterator) `friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [25](#range.adjacent.iterator-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12998) *Effects*: Equivalent to: return !(y < x); [🔗](#lib:operator%3e=,adjacent_view::iterator) `friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [26](#range.adjacent.iterator-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13010) *Effects*: Equivalent to: return !(x < y); [🔗](#lib:operator%3c=%3e,adjacent_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [27](#range.adjacent.iterator-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13023) *Returns*: x.*current_*.back() <=> y.*current_*.back()[.](#range.adjacent.iterator-27.sentence-1) [🔗](#lib:operator+,adjacent_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [28](#range.adjacent.iterator-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13037) *Effects*: Equivalent to:auto r = i; r += n;return r; [🔗](#lib:operator-,adjacent_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [29](#range.adjacent.iterator-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13054) *Effects*: Equivalent to:auto r = i; r -= n;return r; [🔗](#lib:operator-,adjacent_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [30](#range.adjacent.iterator-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13071) *Effects*: Equivalent to:return x.*current_*.back() - y.*current_*.back(); [🔗](#lib:iter_move,adjacent_view::iterator) `friend constexpr auto iter_move(const iterator& i) noexcept(see below); ` [31](#range.adjacent.iterator-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13083) *Effects*: Equivalent to:return *tuple-transform*(ranges​::​iter_move, i.*current_*); [32](#range.adjacent.iterator-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13088) *Remarks*: The exception specification is equivalent to:noexcept(ranges::iter_move(declval&>())) && is_nothrow_move_constructible_v> [🔗](#lib:iter_swap,adjacent_view::iterator) `friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [33](#range.adjacent.iterator-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13104) *Preconditions*: None of the iterators in l.*current_* is equal to an iterator in r.*current_*[.](#range.adjacent.iterator-33.sentence-1) [34](#range.adjacent.iterator-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13109) *Effects*: For every integer 0≤i>(), declval>())) #### [25.7.27.4](#range.adjacent.sentinel) Class template adjacent_view​::​*sentinel* [[range.adjacent.sentinel]](range.adjacent.sentinel) [🔗](#lib:adjacent_view::sentinel) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && (N > 0)templateclass adjacent_view::*sentinel* {using *Base* = *maybe-const*; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*constexpr explicit *sentinel*(sentinel_t<*Base*> end); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t<*maybe-const*>>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *iterator*& x, const *sentinel*& y); templaterequires [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*>>friend constexpr range_difference_t<*maybe-const*>operator-(const *sentinel*& y, const *iterator*& x); };} [🔗](#lib:adjacent_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end); ` [1](#range.adjacent.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13164) *Effects*: Initializes *end_* with end[.](#range.adjacent.sentinel-1.sentence-1) [🔗](#lib:adjacent_view::sentinel,constructor_) `constexpr sentinel(sentinel i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [2](#range.adjacent.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13176) *Effects*: Initializes *end_* with std​::​move(i.*end_*)[.](#range.adjacent.sentinel-2.sentence-1) [🔗](#lib:operator==,adjacent_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), iterator_t>> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.adjacent.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13189) *Effects*: Equivalent to: return x.*current_*.back() == y.*end_*; [🔗](#lib:operator-,adjacent_view::sentinel) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const iterator& x, const sentinel& y); ` [4](#range.adjacent.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13203) *Effects*: Equivalent to: return x.*current_*.back() - y.*end_*; [🔗](#lib:operator-,adjacent_view::sentinel_) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>> friend constexpr range_difference_t> operator-(const sentinel& y, const iterator& x); ` [5](#range.adjacent.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13217) *Effects*: Equivalent to: return y.*end_* - x.*current_*.back(); ### [25.7.28](#range.adjacent.transform) Adjacent transform view [[range.adjacent.transform]](range.adjacent.transform) #### [25.7.28.1](#range.adjacent.transform.overview) Overview [[range.adjacent.transform.overview]](range.adjacent.transform.overview) [1](#range.adjacent.transform.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13226) adjacent_transform_view takes an invocable object and a view and produces a view whose Mth element is the result of applying the invocable object to the Mth through (M+N−1)th elements of the original view[.](#range.adjacent.transform.overview-1.sentence-1) If the original view has fewer than N elements, the resulting view is empty[.](#range.adjacent.transform.overview-1.sentence-2) [2](#range.adjacent.transform.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13234) The name views​::​adjacent_transform denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.adjacent.transform.overview-2.sentence-1) Given subexpressions E and F and a constant expression N: - [(2.1)](#range.adjacent.transform.overview-2.1) If N is equal to 0 anddecltype((E)) models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"),views​::​adjacent_transform(E, F) is expression-equivalent to((void)E, views​::​zip_transform(F)), except that the evaluations of E and F are indeterminately sequenced[.](#range.adjacent.transform.overview-2.1.sentence-1) - [(2.2)](#range.adjacent.transform.overview-2.2) Otherwise, the expression views​::​adjacent_transform(E, F) is expression-equivalent toadjacent_transform_view, decay_t, N>(E, F)[.](#range.adjacent.transform.overview-2.2.sentence-1) [3](#range.adjacent.transform.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13255) [*Example [1](#range.adjacent.transform.overview-example-1)*: vector v = {1, 2, 3, 4}; for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { cout << i << ' '; // prints 2 6 12} — *end example*] #### [25.7.28.2](#range.adjacent.transform.view) Class template adjacent_transform_view [[range.adjacent.transform.view]](range.adjacent.transform.view) [🔗](#lib:adjacent_transform_view) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && (N > 0) && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]"), N)...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]"), N)...>>class adjacent_transform_view : public view_interface> {*movable-box* *fun_*; // *exposition only* adjacent_view *inner_*; // *exposition only*using *InnerView* = adjacent_view; // *exposition only*templateusing *inner-iterator* = iterator_t<*maybe-const*>; // *exposition only*templateusing *inner-sentinel* = sentinel_t<*maybe-const*>; // *exposition only*// [[range.adjacent.transform.iterator]](#range.adjacent.transform.iterator "25.7.28.3 Class template adjacent_­transform_­view​::​iterator"), class template adjacent_transform_view​::​*iterator*template class *iterator*; // *exposition only*// [[range.adjacent.transform.sentinel]](#range.adjacent.transform.sentinel "25.7.28.4 Class template adjacent_­transform_­view​::​sentinel"), class template adjacent_transform_view​::​*sentinel*template class *sentinel*; // *exposition only*public: adjacent_transform_view() = default; constexpr explicit adjacent_transform_view(V base, F fun); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *inner_*.base(); }constexpr V base() && { return std::move(*inner_*).base(); }constexpr auto begin() {return *iterator*(*this, *inner_*.begin()); }constexpr auto begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]"), N)...> {return *iterator*(*this, *inner_*.begin()); }constexpr auto end() {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*InnerView*>) {return *iterator*(*this, *inner_*.end()); } else {return *sentinel*(*inner_*.end()); }}constexpr auto end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]"), N)...> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(*this, *inner_*.end()); } else {return *sentinel*(*inner_*.end()); }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*InnerView*> {return *inner_*.size(); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") {return *inner_*.size(); }constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<*InnerView*> {return *inner_*.reserve_hint(); }constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") {return *inner_*.reserve_hint(); }};} [🔗](#lib:adjacent_transform_view,constructor) `constexpr explicit adjacent_transform_view(V base, F fun); ` [1](#range.adjacent.transform.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13356) *Effects*: Initializes *fun_* with std​::​move(fun) and*inner_* with std​::​move(base)[.](#range.adjacent.transform.view-1.sentence-1) #### [25.7.28.3](#range.adjacent.transform.iterator) Class template adjacent_transform_view​::​*iterator* [[range.adjacent.transform.iterator]](range.adjacent.transform.iterator) [🔗](#lib:adjacent_transform_view::iterator) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && (N > 0) && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]"), N)...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]"), N)...>>templateclass adjacent_transform_view::*iterator* {using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only**Parent** *parent_* = nullptr; // *exposition only**inner-iterator* *inner_*; // *exposition only*constexpr *iterator*(*Parent*& parent, *inner-iterator* inner); // *exposition only*public:using iterator_category = *see below*; using iterator_concept = typename *inner-iterator*::iterator_concept; using value_type = remove_cvref_t&, *REPEAT*(range_reference_t<*Base*>, N)...>>; using difference_type = range_difference_t<*Base*>; *iterator*() = default; constexpr *iterator*(*iterator* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*inner-iterator*, *inner-iterator*>; constexpr decltype(auto) operator*() const noexcept(*see below*); constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr decltype(auto) operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); friend constexpr bool operator<(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<*inner-iterator*>; friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*inner-iterator*, *inner-iterator*>; };} [1](#range.adjacent.transform.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13427) The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") *iterator*​::​iterator_category is defined as follows: - [(1.1)](#range.adjacent.transform.iterator-1.1) If invoke_result_t<*maybe-const*&,*REPEAT*(range_reference_t<*Base*>, N)...> is not a reference,iterator_category denotes input_iterator_tag[.](#range.adjacent.transform.iterator-1.1.sentence-1) - [(1.2)](#range.adjacent.transform.iterator-1.2) Otherwise, let C denote the typeiterator_traits>​::​iterator_category[.](#range.adjacent.transform.iterator-1.2.sentence-1) * [(1.2.1)](#range.adjacent.transform.iterator-1.2.1) If [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") is true,iterator_category denotes random_access_iterator_tag[.](#range.adjacent.transform.iterator-1.2.1.sentence-1) * [(1.2.2)](#range.adjacent.transform.iterator-1.2.2) Otherwise, if [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") is true,iterator_category denotes bidirectional_iterator_tag[.](#range.adjacent.transform.iterator-1.2.2.sentence-1) * [(1.2.3)](#range.adjacent.transform.iterator-1.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[.](#range.adjacent.transform.iterator-1.2.3.sentence-1) * [(1.2.4)](#range.adjacent.transform.iterator-1.2.4) Otherwise, iterator_category denotes input_iterator_tag[.](#range.adjacent.transform.iterator-1.2.4.sentence-1) [🔗](#lib:adjacent_transform_view::iterator,constructor) `constexpr iterator(Parent& parent, inner-iterator inner); ` [2](#range.adjacent.transform.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13465) *Effects*: Initializes *parent_* with addressof(parent) and*inner_* with std​::​move(inner)[.](#range.adjacent.transform.iterator-2.sentence-1) [🔗](#lib:adjacent_transform_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), inner-iterator>; ` [3](#range.adjacent.transform.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13478) *Effects*: Initializes *parent_* with i.*parent_* and*inner_* with std​::​move(i.*inner_*)[.](#range.adjacent.transform.iterator-3.sentence-1) [🔗](#lib:operator*,adjacent_transform_view::iterator) `constexpr decltype(auto) operator*() const noexcept(see below); ` [4](#range.adjacent.transform.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13490) *Effects*: Equivalent to:return apply([&](const auto&... iters) -> decltype(auto) {return invoke(**parent_*->*fun_*, *iters...);}, *inner_*.*current_*); [5](#range.adjacent.transform.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13499) *Remarks*: Let Is be the pack 0, 1, …, (N - 1)[.](#range.adjacent.transform.iterator-5.sentence-1) The exception specification is equivalent to:noexcept(invoke(**parent_*->*fun_*, *std::get(*inner_*.*current_*)...)) [🔗](#lib:operator++,adjacent_transform_view::iterator) `constexpr iterator& operator++(); ` [6](#range.adjacent.transform.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13514) *Effects*: Equivalent to:++*inner_*;return *this; [🔗](#lib:operator++,adjacent_transform_view::iterator_) `constexpr iterator operator++(int); ` [7](#range.adjacent.transform.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13529) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,adjacent_transform_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [8](#range.adjacent.transform.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13545) *Effects*: Equivalent to:--*inner_*;return *this; [🔗](#lib:operator--,adjacent_transform_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [9](#range.adjacent.transform.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13560) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,adjacent_transform_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.adjacent.transform.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13576) *Effects*: Equivalent to:*inner_* += x;return *this; [🔗](#lib:operator-=,adjacent_transform_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.adjacent.transform.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13591) *Effects*: Equivalent to:*inner_* -= x;return *this; [🔗](#lib:operator%5b%5d,adjacent_transform_view::iterator) `constexpr decltype(auto) operator[](difference_type n) const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.adjacent.transform.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13607) *Effects*: Equivalent to:return apply([&](const auto&... iters) -> decltype(auto) {return invoke(**parent_*->*fun_*, iters[n]...);}, *inner_*.*current_*); [🔗](#lib:operator==,adjacent_transform_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [13](#range.adjacent.transform.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13633) Let *op* be the operator[.](#range.adjacent.transform.iterator-13.sentence-1) [14](#range.adjacent.transform.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13636) *Effects*: Equivalent to: return x.*inner_* *op* y.*inner_*; [🔗](#lib:operator+,adjacent_transform_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [15](#range.adjacent.transform.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13650) *Effects*: Equivalent to: return *iterator*(*i.*parent_*, i.*inner_* + n); [🔗](#lib:operator-,adjacent_transform_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [16](#range.adjacent.transform.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13662) *Effects*: Equivalent to: return *iterator*(*i.*parent_*, i.*inner_* - n); [🔗](#lib:operator-,adjacent_transform_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), inner-iterator>; ` [17](#range.adjacent.transform.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13674) *Effects*: Equivalent to: return x.*inner_* - y.*inner_*; #### [25.7.28.4](#range.adjacent.transform.sentinel) Class template adjacent_transform_view​::​*sentinel* [[range.adjacent.transform.sentinel]](range.adjacent.transform.sentinel) [🔗](#lib:adjacent_transform_view::sentinel) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]") F, size_t N>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && (N > 0) && is_object_v &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]"), N)...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header  synopsis [iterator.synopsis]"), N)...>>templateclass adjacent_transform_view::*sentinel* {*inner-sentinel* *inner_*; // *exposition only*constexpr explicit *sentinel*(*inner-sentinel* inner); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel* i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*inner-sentinel*, *inner-sentinel*>; templaterequires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<*inner-sentinel*, *inner-iterator*>friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); templaterequires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*inner-sentinel*, *inner-iterator*>friend constexpr range_difference_t<*maybe-const*>operator-(const *iterator*& x, const *sentinel*& y); templaterequires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*inner-sentinel*, *inner-iterator*>friend constexpr range_difference_t<*maybe-const*>operator-(const *sentinel*& x, const *iterator*& y); };} [🔗](#lib:adjacent_transform_view::sentinel,constructor) `constexpr explicit sentinel(inner-sentinel inner); ` [1](#range.adjacent.transform.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13721) *Effects*: Initializes *inner_* with inner[.](#range.adjacent.transform.sentinel-1.sentence-1) [🔗](#lib:adjacent_transform_view::sentinel,constructor_) `constexpr sentinel(sentinel i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), inner-sentinel>; ` [2](#range.adjacent.transform.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13733) *Effects*: Initializes *inner_* with std​::​move(i.*inner_*)[.](#range.adjacent.transform.sentinel-2.sentence-1) [🔗](#lib:operator==,adjacent_transform_view::sentinel) `template requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]"), inner-iterator> friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.adjacent.transform.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13746) *Effects*: Equivalent to: return x.*inner_* == y.*inner_*; [🔗](#lib:operator-,adjacent_transform_view::sentinel) `template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), inner-iterator> friend constexpr range_difference_t> operator-(const iterator& x, const sentinel& y); template requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), inner-iterator> friend constexpr range_difference_t> operator-(const sentinel& x, const iterator& y); ` [4](#range.adjacent.transform.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13765) *Effects*: Equivalent to: return x.*inner_* - y.*inner_*; ### [25.7.29](#range.chunk) Chunk view [[range.chunk]](range.chunk) #### [25.7.29.1](#range.chunk.overview) Overview [[range.chunk.overview]](range.chunk.overview) [1](#range.chunk.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13774) chunk_view takes a view and a number N and produces a range of views that are N-sized non-overlapping successive chunks of the elements of the original view, in order[.](#range.chunk.overview-1.sentence-1) The last view in the range can have fewer than N elements[.](#range.chunk.overview-1.sentence-2) [2](#range.chunk.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13781) The name views​::​chunk denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.chunk.overview-2.sentence-1) Given subexpressions E and N, the expression views​::​chunk(E, N) is expression-equivalent tochunk_view(E, N)[.](#range.chunk.overview-2.sentence-2) [*Example [1](#range.chunk.overview-example-1)*: vector v = {1, 2, 3, 4, 5}; for (auto r : v | views::chunk(2)) { cout << '['; auto sep = ""; for (auto i : r) { cout << sep << i; sep = ", "; } cout << "] ";}// The above prints [1, 2] [3, 4] [5] — *end example*] #### [25.7.29.2](#range.chunk.view.input) Class template chunk_view for input ranges [[range.chunk.view.input]](range.chunk.view.input) [🔗](#lib:chunk_view) namespace std::ranges {templateconstexpr I *div-ceil*(I num, I denom) { // *exposition only* I r = num / denom; if (num % denom)++r; return r; }template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")class chunk_view : public view_interface> { V *base_*; // *exposition only* range_difference_t *n_*; // *exposition only* range_difference_t *remainder_* = 0; // *exposition only**non-propagating-cache*> *current_*; // *exposition only*// [[range.chunk.outer.iter]](#range.chunk.outer.iter "25.7.29.3 Class chunk_­view​::​outer-iterator"), class chunk_view​::​*outer-iterator*class *outer-iterator*; // *exposition only*// [[range.chunk.inner.iter]](#range.chunk.inner.iter "25.7.29.5 Class chunk_­view​::​inner-iterator"), class chunk_view​::​*inner-iterator*class *inner-iterator*; // *exposition only*public:constexpr explicit chunk_view(V base, range_difference_t n); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr *outer-iterator* begin(); constexpr default_sentinel_t end() const noexcept; 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]"); constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); }; template chunk_view(R&&, range_difference_t) -> chunk_view>;} [🔗](#lib:chunk_view,constructor) `constexpr explicit chunk_view(V base, range_difference_t n); ` [1](#range.chunk.view.input-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13861) *Preconditions*: n > 0 is true[.](#range.chunk.view.input-1.sentence-1) [2](#range.chunk.view.input-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13865) *Effects*: Initializes *base_* with std​::​move(base) and*n_* with n[.](#range.chunk.view.input-2.sentence-1) [🔗](#lib:begin,chunk_view) `constexpr outer-iterator begin(); ` [3](#range.chunk.view.input-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13877) *Effects*: Equivalent to:*current_* = ranges::begin(*base_*);*remainder_* = *n_*;return *outer-iterator*(*this); [🔗](#lib:end,chunk_view) `constexpr default_sentinel_t end() const noexcept; ` [4](#range.chunk.view.input-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13893) *Returns*: default_sentinel[.](#range.chunk.view.input-4.sentence-1) [🔗](#lib:size,chunk_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]"); ` [5](#range.chunk.view.input-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13905) *Effects*: Equivalent to:return *to-unsigned-like*(*div-ceil*(ranges::distance(*base_*), *n_*)); [🔗](#lib:reserve_hint,chunk_view) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [6](#range.chunk.view.input-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13920) *Effects*: Equivalent to:auto s = static_cast>(ranges::reserve_hint(*base_*));return *to-unsigned-like*(*div-ceil*(s, *n_*)); #### [25.7.29.3](#range.chunk.outer.iter) Class chunk_view​::​*outer-iterator* [[range.chunk.outer.iter]](range.chunk.outer.iter) [🔗](#lib:chunk_view::outer-iterator) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")class chunk_view::*outer-iterator* { chunk_view* *parent_*; // *exposition only*constexpr explicit *outer-iterator*(chunk_view& parent); // *exposition only*public:using iterator_concept = input_iterator_tag; using difference_type = range_difference_t; // [[range.chunk.outer.value]](#range.chunk.outer.value "25.7.29.4 Class chunk_­view​::​outer-iterator​::​value_­type"), class chunk_view​::​*outer-iterator*​::​value_typestruct value_type; *outer-iterator*(*outer-iterator*&&) = default; *outer-iterator*& operator=(*outer-iterator*&&) = default; constexpr value_type operator*() const; constexpr *outer-iterator*& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const *outer-iterator*& x, default_sentinel_t); friend constexpr difference_type operator-(default_sentinel_t y, const *outer-iterator*& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; friend constexpr difference_type operator-(const *outer-iterator*& x, default_sentinel_t y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; };} [🔗](#lib:chunk_view::outer-iterator,constructor) `constexpr explicit outer-iterator(chunk_view& parent); ` [1](#range.chunk.outer.iter-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13971) *Effects*: Initializes *parent_* with addressof(parent)[.](#range.chunk.outer.iter-1.sentence-1) [🔗](#lib:operator*,chunk_view::outer-iterator) `constexpr value_type operator*() const; ` [2](#range.chunk.outer.iter-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13982) *Preconditions*: *this == default_sentinel is false[.](#range.chunk.outer.iter-2.sentence-1) [3](#range.chunk.outer.iter-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13986) *Returns*: value_type(**parent_*)[.](#range.chunk.outer.iter-3.sentence-1) [🔗](#lib:operator++,chunk_view::outer-iterator) `constexpr outer-iterator& operator++(); ` [4](#range.chunk.outer.iter-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13997) *Preconditions*: *this == default_sentinel is false[.](#range.chunk.outer.iter-4.sentence-1) [5](#range.chunk.outer.iter-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14001) *Effects*: Equivalent to:ranges::advance(**parent_*->*current_*, *parent_*->*remainder_*, ranges::end(*parent_*->*base_*));*parent_*->*remainder_* = *parent_*->*n_*;return *this; [🔗](#lib:operator++,chunk_view::outer-iterator_) `constexpr void operator++(int); ` [6](#range.chunk.outer.iter-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14017) *Effects*: Equivalent to ++*this[.](#range.chunk.outer.iter-6.sentence-1) [🔗](#lib:operator==,chunk_view::outer-iterator) `friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t); ` [7](#range.chunk.outer.iter-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14028) *Effects*: Equivalent to:return *x.*parent_*->*current_* == ranges::end(x.*parent_*->*base_*) && x.*parent_*->*remainder_* != 0; [🔗](#lib:operator-,chunk_view::outer-iterator) `friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [8](#range.chunk.outer.iter-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14043) *Effects*: Equivalent to:const auto dist = ranges::end(x.*parent_*->*base_*) - *x.*parent_*->*current_*;if (dist < x.*parent_*->*remainder_*) {return dist == 0 ? 0 : 1;}return *div-ceil*(dist - x.*parent_*->*remainder_*, x.*parent_*->*n_*) + 1; [🔗](#lib:operator-,chunk_view::outer-iterator_) `friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [9](#range.chunk.outer.iter-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14062) *Effects*: Equivalent to: return -(y - x); #### [25.7.29.4](#range.chunk.outer.value) Class chunk_view​::​*outer-iterator*​::​value_type [[range.chunk.outer.value]](range.chunk.outer.value) [🔗](#lib:chunk_view::outer-iterator::value_type) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")struct chunk_view::*outer-iterator*::value_type : view_interface {private: chunk_view* *parent_*; // *exposition only*constexpr explicit value_type(chunk_view& parent); // *exposition only*public:constexpr *inner-iterator* begin() const noexcept; constexpr default_sentinel_t end() const noexcept; constexpr auto size() constrequires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; constexpr auto reserve_hint() const noexcept; };} [🔗](#lib:chunk_view::outer-iterator::value_type,constructor) `constexpr explicit value_type(chunk_view& parent); ` [1](#range.chunk.outer.value-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14098) *Effects*: Initializes *parent_* with addressof(parent)[.](#range.chunk.outer.value-1.sentence-1) [🔗](#lib:begin,chunk_view::outer-iterator::value_type) `constexpr inner-iterator begin() const noexcept; ` [2](#range.chunk.outer.value-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14109) *Returns*: *inner-iterator*(**parent_*)[.](#range.chunk.outer.value-2.sentence-1) [🔗](#lib:end,chunk_view::outer-iterator::value_type) `constexpr default_sentinel_t end() const noexcept; ` [3](#range.chunk.outer.value-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14120) *Returns*: default_sentinel[.](#range.chunk.outer.value-3.sentence-1) [🔗](#lib:size,chunk_view::outer-iterator::value_type) `constexpr auto size() const requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [4](#range.chunk.outer.value-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14132) *Effects*: Equivalent to:return *to-unsigned-like*(ranges::min(*parent_*->*remainder_*, ranges::end(*parent_*->*base_*) - **parent_*->*current_*)); [🔗](#lib:reserve_hint,chunk_view::outer-iterator::value_type) `constexpr auto reserve_hint() const noexcept; ` [5](#range.chunk.outer.value-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14147) *Effects*: Equivalent to:return *to-unsigned-like*(*parent_*->*remainder_*); #### [25.7.29.5](#range.chunk.inner.iter) Class chunk_view​::​*inner-iterator* [[range.chunk.inner.iter]](range.chunk.inner.iter) [🔗](#lib:chunk_view::inner-iterator) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")class chunk_view::*inner-iterator* { chunk_view* *parent_*; // *exposition only*constexpr explicit *inner-iterator*(chunk_view& parent) noexcept; // *exposition only*public:using iterator_concept = input_iterator_tag; using difference_type = range_difference_t; using value_type = range_value_t; *inner-iterator*(*inner-iterator*&&) = default; *inner-iterator*& operator=(*inner-iterator*&&) = default; constexpr const iterator_t& base() const &; constexpr range_reference_t operator*() const; constexpr *inner-iterator*& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const *inner-iterator*& x, default_sentinel_t); friend constexpr difference_type operator-(default_sentinel_t y, const *inner-iterator*& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; friend constexpr difference_type operator-(const *inner-iterator*& x, default_sentinel_t y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; friend constexpr range_rvalue_reference_t iter_move(const *inner-iterator*& i)noexcept(noexcept(ranges::iter_move(*i.*parent_*->*current_*))); friend constexpr void iter_swap(const *inner-iterator*& x, const *inner-iterator*& y)noexcept(noexcept(ranges::iter_swap(*x.*parent_*->*current_*, *y.*parent_*->*current_*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [🔗](#lib:chunk_view::inner-iterator,constructor) `constexpr explicit inner-iterator(chunk_view& parent) noexcept; ` [1](#range.chunk.inner.iter-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14204) *Effects*: Initializes *parent_* with addressof(parent)[.](#range.chunk.inner.iter-1.sentence-1) [🔗](#lib:base,chunk_view::inner-iterator) `constexpr const iterator_t& base() const &; ` [2](#range.chunk.inner.iter-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14215) *Effects*: Equivalent to: return **parent_*->*current_*; [🔗](#lib:operator*,chunk_view::inner-iterator) `constexpr range_reference_t operator*() const; ` [3](#range.chunk.inner.iter-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14226) *Preconditions*: *this == default_sentinel is false[.](#range.chunk.inner.iter-3.sentence-1) [4](#range.chunk.inner.iter-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14230) *Effects*: Equivalent to: return ***parent_*->*current_*; [🔗](#lib:operator++,chunk_view::inner-iterator) `constexpr inner-iterator& operator++(); ` [5](#range.chunk.inner.iter-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14241) *Preconditions*: *this == default_sentinel is false[.](#range.chunk.inner.iter-5.sentence-1) [6](#range.chunk.inner.iter-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14245) *Effects*: Equivalent to:++**parent_*->*current_*;if (**parent_*->*current_* == ranges::end(*parent_*->*base_*))*parent_*->*remainder_* = 0;else--*parent_*->*remainder_*;return *this; [🔗](#lib:operator++,chunk_view::inner-iterator_) `constexpr void operator++(int); ` [7](#range.chunk.inner.iter-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14264) *Effects*: Equivalent to ++*this[.](#range.chunk.inner.iter-7.sentence-1) [🔗](#lib:operator==,chunk_view::inner-iterator) `friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t); ` [8](#range.chunk.inner.iter-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14275) *Returns*: x.*parent_*->*remainder_* == 0[.](#range.chunk.inner.iter-8.sentence-1) [🔗](#lib:operator-,chunk_view::inner-iterator) `friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [9](#range.chunk.inner.iter-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14287) *Effects*: Equivalent to:return ranges::min(x.*parent_*->*remainder_*, ranges::end(x.*parent_*->*base_*) - *x.*parent_*->*current_*); [🔗](#lib:operator-,chunk_view::inner-iterator_) `friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [10](#range.chunk.inner.iter-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14303) *Effects*: Equivalent to: return -(y - x); [🔗](#lib:iter_move,chunk_view::inner-iterator) `friend constexpr range_rvalue_reference_t iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(*i.parent_->current_))); ` [11](#range.chunk.inner.iter-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14315) *Effects*: Equivalent to: return ranges​::​iter_move(*i.*parent_*->*current_*); [🔗](#lib:iter_swap,chunk_view::inner-iterator) `friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [12](#range.chunk.inner.iter-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14328) *Effects*: Equivalent to: ranges​::​iter_swap(*x.*parent_*->*current_*, *y.*parent_*->*current_*); #### [25.7.29.6](#range.chunk.view.fwd) Class template chunk_view for forward ranges [[range.chunk.view.fwd]](range.chunk.view.fwd) [🔗](#lib:chunk_view_) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")class chunk_view : public view_interface> { V *base_*; // *exposition only* range_difference_t *n_*; // *exposition only*// [[range.chunk.fwd.iter]](#range.chunk.fwd.iter "25.7.29.7 Class template chunk_­view​::​iterator for forward ranges"), class template chunk_view​::​*iterator*template class *iterator*; // *exposition only*public:constexpr explicit chunk_view(V base, range_difference_t n); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {return *iterator*(this, ranges::begin(*base_*)); }constexpr auto begin() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") {return *iterator*(this, ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")) {auto missing = (*n_* - ranges::distance(*base_*) % *n_*) % *n_*; return *iterator*(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(this, ranges::end(*base_*)); } else {return default_sentinel; }}constexpr auto end() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")) {auto missing = (*n_* - ranges::distance(*base_*) % *n_*) % *n_*; return *iterator*(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(this, ranges::end(*base_*)); } else {return default_sentinel; }}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]"); constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); };} [🔗](#lib:chunk_view,constructor_) `constexpr explicit chunk_view(V base, range_difference_t n); ` [1](#range.chunk.view.fwd-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14400) *Preconditions*: n > 0 is true[.](#range.chunk.view.fwd-1.sentence-1) [2](#range.chunk.view.fwd-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14404) *Effects*: Initializes *base_* with std​::​move(base) and*n_* with n[.](#range.chunk.view.fwd-2.sentence-1) [🔗](#lib:size,chunk_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]"); ` [3](#range.chunk.view.fwd-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14417) *Effects*: Equivalent to:return *to-unsigned-like*(*div-ceil*(ranges::distance(*base_*), *n_*)); [🔗](#lib:reserve_hint,chunk_view_) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [4](#range.chunk.view.fwd-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14432) *Effects*: Equivalent to:auto s = static_cast>(ranges::reserve_hint(*base_*));return *to-unsigned-like*(*div-ceil*(s, *n_*)); #### [25.7.29.7](#range.chunk.fwd.iter) Class template chunk_view​::​*iterator* for forward ranges [[range.chunk.fwd.iter]](range.chunk.fwd.iter) [🔗](#lib:chunk_view::iterator) namespace std::ranges {template<[view](range.view#concept:view "25.4.5 Views [range.view]") V>requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")templateclass chunk_view::*iterator* {using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only* range_difference_t<*Base*> *n_* = 0; // *exposition only* range_difference_t<*Base*> *missing_* = 0; // *exposition only*constexpr *iterator*(*Parent** parent, iterator_t<*Base*> current, // *exposition only* range_difference_t<*Base*> missing = 0); public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = decltype(views::take(subrange(*current_*, *end_*), *n_*)); using difference_type = range_difference_t<*Base*>; *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<*Base*>>&& [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr iterator_t<*Base*> base() const; constexpr value_type operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr value_type operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); friend constexpr bool operator==(const *iterator*& x, default_sentinel_t); friend constexpr bool operator<(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr difference_type operator-(default_sentinel_t y, const *iterator*& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr difference_type operator-(const *iterator*& x, default_sentinel_t y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; };} [1](#range.chunk.fwd.iter-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14521) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.chunk.fwd.iter-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes random_access_iterator_tag[.](#range.chunk.fwd.iter-1.1.sentence-1) - [(1.2)](#range.chunk.fwd.iter-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.chunk.fwd.iter-1.2.sentence-1) - [(1.3)](#range.chunk.fwd.iter-1.3) Otherwise, iterator_concept denotes forward_iterator_tag[.](#range.chunk.fwd.iter-1.3.sentence-1) [🔗](#lib:chunk_view::iterator,constructor) `constexpr iterator(Parent* parent, iterator_t current, range_difference_t missing = 0); ` [2](#range.chunk.fwd.iter-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14541) *Effects*: Initializes *current_* with current,*end_* with ranges​::​end(parent->*base_*),*n_* with parent->*n_*, and*missing_* with missing[.](#range.chunk.fwd.iter-2.sentence-1) [🔗](#lib:chunk_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [3](#range.chunk.fwd.iter-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14557) *Effects*: Initializes *current_* with std​::​move(i.*current_*),*end_* with std​::​move(i.*end_*),*n_* with i.*n_*, and*missing_* with i.*missing_*[.](#range.chunk.fwd.iter-3.sentence-1) [🔗](#lib:base,chunk_view::iterator) `constexpr iterator_t base() const; ` [4](#range.chunk.fwd.iter-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14571) *Returns*: *current_*[.](#range.chunk.fwd.iter-4.sentence-1) [🔗](#lib:operator*,chunk_view::iterator) `constexpr value_type operator*() const; ` [5](#range.chunk.fwd.iter-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14582) *Preconditions*: *current_* != *end_* is true[.](#range.chunk.fwd.iter-5.sentence-1) [6](#range.chunk.fwd.iter-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14586) *Returns*: views​::​take(subrange(*current_*, *end_*), *n_*)[.](#range.chunk.fwd.iter-6.sentence-1) [🔗](#lib:operator++,chunk_view::iterator) `constexpr iterator& operator++(); ` [7](#range.chunk.fwd.iter-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14597) *Preconditions*: *current_* != *end_* is true[.](#range.chunk.fwd.iter-7.sentence-1) [8](#range.chunk.fwd.iter-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14601) *Effects*: Equivalent to:*missing_* = ranges::advance(*current_*, *n_*, *end_*);return *this; [🔗](#lib:operator++,chunk_view::iterator_) `constexpr iterator operator++(int); ` [9](#range.chunk.fwd.iter-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14616) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,chunk_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.chunk.fwd.iter-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14632) *Effects*: Equivalent to:ranges::advance(*current_*, *missing_* - *n_*);*missing_* = 0;return *this; [🔗](#lib:operator--,chunk_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.chunk.fwd.iter-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14648) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,chunk_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.chunk.fwd.iter-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14665) *Preconditions*: If x is positive,ranges​::​distance(*current_*, *end_*) > *n_* * (x - 1) is true[.](#range.chunk.fwd.iter-12.sentence-1) [*Note [1](#range.chunk.fwd.iter-note-1)*: If x is negative, the *Effects* paragraph implies a precondition[.](#range.chunk.fwd.iter-12.sentence-2) — *end note*] [13](#range.chunk.fwd.iter-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14674) *Effects*: Equivalent to:if (x > 0) { ranges::advance(*current_*, *n_* * (x - 1)); *missing_* = ranges::advance(*current_*, *n_*, *end_*);} else if (x < 0) { ranges::advance(*current_*, *n_* * x + *missing_*); *missing_* = 0;}return *this; [🔗](#lib:operator-=,chunk_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [14](#range.chunk.fwd.iter-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14696) *Effects*: Equivalent to: return *this += -x; [🔗](#lib:operator%5b%5d,chunk_view::iterator) `constexpr value_type operator[](difference_type n) const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [15](#range.chunk.fwd.iter-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14708) *Returns*: *(*this + n)[.](#range.chunk.fwd.iter-15.sentence-1) [🔗](#lib:operator-=,chunk_view::iterator_) `friend constexpr bool operator==(const iterator& x, const iterator& y); ` [16](#range.chunk.fwd.iter-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14719) *Returns*: x.*current_* == y.*current_*[.](#range.chunk.fwd.iter-16.sentence-1) [🔗](#lib:operator==,chunk_view::iterator) `friend constexpr bool operator==(const iterator& x, default_sentinel_t); ` [17](#range.chunk.fwd.iter-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14730) *Returns*: x.*current_* == x.*end_*[.](#range.chunk.fwd.iter-17.sentence-1) [🔗](#lib:operator%3c,chunk_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.chunk.fwd.iter-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14742) *Returns*: x.*current_* < y.*current_*[.](#range.chunk.fwd.iter-18.sentence-1) [🔗](#lib:operator%3e,chunk_view::iterator) `friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [19](#range.chunk.fwd.iter-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14754) *Effects*: Equivalent to: return y < x; [🔗](#lib:operator%3c=,chunk_view::iterator) `friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [20](#range.chunk.fwd.iter-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14766) *Effects*: Equivalent to: return !(y < x); [🔗](#lib:operator%3e=,chunk_view::iterator) `friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [21](#range.chunk.fwd.iter-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14778) *Effects*: Equivalent to: return !(x < y); [🔗](#lib:operator%3c=%3e,chunk_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [22](#range.chunk.fwd.iter-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14791) *Returns*: x.*current_* <=> y.*current_*[.](#range.chunk.fwd.iter-22.sentence-1) [🔗](#lib:operator+,chunk_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [23](#range.chunk.fwd.iter-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14805) *Effects*: Equivalent to:auto r = i; r += n;return r; [🔗](#lib:operator-,chunk_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [24](#range.chunk.fwd.iter-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14822) *Effects*: Equivalent to:auto r = i; r -= n;return r; [🔗](#lib:operator-,chunk_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [25](#range.chunk.fwd.iter-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14839) *Returns*: (x.*current_* - y.*current_* + x.*missing_* - y.*missing_*) / x.*n_*[.](#range.chunk.fwd.iter-25.sentence-1) [🔗](#lib:operator-,chunk_view::iterator__) `friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [26](#range.chunk.fwd.iter-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14851) *Returns*: *div-ceil*(x.*end_* - x.*current_*, x.*n_*)[.](#range.chunk.fwd.iter-26.sentence-1) [🔗](#lib:operator-,chunk_view::iterator___) `friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [27](#range.chunk.fwd.iter-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14863) *Effects*: Equivalent to: return -(y - x); ### [25.7.30](#range.slide) Slide view [[range.slide]](range.slide) #### [25.7.30.1](#range.slide.overview) Overview [[range.slide.overview]](range.slide.overview) [1](#range.slide.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14872) slide_view takes a view and a number N and produces a view whose Mth element is a view over the Mth through(M+N−1)th elements of the original view[.](#range.slide.overview-1.sentence-1) If the original view has fewer than N elements, the resulting view is empty[.](#range.slide.overview-1.sentence-2) [2](#range.slide.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14882) The name views​::​slide denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.slide.overview-2.sentence-1) Given subexpressions E and N, the expression views​::​slide(E, N) is expression-equivalent toslide_view(E, N)[.](#range.slide.overview-2.sentence-2) [*Example [1](#range.slide.overview-example-1)*: vector v = {1, 2, 3, 4}; for (auto i : v | views::slide(2)) { cout << '[' << i[0] << ", " << i[1] << "] "; // prints [1, 2] [2, 3] [3, 4]} — *end example*] #### [25.7.30.2](#range.slide.view) Class template slide_view [[range.slide.view]](range.slide.view) [🔗](#lib:slide_view) namespace std::ranges {templateconcept [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]") = [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"); // *exposition only*templateconcept [*slide-caches-last*](#concept:slide-caches-last "25.7.30.2 Class template slide_­view [range.slide.view]") = // *exposition only*![*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]") && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); templateconcept [*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]") = // *exposition only*![*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]") && ![*slide-caches-last*](#concept:slide-caches-last "25.7.30.2 Class template slide_­view [range.slide.view]"); template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class slide_view : public view_interface> { V *base_*; // *exposition only* range_difference_t *n_*; // *exposition only*// [[range.slide.iterator]](#range.slide.iterator "25.7.30.3 Class template slide_­view​::​iterator"), class template slide_view​::​*iterator*template class *iterator*; // *exposition only*// [[range.slide.sentinel]](#range.slide.sentinel "25.7.30.4 Class slide_­view​::​sentinel"), class slide_view​::​*sentinel*class *sentinel*; // *exposition only*public:constexpr explicit slide_view(V base, range_difference_t n); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin()requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"))); constexpr auto begin() const requires [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"); constexpr auto end()requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"))); constexpr auto end() const requires [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.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]"); constexpr auto reserve_hintsize() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hintsize() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); }; template slide_view(R&&, range_difference_t) -> slide_view>;} [🔗](#lib:slide_view,constructor_) `constexpr explicit slide_view(V base, range_difference_t n); ` [1](#range.slide.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14960) *Preconditions*: n > 0 is true[.](#range.slide.view-1.sentence-1) [2](#range.slide.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14964) *Effects*: Initializes *base_* with std​::​move(base) and*n_* with n[.](#range.slide.view-2.sentence-1) [🔗](#lib:begin,slide_view) `constexpr auto begin() requires (!([simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [slide-caches-nothing](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"))); ` [3](#range.slide.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14977) *Returns*: - [(3.1)](#range.slide.view-3.1) If V models [*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]"),*iterator*(ranges::begin(*base_*), ranges::next(ranges::begin(*base_*), *n_* - 1, ranges::end(*base_*)), *n_*) - [(3.2)](#range.slide.view-3.2) Otherwise, *iterator*(ranges​::​begin(*base_*), *n_*)[.](#range.slide.view-3.sentence-1) [4](#range.slide.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14990) *Remarks*: In order to provide the amortized constant-time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept, this function caches the result within the slide_view for use on subsequent calls when V models [*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]")[.](#range.slide.view-4.sentence-1) [🔗](#lib:begin,slide_view_) `constexpr auto begin() const requires [slide-caches-nothing](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"); ` [5](#range.slide.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15005) *Returns*: *iterator*(ranges​::​begin(*base_*), *n_*)[.](#range.slide.view-5.sentence-1) [🔗](#lib:end,slide_view) `constexpr auto end() requires (!([simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") && [slide-caches-nothing](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"))); ` [6](#range.slide.view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15017) *Returns*: - [(6.1)](#range.slide.view-6.1) If V models [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"),*iterator*(ranges::begin(*base_*) + range_difference_t(size()), *n_*) - [(6.2)](#range.slide.view-6.2) Otherwise, if V models [*slide-caches-last*](#concept:slide-caches-last "25.7.30.2 Class template slide_­view [range.slide.view]"),*iterator*(ranges::prev(ranges::end(*base_*), *n_* - 1, ranges::begin(*base_*)), *n_*) - [(6.3)](#range.slide.view-6.3) Otherwise, if V models [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"),*iterator*(ranges::end(*base_*), ranges::end(*base_*), *n_*) - [(6.4)](#range.slide.view-6.4) Otherwise, *sentinel*(ranges​::​end(*base_*))[.](#range.slide.view-6.sentence-1) [7](#range.slide.view-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15039) *Remarks*: In order to provide the amortized constant-time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept, this function caches the result within the slide_view for use on subsequent calls when V models [*slide-caches-last*](#concept:slide-caches-last "25.7.30.2 Class template slide_­view [range.slide.view]")[.](#range.slide.view-7.sentence-1) [🔗](#lib:end,slide_view_) `constexpr auto end() const requires [slide-caches-nothing](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"); ` [8](#range.slide.view-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15054) *Returns*: begin() + range_difference_t(size())[.](#range.slide.view-8.sentence-1) [🔗](#lib:size,slide_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]"); ` [9](#range.slide.view-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15066) *Effects*: Equivalent to:auto sz = ranges::distance(*base_*) - *n_* + 1;if (sz < 0) sz = 0;return *to-unsigned-like*(sz); [🔗](#lib:reserve_hint,slide_view) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [10](#range.slide.view-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15083) *Effects*: Equivalent to:auto sz = static_cast>(ranges::reserve_hint(*base_*)) -*n_* + 1;if (sz < 0) sz = 0;return *to-unsigned-like*(sz); #### [25.7.30.3](#range.slide.iterator) Class template slide_view​::​*iterator* [[range.slide.iterator]](range.slide.iterator) [🔗](#lib:slide_view::iterator) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")templateclass slide_view::*iterator* {using *Base* = *maybe-const*; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only* iterator_t<*Base*> *last_ele_* = iterator_t<*Base*>(); // *exposition only*,// present only if *Base* models [*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]") range_difference_t<*Base*> *n_* = 0; // *exposition only*constexpr *iterator*(iterator_t<*Base*> current, range_difference_t<*Base*> n) // *exposition only*requires (![*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]")<*Base*>); constexpr *iterator*(iterator_t<*Base*> current, iterator_t<*Base*> last_ele, // *exposition only* range_difference_t<*Base*> n)requires [*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]")<*Base*>; public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = decltype(views::counted(*current_*, *n_*)); using difference_type = range_difference_t<*Base*>; *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<*Base*>>; constexpr auto operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr auto operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); friend constexpr bool operator<(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; };} [1](#range.slide.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15167) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.slide.iterator-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes random_access_iterator_tag[.](#range.slide.iterator-1.1.sentence-1) - [(1.2)](#range.slide.iterator-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.slide.iterator-1.2.sentence-1) - [(1.3)](#range.slide.iterator-1.3) Otherwise, iterator_concept denotes forward_iterator_tag[.](#range.slide.iterator-1.3.sentence-1) [2](#range.slide.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15180) If the invocation of any non-const member function of *iterator* exits via an exception, the *iterator* acquires a singular value[.](#range.slide.iterator-2.sentence-1) [🔗](#lib:slide_view::iterator,constructor) `constexpr iterator(iterator_t current, range_difference_t n) requires (![slide-caches-first](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]")); ` [3](#range.slide.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15191) *Effects*: Initializes *current_* with current and*n_* with n[.](#range.slide.iterator-3.sentence-1) [🔗](#lib:slide_view::iterator,constructor_) `constexpr iterator(iterator_t current, iterator_t last_ele, range_difference_t n) requires [slide-caches-first](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]"); ` [4](#range.slide.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15205) *Effects*: Initializes *current_* with current,*last_ele_* with last_ele, and*n_* with n[.](#range.slide.iterator-4.sentence-1) [🔗](#lib:slide_view::iterator,constructor__) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [5](#range.slide.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15219) *Effects*: Initializes *current_* with std​::​move(i.*current_*) and*n_* with i.*n_*[.](#range.slide.iterator-5.sentence-1) [*Note [1](#range.slide.iterator-note-1)*: *iterator* can only be formed when *Base* models [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]"), in which case *last_ele_* is not present[.](#range.slide.iterator-5.sentence-2) — *end note*] [🔗](#lib:operator*,slide_view::iterator) `constexpr auto operator*() const; ` [6](#range.slide.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15236) *Returns*: views​::​counted(*current_*, *n_*)[.](#range.slide.iterator-6.sentence-1) [🔗](#lib:operator++,slide_view::iterator) `constexpr iterator& operator++(); ` [7](#range.slide.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15247) *Preconditions*: *current_* and *last_ele_* (if present) are incrementable[.](#range.slide.iterator-7.sentence-1) [8](#range.slide.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15251) *Postconditions*: *current_* and *last_ele_* (if present) are each equal to ranges​::​next(i), where i is the value of that data member before the call[.](#range.slide.iterator-8.sentence-1) [9](#range.slide.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15257) *Returns*: *this[.](#range.slide.iterator-9.sentence-1) [🔗](#lib:operator++,slide_view::iterator_) `constexpr iterator operator++(int); ` [10](#range.slide.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15268) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,slide_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.slide.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15284) *Preconditions*: *current_* and *last_ele_* (if present) are decrementable[.](#range.slide.iterator-11.sentence-1) [12](#range.slide.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15288) *Postconditions*: *current_* and *last_ele_* (if present) are each equal to ranges​::​prev(i), where i is the value of that data member before the call[.](#range.slide.iterator-12.sentence-1) [13](#range.slide.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15294) *Returns*: *this[.](#range.slide.iterator-13.sentence-1) [🔗](#lib:operator--,slide_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [14](#range.slide.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15305) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,slide_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [15](#range.slide.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15322) *Preconditions*: *current_* + x and *last_ele_* + x (if *last_ele_* is present) have well-defined behavior[.](#range.slide.iterator-15.sentence-1) [16](#range.slide.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15327) *Postconditions*: *current_* and *last_ele_* (if present) are each equal to i + x, where i is the value of that data member before the call[.](#range.slide.iterator-16.sentence-1) [17](#range.slide.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15333) *Returns*: *this[.](#range.slide.iterator-17.sentence-1) [🔗](#lib:operator-=,slide_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.slide.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15345) *Preconditions*: *current_* - x and *last_ele_* - x (if *last_ele_* is present) have well-defined behavior[.](#range.slide.iterator-18.sentence-1) [19](#range.slide.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15350) *Postconditions*: *current_* and *last_ele_* (if present) are each equal to i - x, where i is the value of that data member before the call[.](#range.slide.iterator-19.sentence-1) [20](#range.slide.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15356) *Returns*: *this[.](#range.slide.iterator-20.sentence-1) [🔗](#lib:operator%5b%5d,slide_view::iterator) `constexpr auto operator[](difference_type n) const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [21](#range.slide.iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15368) *Effects*: Equivalent to: return views​::​counted(*current_* + n, *n_*); [🔗](#lib:operator==,slide_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y); ` [22](#range.slide.iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15379) *Returns*: If *last_ele_* is present,x.*last_ele_* == y.*last_ele_*; otherwise, x.*current_* == y.*current_*[.](#range.slide.iterator-22.sentence-1) [🔗](#lib:operator%3c,slide_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [23](#range.slide.iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15393) *Returns*: x.*current_* < y.*current_*[.](#range.slide.iterator-23.sentence-1) [🔗](#lib:operator%3e,slide_view::iterator) `friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [24](#range.slide.iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15405) *Effects*: Equivalent to: return y < x; [🔗](#lib:operator%3c=,slide_view::iterator) `friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [25](#range.slide.iterator-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15417) *Effects*: Equivalent to: return !(y < x); [🔗](#lib:operator%3e=,slide_view::iterator) `friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [26](#range.slide.iterator-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15429) *Effects*: Equivalent to: return !(x < y); [🔗](#lib:operator%3c=%3e,slide_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [27](#range.slide.iterator-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15442) *Returns*: x.*current_* <=> y.*current_*[.](#range.slide.iterator-27.sentence-1) [🔗](#lib:operator+,slide_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [28](#range.slide.iterator-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15456) *Effects*: Equivalent to:auto r = i; r += n;return r; [🔗](#lib:operator-,slide_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [29](#range.slide.iterator-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15473) *Effects*: Equivalent to:auto r = i; r -= n;return r; [🔗](#lib:operator-,slide_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [30](#range.slide.iterator-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15490) *Returns*: If *last_ele_* is present,x.*last_ele_* - y.*last_ele_*; otherwise, x.*current_* - y.*current_*[.](#range.slide.iterator-30.sentence-1) #### [25.7.30.4](#range.slide.sentinel) Class slide_view​::​*sentinel* [[range.slide.sentinel]](range.slide.sentinel) [🔗](#lib:slide_view::sentinel) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class slide_view::*sentinel* { sentinel_t *end_* = sentinel_t(); // *exposition only*constexpr explicit *sentinel*(sentinel_t end); // *exposition only*public:*sentinel*() = default; friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); friend constexpr range_difference_toperator-(const *iterator*& x, const *sentinel*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; friend constexpr range_difference_toperator-(const *sentinel*& y, const *iterator*& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; };} [1](#range.slide.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15524) [*Note [1](#range.slide.sentinel-note-1)*: *sentinel* is used only when [*slide-caches-first*](#concept:slide-caches-first "25.7.30.2 Class template slide_­view [range.slide.view]") is true[.](#range.slide.sentinel-1.sentence-1) — *end note*] [🔗](#lib:slide_view::sentinel,constructor) `constexpr explicit sentinel(sentinel_t end); ` [2](#range.slide.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15536) *Effects*: Initializes *end_* with end[.](#range.slide.sentinel-2.sentence-1) [🔗](#lib:operator==,slide_view::sentinel) `friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.slide.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15547) *Returns*: x.*last_ele_* == y.*end_*[.](#range.slide.sentinel-3.sentence-1) [🔗](#lib:operator-,slide_view::sentinel) `friend constexpr range_difference_t operator-(const iterator& x, const sentinel& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [4](#range.slide.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15560) *Returns*: x.*last_ele_* - y.*end_*[.](#range.slide.sentinel-4.sentence-1) [🔗](#lib:operator-,slide_view::sentinel_) `friend constexpr range_difference_t operator-(const sentinel& y, const iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [5](#range.slide.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15573) *Returns*: y.*end_* - x.*last_ele_*[.](#range.slide.sentinel-5.sentence-1) ### [25.7.31](#range.chunk.by) Chunk by view [[range.chunk.by]](range.chunk.by) #### [25.7.31.1](#range.chunk.by.overview) Overview [[range.chunk.by.overview]](range.chunk.by.overview) [1](#range.chunk.by.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15582) chunk_by_view takes a view and a predicate, and splits the view into subranges between each pair of adjacent elements for which the predicate returns false[.](#range.chunk.by.overview-1.sentence-1) [2](#range.chunk.by.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15588) The name views​::​chunk_by denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.chunk.by.overview-2.sentence-1) Given subexpressions E and F, the expression views​::​chunk_by(E, F) is expression-equivalent tochunk_by_view(E, F)[.](#range.chunk.by.overview-2.sentence-2) [*Example [1](#range.chunk.by.overview-example-1)*: vector v = {1, 2, 2, 3, 0, 4, 5, 2}; for (auto r : v | views::chunk_by(ranges::less_equal{})) { cout << '['; auto sep = ""; for (auto i : r) { cout << sep << i; sep = ", "; } cout << "] ";}// The above prints [1, 2, 2, 3] [0, 4, 5] [2] — *end example*] #### [25.7.31.2](#range.chunk.by.view) Class template chunk_by_view [[range.chunk.by.view]](range.chunk.by.view) [🔗](#lib:chunk_by_view) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [indirect_binary_predicate](indirectcallable.indirectinvocable#concept:indirect_binary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]"), iterator_t> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_vclass chunk_by_view : public view_interface> { V *base_* = V(); // *exposition only**movable-box* *pred_*; // *exposition only*// [[range.chunk.by.iter]](#range.chunk.by.iter "25.7.31.3 Class chunk_­by_­view​::​iterator"), class chunk_by_view​::​*iterator*class *iterator*; // *exposition only*public: chunk_by_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit chunk_by_view(V base, Pred pred); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr const Pred& pred() const; constexpr *iterator* begin(); constexpr auto end(); constexpr iterator_t *find-next*(iterator_t); // *exposition only*constexpr iterator_t *find-prev*(iterator_t) // *exposition only*requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); }; template chunk_by_view(R&&, Pred) -> chunk_by_view, Pred>;} [🔗](#lib:chunk_by_view,constructor) `constexpr explicit chunk_by_view(V base, Pred pred); ` [1](#range.chunk.by.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15654) *Effects*: Initializes *base_* with std​::​move(base) and*pred_* with std​::​move(pred)[.](#range.chunk.by.view-1.sentence-1) [🔗](#lib:pred,chunk_by_view) `constexpr const Pred& pred() const; ` [2](#range.chunk.by.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15666) *Effects*: Equivalent to: return **pred_*; [🔗](#lib:begin,chunk_by_view) `constexpr iterator begin(); ` [3](#range.chunk.by.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15677) *Preconditions*: *pred_*.has_value() is true[.](#range.chunk.by.view-3.sentence-1) [4](#range.chunk.by.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15681) *Returns*: *iterator*(*this, ranges​::​begin(*base_*), *find-next*(ranges​::​begin(*base_*)))[.](#range.chunk.by.view-4.sentence-1) [5](#range.chunk.by.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15685) *Remarks*: In order to provide the amortized constant-time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept, this function caches the result within the chunk_by_view for use on subsequent calls[.](#range.chunk.by.view-5.sentence-1) [🔗](#lib:end,chunk_by_view) `constexpr auto end(); ` [6](#range.chunk.by.view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15699) *Effects*: Equivalent to:if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(*this, ranges::end(*base_*), ranges::end(*base_*));} else {return default_sentinel;} [🔗](#lib:find-next,chunk_by_view) `constexpr iterator_t find-next(iterator_t current); ` [7](#range.chunk.by.view-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15717) *Preconditions*: *pred_*.has_value() is true[.](#range.chunk.by.view-7.sentence-1) [8](#range.chunk.by.view-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15721) *Returns*: ranges::next(ranges::adjacent_find(current, ranges::end(*base_*), not_fn(ref(**pred_*))), 1, ranges::end(*base_*)) [🔗](#lib:find-prev,chunk_by_view) `constexpr iterator_t find-prev(iterator_t current) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [9](#range.chunk.by.view-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15735) *Preconditions*: - [(9.1)](#range.chunk.by.view-9.1) current is not equal to ranges​::​begin(*base_*)[.](#range.chunk.by.view-9.1.sentence-1) - [(9.2)](#range.chunk.by.view-9.2) *pred_*.has_value() is true[.](#range.chunk.by.view-9.2.sentence-1) [10](#range.chunk.by.view-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15744) *Returns*: An iterator i in the range [ranges​::​begin(*base_*), current) such that: - [(10.1)](#range.chunk.by.view-10.1) ranges​::​adjacent_find(i, current, not_fn(ref(**pred_*))) is equal to current; and - [(10.2)](#range.chunk.by.view-10.2) if i is not equal to ranges​::​begin(*base_*), then bool(invoke(**pred_*, *ranges​::​prev(i), *i)) is false[.](#range.chunk.by.view-10.sentence-1) #### [25.7.31.3](#range.chunk.by.iter) Class chunk_by_view​::​*iterator* [[range.chunk.by.iter]](range.chunk.by.iter) [🔗](#lib:chunk_by_view::iterator) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [indirect_binary_predicate](indirectcallable.indirectinvocable#concept:indirect_binary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]"), iterator_t> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && is_object_vclass chunk_by_view::*iterator* { chunk_by_view* *parent_* = nullptr; // *exposition only* iterator_t *current_* = iterator_t(); // *exposition only* iterator_t *next_* = iterator_t(); // *exposition only*constexpr *iterator*(chunk_by_view& parent, iterator_t current, // *exposition only* iterator_t next); public:using value_type = subrange>; using difference_type = range_difference_t; using iterator_category = input_iterator_tag; using iterator_concept = *see below*; *iterator*() = default; constexpr value_type operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); friend constexpr bool operator==(const *iterator*& x, default_sentinel_t); };} [1](#range.chunk.by.iter-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15794) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.chunk.by.iter-1.1) If V models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.chunk.by.iter-1.1.sentence-1) - [(1.2)](#range.chunk.by.iter-1.2) Otherwise, iterator_concept denotes forward_iterator_tag[.](#range.chunk.by.iter-1.2.sentence-1) [🔗](#lib:chunk_by_view::iterator,constructor) `constexpr iterator(chunk_by_view& parent, iterator_t current, iterator_t next); ` [2](#range.chunk.by.iter-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15810) *Effects*: Initializes *parent_* with addressof(parent),*current_* with current, and*next_* with next[.](#range.chunk.by.iter-2.sentence-1) [🔗](#lib:operator*,chunk_by_view::iterator) `constexpr value_type operator*() const; ` [3](#range.chunk.by.iter-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15823) *Preconditions*: *current_* is not equal to *next_*[.](#range.chunk.by.iter-3.sentence-1) [4](#range.chunk.by.iter-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15827) *Returns*: subrange(*current_*, *next_*)[.](#range.chunk.by.iter-4.sentence-1) [🔗](#lib:operator++,chunk_by_view::iterator) `constexpr iterator& operator++(); ` [5](#range.chunk.by.iter-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15838) *Preconditions*: *current_* is not equal to *next_*[.](#range.chunk.by.iter-5.sentence-1) [6](#range.chunk.by.iter-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15842) *Effects*: Equivalent to:*current_* = *next_*;*next_* = *parent_*->*find-next*(*current_*);return *this; [🔗](#lib:operator++,chunk_by_view::iterator_) `constexpr iterator operator++(int); ` [7](#range.chunk.by.iter-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15858) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,chunk_by_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [8](#range.chunk.by.iter-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15874) *Effects*: Equivalent to:*next_* = *current_*;*current_* = *parent_*->*find-prev*(*next_*);return *this; [🔗](#lib:operator--,chunk_by_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [9](#range.chunk.by.iter-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15890) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator==,chunk_by_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y); ` [10](#range.chunk.by.iter-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15906) *Returns*: x.*current_* == y.*current_*[.](#range.chunk.by.iter-10.sentence-1) [🔗](#lib:operator==,chunk_by_view::iterator_) `friend constexpr bool operator==(const iterator& x, default_sentinel_t); ` [11](#range.chunk.by.iter-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15917) *Returns*: x.*current_* == x.*next_*[.](#range.chunk.by.iter-11.sentence-1) ### [25.7.32](#range.stride) Stride view [[range.stride]](range.stride) #### [25.7.32.1](#range.stride.overview) Overview [[range.stride.overview]](range.stride.overview) [1](#range.stride.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15926) stride_view presents a view of an underlying sequence, advancing over n elements at a time, as opposed to the usual single-step succession[.](#range.stride.overview-1.sentence-1) [2](#range.stride.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15931) The name views​::​stride denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.stride.overview-2.sentence-1) Given subexpressions E and N, the expression views​::​stride(E, N) is expression-equivalent to stride_view(E, N)[.](#range.stride.overview-2.sentence-2) [3](#range.stride.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15938) [*Example [1](#range.stride.overview-example-1)*: auto input = views::iota(0, 12) | views::stride(3); ranges::copy(input, ostream_iterator(cout, " ")); // prints 0 3 6 9 ranges::copy(input | views::reverse, ostream_iterator(cout, " ")); // prints 9 6 3 0 — *end example*] #### [25.7.32.2](#range.stride.view) Class template stride_view [[range.stride.view]](range.stride.view) [🔗](#lib:stride_view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class stride_view : public view_interface> { V *base_*; // *exposition only* range_difference_t *stride_*; // *exposition only*// [[range.stride.iterator]](#range.stride.iterator "25.7.32.3 Class template stride_­view​::​iterator"), class template stride_view​::​*iterator*template class *iterator*; // *exposition only*public:constexpr explicit stride_view(V base, range_difference_t stride); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr range_difference_t stride() const noexcept; constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {return *iterator*(this, ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {return *iterator*(this, ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")) {auto missing = (*stride_* - ranges::distance(*base_*) % *stride_*) % *stride_*; return *iterator*(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(this, ranges::end(*base_*)); } else {return default_sentinel; }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]") {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")) {auto missing = (*stride_* - ranges::distance(*base_*) % *stride_*) % *stride_*; return *iterator*(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*(this, ranges::end(*base_*)); } else {return default_sentinel; }}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]"); constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); }; template stride_view(R&&, range_difference_t) -> stride_view>;} [🔗](#lib:stride_view,constructor) `constexpr stride_view(V base, range_difference_t stride); ` [1](#range.stride.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16015) *Preconditions*: stride > 0 is true[.](#range.stride.view-1.sentence-1) [2](#range.stride.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16019) *Effects*: Initializes *base_* with std​::​move(base) and*stride_* with stride[.](#range.stride.view-2.sentence-1) [🔗](#lib:stride,stride_view) `constexpr range_difference_t stride() const noexcept; ` [3](#range.stride.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16031) *Returns*: *stride_*[.](#range.stride.view-3.sentence-1) [🔗](#lib:size,stride_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]"); ` [4](#range.stride.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16043) *Effects*: Equivalent to:return *to-unsigned-like*(*div-ceil*(ranges::distance(*base_*), *stride_*)); [🔗](#lib:reserve_hint,stride_view) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [5](#range.stride.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16058) *Effects*: Equivalent to:auto s = static_cast>(ranges::reserve_hint(*base_*));return *to-unsigned-like*(*div-ceil*(s, *stride_*)); #### [25.7.32.3](#range.stride.iterator) Class template stride_view​::​*iterator* [[range.stride.iterator]](range.stride.iterator) [🔗](#lib:stride_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")templateclass stride_view::*iterator* {using *Parent* = *maybe-const*; // *exposition only*using *Base* = *maybe-const*; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only* range_difference_t<*Base*> *stride_* = 0; // *exposition only* range_difference_t<*Base*> *missing_* = 0; // *exposition only*constexpr *iterator*(*Parent** parent, iterator_t<*Base*> current, // *exposition only* range_difference_t<*Base*> missing = 0); public:using difference_type = range_difference_t<*Base*>; using value_type = range_value_t<*Base*>; using iterator_concept = *see below*; using iterator_category = *see below*; // not always present*iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")> = default; constexpr *iterator*(*iterator* other)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t<*Base*>>&& [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t<*Base*>>; constexpr iterator_t<*Base*> base() &&; constexpr const iterator_t<*Base*>& base() const & noexcept; constexpr decltype(auto) operator*() const { return **current_*; }constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; constexpr decltype(auto) operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>{ return *(*this + n); }friend constexpr bool operator==(const *iterator*& x, default_sentinel_t); 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*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; friend constexpr *iterator* operator+(const *iterator*& x, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& x, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr difference_type operator-(default_sentinel_t y, const *iterator*& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr difference_type operator-(const *iterator*& x, default_sentinel_t y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr range_rvalue_reference_t<*Base*> iter_move(const *iterator*& i)noexcept(noexcept(ranges::iter_move(i.*current_*))); friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)noexcept(noexcept(ranges::iter_swap(x.*current_*, y.*current_*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [1](#range.stride.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16161) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.stride.iterator-1.1) If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes random_access_iterator_tag[.](#range.stride.iterator-1.1.sentence-1) - [(1.2)](#range.stride.iterator-1.2) Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes bidirectional_iterator_tag[.](#range.stride.iterator-1.2.sentence-1) - [(1.3)](#range.stride.iterator-1.3) Otherwise, if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes forward_iterator_tag[.](#range.stride.iterator-1.3.sentence-1) - [(1.4)](#range.stride.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.stride.iterator-1.4.sentence-1) [2](#range.stride.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16177) 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 *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.stride.iterator-2.sentence-1) In that case,*iterator*​::​iterator_category is defined as follows: - [(2.1)](#range.stride.iterator-2.1) Let C denote the type iterator_traits>​::​iterator_category[.](#range.stride.iterator-2.1.sentence-1) - [(2.2)](#range.stride.iterator-2.2) If C models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"), then iterator_category denotes random_access_iterator_tag[.](#range.stride.iterator-2.2.sentence-1) - [(2.3)](#range.stride.iterator-2.3) Otherwise, iterator_category denotes C[.](#range.stride.iterator-2.3.sentence-1) [🔗](#lib:stride_view::iterator,constructor) `constexpr iterator(Parent* parent, iterator_t current, range_difference_t missing = 0); ` [3](#range.stride.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16201) *Effects*: Initializes *current_* with std​::​move(current),*end_* with ranges​::​end(parent->*base_*),*stride_* with parent->*stride_*, and*missing_* with missing[.](#range.stride.iterator-3.sentence-1) [🔗](#lib:stride_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), sentinel_t>; ` [4](#range.stride.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16217) *Effects*: Initializes *current_* with std​::​move(i.*current_*),*end_* with std​::​move(i.*end_*),*stride_* with i.*stride_*, and*missing_* with i.*missing_*[.](#range.stride.iterator-4.sentence-1) [🔗](#lib:base,stride_view::iterator) `constexpr iterator_t base() &&; ` [5](#range.stride.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16231) *Returns*: std​::​move(*current_*)[.](#range.stride.iterator-5.sentence-1) [🔗](#lib:base,stride_view::iterator_) `constexpr const iterator_t& base() const & noexcept; ` [6](#range.stride.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16242) *Returns*: *current_*[.](#range.stride.iterator-6.sentence-1) [🔗](#lib:operator++,stride_view::iterator) `constexpr iterator& operator++(); ` [7](#range.stride.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16253) *Preconditions*: *current_* != *end_* is true[.](#range.stride.iterator-7.sentence-1) [8](#range.stride.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16257) *Effects*: Equivalent to:*missing_* = ranges::advance(*current_*, *stride_*, *end_*);return *this; [🔗](#lib:operator++,stride_view::iterator_) `constexpr void operator++(int); ` [9](#range.stride.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16272) *Effects*: Equivalent to ++*this; [🔗](#lib:operator++,stride_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [10](#range.stride.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16283) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,stride_view::iterator) `constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [11](#range.stride.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16299) *Effects*: Equivalent to:ranges::advance(*current_*, *missing_* - *stride_*);*missing_* = 0;return *this; [🔗](#lib:operator--,stride_view::iterator_) `constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"); ` [12](#range.stride.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16315) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,stride_view::iterator) `constexpr iterator& operator+=(difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [13](#range.stride.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16331) *Preconditions*: If n is positive,ranges​::​distance(*current_*, *end_*) > *stride_* * (n - 1) is true[.](#range.stride.iterator-13.sentence-1) [*Note [1](#range.stride.iterator-note-1)*: If n is negative, the *Effects* paragraph implies a precondition[.](#range.stride.iterator-13.sentence-2) — *end note*] [14](#range.stride.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16340) *Effects*: Equivalent to:if (n > 0) { ranges::advance(*current_*, *stride_* * (n - 1)); *missing_* = ranges::advance(*current_*, *stride_*, *end_*);} else if (n < 0) { ranges::advance(*current_*, *stride_* * n + *missing_*); *missing_* = 0;}return *this; [🔗](#lib:operator-=,stride_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [15](#range.stride.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16362) *Effects*: Equivalent to: return *this += -x; [🔗](#lib:operator==,stride_view::iterator) `friend constexpr bool operator==(const iterator& x, default_sentinel_t); ` [16](#range.stride.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16373) *Returns*: x.*current_* == x.*end_*[.](#range.stride.iterator-16.sentence-1) [🔗](#lib:operator==,stride_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]")>; ` [17](#range.stride.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16385) *Returns*: x.*current_* == y.*current_*[.](#range.stride.iterator-17.sentence-1) [🔗](#lib:operator%3c,stride_view::iterator) `friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [18](#range.stride.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16397) *Returns*: x.*current_* < y.*current_*[.](#range.stride.iterator-18.sentence-1) [🔗](#lib:operator%3e,stride_view::iterator) `friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [19](#range.stride.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16409) *Effects*: Equivalent to: return y < x; [🔗](#lib:operator%3c=,stride_view::iterator) `friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [20](#range.stride.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16421) *Effects*: Equivalent to: return !(y < x); [🔗](#lib:operator%3e=,stride_view::iterator) `friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [21](#range.stride.iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16433) *Effects*: Equivalent to: return !(x < y); [🔗](#lib:operator%3c=%3e,stride_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")>; ` [22](#range.stride.iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16445) *Returns*: x.*current_* <=> y.*current_*[.](#range.stride.iterator-22.sentence-1) [🔗](#lib:operator+,stride_view::iterator) `friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [23](#range.stride.iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16459) *Effects*: Equivalent to:auto r = i; r += n;return r; [🔗](#lib:operator-,stride_view::iterator) `friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]"); ` [24](#range.stride.iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16476) *Effects*: Equivalent to:auto r = i; r -= n;return r; [🔗](#lib:operator-,stride_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [25](#range.stride.iterator-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16493) *Returns*: Let N be (x.*current_* - y.*current_*)[.](#range.stride.iterator-25.sentence-1) - [(25.1)](#range.stride.iterator-25.1) If *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"),(N + x.*missing_* - y.*missing_*) / x.*stride_*[.](#range.stride.iterator-25.1.sentence-1) - [(25.2)](#range.stride.iterator-25.2) Otherwise, if N is negative, -*div-ceil*(-N, x.*stride_*)[.](#range.stride.iterator-25.2.sentence-1) - [(25.3)](#range.stride.iterator-25.3) Otherwise, *div-ceil*(N, x.*stride_*)[.](#range.stride.iterator-25.3.sentence-1) [🔗](#lib:operator-,stride_view::iterator__) `friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [26](#range.stride.iterator-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16514) *Returns*: *div-ceil*(x.*end_* - x.*current_*, x.*stride_*)[.](#range.stride.iterator-26.sentence-1) [🔗](#lib:operator-,stride_view::iterator___) `friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [27](#range.stride.iterator-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16526) *Effects*: Equivalent to: return -(y - x); [🔗](#lib:iter_move,stride_view::iterator) `friend constexpr range_rvalue_reference_t iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); ` [28](#range.stride.iterator-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16538) *Effects*: Equivalent to: return ranges​::​iter_move(i.*current_*); [🔗](#lib:iter_swap,stride_view::iterator) `friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [29](#range.stride.iterator-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16551) *Effects*: Equivalent to:ranges​::​iter_swap(x.*current_*, y.*current_*); ### [25.7.33](#range.cartesian) Cartesian product view [[range.cartesian]](range.cartesian) #### [25.7.33.1](#range.cartesian.overview) Overview [[range.cartesian.overview]](range.cartesian.overview) [1](#range.cartesian.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16562) cartesian_product_view takes any non-zero number of ranges n and produces a view of tuples calculated by the n-ary cartesian product of the provided ranges[.](#range.cartesian.overview-1.sentence-1) [2](#range.cartesian.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16567) The name views​::​cartesian_product denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#range.cartesian.overview-2.sentence-1) Given a pack of subexpressions Es, the expression views​::​cartesian_product(Es...) is expression-equivalent to - [(2.1)](#range.cartesian.overview-2.1) views​::​single(tuple()) if Es is an empty pack, - [(2.2)](#range.cartesian.overview-2.2) otherwise,cartesian_product_view...>(Es...)[.](#range.cartesian.overview-2.sentence-2) [3](#range.cartesian.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16581) [*Example [1](#range.cartesian.overview-example-1)*: vector v { 0, 1, 2 };for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) { cout << a << ' ' << b << ' ' << c << '\n';}// The above prints// 0 0 0// 0 0 1// 0 0 2// 0 1 0// 0 1 1// ... — *end example*] #### [25.7.33.2](#range.cartesian.view) Class template cartesian_product_view [[range.cartesian.view]](range.cartesian.view) [🔗](#lib:cartesian_product_view_) namespace std::ranges {templateconcept [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") = // *exposition only*([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ... &&([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*>&& [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*>)); templateconcept [*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") = // *exposition only*[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") || ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")); templateconcept [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") = // *exposition only*([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*> && ... &&([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*>&& [*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")<*maybe-const*>)); templateconcept [*cartesian-product-is-common*](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") = // *exposition only*[*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); templateconcept [*cartesian-product-is-sized*](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") = // *exposition only*([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") && ...); template class FirstSent, class First, class... Vs>concept [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") = // *exposition only*([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*>&& [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*>>)); template<[*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") R>constexpr auto *cartesian-common-arg-end*(R& r) { // *exposition only*if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return ranges::end(r); } else {return ranges::begin(r) + ranges::distance(r); }}template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") First, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")... Vs>requires ([view](range.view#concept:view "25.4.5 Views [range.view]") && ... && [view](range.view#concept:view "25.4.5 Views [range.view]"))class cartesian_product_view : public view_interface> {private: tuple *bases_*; // *exposition only*// [[range.cartesian.iterator]](#range.cartesian.iterator "25.7.33.3 Class template cartesian_­product_­view​::​iterator"), class template cartesian_product_view​::​*iterator*template class *iterator*; // *exposition only*public:constexpr cartesian_product_view() = default; constexpr explicit cartesian_product_view(First first_base, Vs... bases); constexpr *iterator* begin()requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") || ... || ![*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]") && ... && [range](range.range#concept:range "25.4.2 Ranges [range.range]")); constexpr *iterator* end()requires ((![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") || ... || ![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) &&[*cartesian-product-is-common*](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")); constexpr *iterator* end() constrequires [*cartesian-product-is-common*](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr default_sentinel_t end() const noexcept; constexpr *see below* size()requires [*cartesian-product-is-sized*](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr *see below* size() constrequires [*cartesian-product-is-sized*](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); }; template cartesian_product_view(Vs&&...) -> cartesian_product_view...>;} [🔗](#lib:cartesian_product_view,constructor) `constexpr explicit cartesian_product_view(First first_base, Vs... bases); ` [1](#range.cartesian.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16685) *Effects*: Initializes *bases_* with std​::​move(first_base), std​::​move(bases)...[.](#range.cartesian.view-1.sentence-1) [🔗](#lib:begin,cartesian_product_view) `constexpr iterator begin() requires (![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") || ... || ![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")); ` [2](#range.cartesian.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16698) *Effects*: Equivalent to:return *iterator*(*this, *tuple-transform*(ranges::begin, *bases_*)); [🔗](#lib:begin,cartesian_product_view_) `constexpr iterator begin() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]") && ... && [range](range.range#concept:range "25.4.2 Ranges [range.range]")); ` [3](#range.cartesian.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16713) *Effects*: Equivalent to:return *iterator*(*this, *tuple-transform*(ranges::begin, *bases_*)); [🔗](#lib:end,cartesian_product_view) `constexpr iterator end() requires ((![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") || ... || ![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")) && [cartesian-product-is-common](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")); constexpr iterator end() const requires [cartesian-product-is-common](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [4](#range.cartesian.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16731) Let: - [(4.1)](#range.cartesian.view-4.1) *is-const* be true for the const-qualified overload, andfalse otherwise; - [(4.2)](#range.cartesian.view-4.2) *is-empty* be true if the expression ranges​::​empty(rng) is true for any rng among the underlying ranges except the first one andfalse otherwise; and - [(4.3)](#range.cartesian.view-4.3) *begin-or-first-end*(rng) be expression-equivalent to*is-empty* ? ranges​::​begin(rng) : ​*cartesian-common-arg-end*(rng) if rng is the first underlying range andranges​::​begin(rng) otherwise[.](#range.cartesian.view-4.sentence-1) [5](#range.cartesian.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16749) *Effects*: Equivalent to:*iterator*<*is-const*> it(*this, *tuple-transform*([](auto& rng){ return *begin-or-first-end*(rng); }, *bases_*));return it; [🔗](#lib:end,cartesian_product_view_) `constexpr default_sentinel_t end() const noexcept; ` [6](#range.cartesian.view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16765) *Returns*: default_sentinel[.](#range.cartesian.view-6.sentence-1) [🔗](#lib:size,cartesian_product_view) `constexpr see below size() requires [cartesian-product-is-sized](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr see below size() const requires [cartesian-product-is-sized](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [7](#range.cartesian.view-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16779) The return type is an implementation-defined unsigned-integer-like type[.](#range.cartesian.view-7.sentence-1) [8](#range.cartesian.view-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16782) *Recommended practice*: The return type should be the smallest unsigned-integer-like type that is sufficiently wide to store the product of the maximum sizes of all the underlying ranges, if such a type exists[.](#range.cartesian.view-8.sentence-1) [9](#range.cartesian.view-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16788) Let p be the product of the sizes of all the ranges in *bases_*[.](#range.cartesian.view-9.sentence-1) [10](#range.cartesian.view-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16791) *Preconditions*: p can be represented by the return type[.](#range.cartesian.view-10.sentence-1) [11](#range.cartesian.view-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16795) *Returns*: p[.](#range.cartesian.view-11.sentence-1) #### [25.7.33.3](#range.cartesian.iterator) Class template cartesian_product_view​::​*iterator* [[range.cartesian.iterator]](range.cartesian.iterator) [🔗](#lib:cartesian_product_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") First, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")... Vs>requires ([view](range.view#concept:view "25.4.5 Views [range.view]") && ... && [view](range.view#concept:view "25.4.5 Views [range.view]"))templateclass cartesian_product_view::*iterator* {public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = tuple>, range_value_t<*maybe-const*>...>; using reference = tuple>, range_reference_t<*maybe-const*>...>; using difference_type = *see below*; *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> &&... && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>); constexpr auto operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*>; constexpr *iterator*& operator--()requires [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr *iterator* operator--(int)requires [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr *iterator*& operator+=(difference_type x)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr *iterator*& operator-=(difference_type x)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); constexpr reference operator[](difference_type n) constrequires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.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*& x, default_sentinel_t); friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); friend constexpr *iterator* operator+(const *iterator*& x, difference_type y)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); friend constexpr *iterator* operator+(difference_type x, const *iterator*& y)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); friend constexpr *iterator* operator-(const *iterator*& x, difference_type y)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); friend constexpr difference_type operator-(const *iterator*& i, default_sentinel_t)requires [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); friend constexpr difference_type operator-(default_sentinel_t, const *iterator*& i)requires [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); friend constexpr auto iter_move(const *iterator*& i) noexcept(*see below*); friend constexpr void iter_swap(const *iterator*& l, const *iterator*& r) noexcept(*see below*)requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>> && ... &&[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>>); private:using *Parent* = *maybe-const*; // *exposition only**Parent** *parent_* = nullptr; // *exposition only* tuple>, iterator_t<*maybe-const*>...> *current_*; // *exposition only*templateconstexpr void *next*(); // *exposition only*templateconstexpr void *prev*(); // *exposition only*templateconstexpr difference_type *distance-from*(const Tuple& t) const; // *exposition only*constexpr *iterator*(*Parent*& parent, tuple>, iterator_t<*maybe-const*>...> current); // *exposition only*};} [1](#range.cartesian.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16891) *iterator*​::​iterator_concept is defined as follows: - [(1.1)](#range.cartesian.iterator-1.1) If [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") is modeled, then iterator_concept denotes random_access_iterator_tag[.](#range.cartesian.iterator-1.1.sentence-1) - [(1.2)](#range.cartesian.iterator-1.2) Otherwise, if [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]") is modeled, then iterator_concept denotes bidirectional_iterator_tag[.](#range.cartesian.iterator-1.2.sentence-1) - [(1.3)](#range.cartesian.iterator-1.3) Otherwise, if *maybe-const* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), then iterator_concept denotes forward_iterator_tag[.](#range.cartesian.iterator-1.3.sentence-1) - [(1.4)](#range.cartesian.iterator-1.4) Otherwise, iterator_concept denotes input_iterator_tag[.](#range.cartesian.iterator-1.4.sentence-1) [2](#range.cartesian.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16911) *iterator*​::​difference_type is an implementation-defined signed-integer-like type[.](#range.cartesian.iterator-2.sentence-1) [3](#range.cartesian.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16916) *Recommended practice*: *iterator*​::​difference_type should be the smallest signed-integer-like type that is sufficiently wide to store the product of the maximum sizes of all underlying ranges if such a type exists[.](#range.cartesian.iterator-3.sentence-1) [🔗](#lib:next,cartesian_product_view) `template constexpr void next(); ` [4](#range.cartesian.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16931) *Effects*: Equivalent to:auto& it = std::get(*current_*);++it;if constexpr (N > 0) {if (it == ranges::end(std::get(*parent_*->*bases_*))) { it = ranges::begin(std::get(*parent_*->*bases_*)); *next*(); }} [🔗](#lib:prev,cartesian_product_view) `template constexpr void prev(); ` [5](#range.cartesian.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16953) *Effects*: Equivalent to:auto& it = std::get(*current_*);if constexpr (N > 0) {if (it == ranges::begin(std::get(*parent_*->*bases_*))) { it = *cartesian-common-arg-end*(std::get(*parent_*->*bases_*)); *prev*(); }}--it; [🔗](#lib:distance-from,cartesian_product_view) `template constexpr difference_type distance-from(const Tuple& t) const; ` [6](#range.cartesian.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16975) Let: - [(6.1)](#range.cartesian.iterator-6.1) *scaled-size*(N) be the product ofstatic_cast(ranges​::​size(std​::​get<​N>(*parent_*->*bases_*))) andscaled-size(N+1) if N ≤ sizeof...(Vs), otherwise static_cast(1); - [(6.2)](#range.cartesian.iterator-6.2) *scaled-distance*(N) be the product ofstatic_cast(std​::​get(*current_*) - std​::​get(t)) and scaled-size(N+1); and - [(6.3)](#range.cartesian.iterator-6.3) *scaled-sum* be the sum of *scaled-distance*(N) for every integer 0 ≤ N ≤ sizeof...(Vs)[.](#range.cartesian.iterator-6.sentence-1) [7](#range.cartesian.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16991) *Preconditions*: *scaled-sum* can be represented by difference_type[.](#range.cartesian.iterator-7.sentence-1) [8](#range.cartesian.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16995) *Returns*: *scaled-sum*[.](#range.cartesian.iterator-8.sentence-1) [🔗](#lib:cartesian_product_view::iterator,constructor) `constexpr iterator(Parent& parent, tuple>, iterator_t>...> current); ` [9](#range.cartesian.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17007) *Effects*: Initializes*parent_* with addressof(parent) and*current_* with std​::​move(current)[.](#range.cartesian.iterator-9.sentence-1) [🔗](#lib:cartesian_product_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t> && ... && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>); ` [10](#range.cartesian.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17022) *Effects*: Initializes*parent_* with i.*parent_* and*current_* with std​::​move(i.*current_*)[.](#range.cartesian.iterator-10.sentence-1) [🔗](#lib:operator*,cartesian_product_view::iterator) `constexpr auto operator*() const; ` [11](#range.cartesian.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17035) *Effects*: Equivalent to:return *tuple-transform*([](auto& i) -> decltype(auto) { return *i; }, *current_*); [🔗](#lib:operator++,cartesian_product_view::iterator) `constexpr iterator& operator++(); ` [12](#range.cartesian.iterator-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17049) *Effects*: Equivalent to:*next*();return *this; [🔗](#lib:operator++,cartesian_product_view::iterator_) `constexpr void operator++(int); ` [13](#range.cartesian.iterator-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17064) *Effects*: Equivalent to ++*this[.](#range.cartesian.iterator-13.sentence-1) [🔗](#lib:operator++,cartesian_product_view::iterator__) `constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")>; ` [14](#range.cartesian.iterator-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17075) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator--,cartesian_product_view::iterator) `constexpr iterator& operator--() requires [cartesian-product-is-bidirectional](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [15](#range.cartesian.iterator-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17092) *Effects*: Equivalent to:*prev*();return *this; [🔗](#lib:operator--,cartesian_product_view::iterator_) `constexpr iterator operator--(int) requires [cartesian-product-is-bidirectional](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [16](#range.cartesian.iterator-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17108) *Effects*: Equivalent to:auto tmp = *this;--*this;return tmp; [🔗](#lib:operator+=,cartesian_product_view::iterator) `constexpr iterator& operator+=(difference_type x) requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [17](#range.cartesian.iterator-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17125) Let orig be the value of *this before the call[.](#range.cartesian.iterator-17.sentence-1) Let ret be: - [(17.1)](#range.cartesian.iterator-17.1) If x > 0, the value of *this had *next* been called x times[.](#range.cartesian.iterator-17.1.sentence-1) - [(17.2)](#range.cartesian.iterator-17.2) Otherwise, if x < 0, the value of *this had *prev* been called -x times[.](#range.cartesian.iterator-17.2.sentence-1) - [(17.3)](#range.cartesian.iterator-17.3) Otherwise, orig[.](#range.cartesian.iterator-17.3.sentence-1) [18](#range.cartesian.iterator-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17140) *Preconditions*: x is in the range[ranges​::​distance(*this, ranges​::​begin(**parent_*)), ranges​::​distance(*this, ranges​::​end(**parent_*))][.](#range.cartesian.iterator-18.sentence-1) [19](#range.cartesian.iterator-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17146) *Effects*: Sets the value of *this to ret[.](#range.cartesian.iterator-19.sentence-1) [20](#range.cartesian.iterator-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17150) *Returns*: *this[.](#range.cartesian.iterator-20.sentence-1) [21](#range.cartesian.iterator-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17154) *Complexity*: Constant[.](#range.cartesian.iterator-21.sentence-1) [🔗](#lib:operator-=,cartesian_product_view::iterator) `constexpr iterator& operator-=(difference_type x) requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [22](#range.cartesian.iterator-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17166) *Effects*: Equivalent to:*this += -x;return *this; [🔗](#lib:operator%5b%5d,cartesian_product_view::iterator) `constexpr reference operator[](difference_type n) const requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [23](#range.cartesian.iterator-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17182) *Effects*: Equivalent to: return *((*this) + n); [🔗](#lib:operator==,cartesian_product_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]")>>; ` [24](#range.cartesian.iterator-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17194) *Effects*: Equivalent to: return x.*current_* == y.*current_*; [🔗](#lib:operator==,cartesian_product_view::iterator_) `friend constexpr bool operator==(const iterator& x, default_sentinel_t); ` [25](#range.cartesian.iterator-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17205) *Returns*: true if std​::​get(x.*current_*) == ranges​::​end(std​::​get(x.*parent_*->*bases_*)) is true for any integer 0 ≤ i ≤ sizeof...(Vs); otherwise, false[.](#range.cartesian.iterator-25.sentence-1) [🔗](#lib:operator%3c=%3e,cartesian_product_view::iterator) `friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [all-random-access](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]"); ` [26](#range.cartesian.iterator-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17220) *Effects*: Equivalent to: return x.*current_* <=> y.*current_*; [🔗](#lib:operator+,cartesian_product_view::iterator) `friend constexpr iterator operator+(const iterator& x, difference_type y) requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [27](#range.cartesian.iterator-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17232) *Effects*: Equivalent to: return *iterator*(x) += y; [🔗](#lib:operator+,cartesian_product_view::iterator_) `friend constexpr iterator operator+(difference_type x, const iterator& y) requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [28](#range.cartesian.iterator-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17244) *Effects*: Equivalent to: return y + x; [🔗](#lib:operator-,cartesian_product_view::iterator) `friend constexpr iterator operator-(const iterator& x, difference_type y) requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [29](#range.cartesian.iterator-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17256) *Effects*: Equivalent to: return *iterator*(x) -= y; [🔗](#lib:operator-,cartesian_product_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [cartesian-is-sized-sentinel](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [30](#range.cartesian.iterator-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17268) *Effects*: Equivalent to: return x.*distance-from*(y.*current_*); [🔗](#lib:operator-,cartesian_product_view::iterator__) `friend constexpr difference_type operator-(const iterator& i, default_sentinel_t) requires [cartesian-is-sized-sentinel](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [31](#range.cartesian.iterator-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17280) Let *end-tuple* be an object of a type that is a specialization of tuple, such that: - [(31.1)](#range.cartesian.iterator-31.1) std​::​get<0>(*end-tuple*) has the same value asranges​::​end(std​::​get<0>(i.*parent_*->*bases_*)); - [(31.2)](#range.cartesian.iterator-31.2) std​::​get(*end-tuple*) has the same value asranges​::​begin(std​::​get(i.*parent_*->*bases_*)) for every integer 1 ≤ N ≤ sizeof...(Vs)[.](#range.cartesian.iterator-31.sentence-1) [32](#range.cartesian.iterator-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17293) *Effects*: Equivalent to: return i.*distance-from*(*end-tuple*); [🔗](#lib:operator-,cartesian_product_view::iterator___) `friend constexpr difference_type operator-(default_sentinel_t s, const iterator& i) requires [cartesian-is-sized-sentinel](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]"); ` [33](#range.cartesian.iterator-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17305) *Effects*: Equivalent to: return -(i - s); [🔗](#lib:iter_move,cartesian_product_view::iterator) `friend constexpr auto iter_move(const iterator& i) noexcept(see below); ` [34](#range.cartesian.iterator-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17316) *Effects*: Equivalent to: return *tuple-transform*(ranges​::​iter_move, i.*current_*); [35](#range.cartesian.iterator-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17320) *Remarks*: The exception specification is equivalent to the logical and of the following expressions: - [(35.1)](#range.cartesian.iterator-35.1) noexcept(ranges​::​iter_move(std​::​get(i.*current_*))) for every integer 0 ≤ N ≤ sizeof...(Vs), - [(35.2)](#range.cartesian.iterator-35.2) is_nothrow_move_constructible_v>> for every type T in First, Vs...[.](#range.cartesian.iterator-35.sentence-1) [🔗](#lib:iter_swap,cartesian_product_view::iterator) `friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>> && ... && [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>>); ` [36](#range.cartesian.iterator-36) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17342) *Effects*: For every integer 0 ≤ i ≤ sizeof...(Vs), performs:ranges::iter_swap(std::get(l.*current_*), std::get(r.*current_*)) [37](#range.cartesian.iterator-37) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17349) *Remarks*: The exception specification is equivalent to the logical and of the following expressions: - [(37.1)](#range.cartesian.iterator-37.1) noexcept(ranges​::​iter_swap(std​::​get(l.*current_*), std​::​get(r.*current_*))) for every integer 0 ≤ i ≤ sizeof...(Vs)[.](#range.cartesian.iterator-37.sentence-1) ### [25.7.34](#range.cache.latest) Cache latest view [[range.cache.latest]](range.cache.latest) #### [25.7.34.1](#range.cache.latest.overview) Overview [[range.cache.latest.overview]](range.cache.latest.overview) [1](#range.cache.latest.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17363) cache_latest_view caches the last-accessed element of its underlying sequence so that the element does not have to be recomputed on repeated access[.](#range.cache.latest.overview-1.sentence-1) [*Note [1](#range.cache.latest.overview-note-1)*: This is useful if computation of the element to produce is expensive[.](#range.cache.latest.overview-1.sentence-2) — *end note*] [2](#range.cache.latest.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17371) The name views​::​cache_latest denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.cache.latest.overview-2.sentence-1) Let E be an expression[.](#range.cache.latest.overview-2.sentence-2) The expression views​::​cache_latest(E) is expression-equivalent tocache_latest_view(E)[.](#range.cache.latest.overview-2.sentence-3) #### [25.7.34.2](#range.cache.latest.view) Class template cache_latest_view [[range.cache.latest.view]](range.cache.latest.view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class [cache_latest_view](#lib:cache_latest_view "25.7.34.2 Class template cache_­latest_­view [range.cache.latest.view]") : public view_interface> { V *base_* = V(); // *exposition only*using *cache-t* = conditional_t>, // *exposition only* add_pointer_t>, range_reference_t>; *non-propagating-cache*<*cache-t*> *cache_*; // *exposition only*// [[range.cache.latest.iterator]](#range.cache.latest.iterator "25.7.34.3 Class cache_­latest_­view​::​iterator"), class cache_latest_view​::​*iterator*class *iterator*; // *exposition only*// [[range.cache.latest.sentinel]](#range.cache.latest.sentinel "25.7.34.4 Class cache_­latest_­view​::​sentinel"), class cache_latest_view​::​*sentinel*class *sentinel*; // *exposition only*public: cache_latest_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit cache_latest_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin(); constexpr auto end(); 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]"); constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); }; template cache_latest_view(R&&) -> cache_latest_view>;} [🔗](#lib:cache_latest_view,constructor) `constexpr explicit cache_latest_view(V base); ` [1](#range.cache.latest.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17425) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.cache.latest.view-1.sentence-1) [🔗](#lib:begin,cache_latest_view) `constexpr auto begin(); ` [2](#range.cache.latest.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17436) *Effects*: Equivalent to: return *iterator*(*this); [🔗](#lib:end,cache_latest_view) `constexpr auto end(); ` [3](#range.cache.latest.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17447) *Effects*: Equivalent to: return *sentinel*(*this); [🔗](#lib:size,cache_latest_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]"); ` [4](#range.cache.latest.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17459) *Effects*: Equivalent to: return ranges​::​size(*base_*); [🔗](#lib:reserve_hint,cache_latest_view) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [5](#range.cache.latest.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17471) *Effects*: Equivalent to: return ranges​::​reserve_hint(*base_*); #### [25.7.34.3](#range.cache.latest.iterator) Class cache_latest_view​::​*iterator* [[range.cache.latest.iterator]](range.cache.latest.iterator) [🔗](#lib:cache_latest_view::iiterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class cache_latest_view::*iterator* { cache_latest_view* *parent_*; // *exposition only* iterator_t *current_*; // *exposition only*constexpr explicit *iterator*(cache_latest_view& parent); // *exposition only*public:using difference_type = range_difference_t; using value_type = range_value_t; using iterator_concept = input_iterator_tag; *iterator*(*iterator*&&) = default; *iterator*& operator=(*iterator*&&) = default; constexpr iterator_t base() &&; constexpr const iterator_t& base() const & noexcept; constexpr range_reference_t& operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); friend constexpr range_rvalue_reference_t iter_move(const *iterator*& i)noexcept(noexcept(ranges::iter_move(i.*current_*))); friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)noexcept(noexcept(ranges::iter_swap(x.*current_*, y.*current_*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [🔗](#lib:cache_latest_view::iterator,constructor) `constexpr explicit iterator(cache_latest_view& parent); ` [1](#range.cache.latest.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17521) *Effects*: Initializes *current_* withranges​::​begin(parent.*base_*) and *parent_* with addressof(parent)[.](#range.cache.latest.iterator-1.sentence-1) [🔗](#lib:base,cache_latest_view::iterator) `constexpr iterator_t base() &&; ` [2](#range.cache.latest.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17534) *Returns*: std​::​move(*current_*)[.](#range.cache.latest.iterator-2.sentence-1) [🔗](#lib:base,cache_latest_view::iterator_) `constexpr const iterator_t& base() const & noexcept; ` [3](#range.cache.latest.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17545) *Returns*: *current_*[.](#range.cache.latest.iterator-3.sentence-1) [🔗](#lib:operator++,cache_latest_view::iterator) `constexpr iterator& operator++(); ` [4](#range.cache.latest.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17556) *Effects*: Equivalent to:*parent_*->*cache_*.reset();++*current_*;return *this; [🔗](#lib:operator++,cache_latest_view::iterator_) `constexpr void operator++(int); ` [5](#range.cache.latest.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17572) *Effects*: Equivalent to: ++*this[.](#range.cache.latest.iterator-5.sentence-1) [🔗](#lib:operator*,cache_latest_view::iterator) `constexpr range_reference_t& operator*() const; ` [6](#range.cache.latest.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17583) *Effects*: Equivalent to:if constexpr (is_reference_v>) {if (!*parent_*->*cache_*) {*parent_*->*cache_* = addressof(*as-lvalue*(**current_*)); }return ***parent_*->*cache_*;} else {if (!*parent_*->c*ache_*) {*parent_*->*cache_*.*emplace-deref*(*current_*); }return **parent_*->*cache_*;} [*Note [1](#range.cache.latest.iterator-note-1)*: Evaluations of operator* on the same iterator object can conflict ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#range.cache.latest.iterator-6.sentence-1) — *end note*] [🔗](#lib:iter_move,cache_latest_view::iterator) `friend constexpr range_rvalue_reference_t iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); ` [7](#range.cache.latest.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17612) *Effects*: Equivalent to: return ranges​::​iter_move(i.*current_*); [🔗](#lib:iter_swap,cache_latest_view::iterator) `friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [8](#range.cache.latest.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17625) *Effects*: Equivalent toranges​::​iter_swap(x.*current_*, y.*current_*)[.](#range.cache.latest.iterator-8.sentence-1) #### [25.7.34.4](#range.cache.latest.sentinel) Class cache_latest_view​::​*sentinel* [[range.cache.latest.sentinel]](range.cache.latest.sentinel) [🔗](#lib:cache_latest_view::sentinel) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class cache_latest_view::*sentinel* { sentinel_t *end_* = sentinel_t(); // *exposition only*constexpr explicit *sentinel*(cache_latest_view& parent); // *exposition only*public:*sentinel*() = default; constexpr sentinel_t base() const; friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); friend constexpr range_difference_t operator-(const *iterator*& x, const *sentinel*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; friend constexpr range_difference_t operator-(const *sentinel*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; };} [🔗](#lib:cache_latest_view::sentinel,constructor) `constexpr explicit sentinel(cache_latest_view& parent); ` [1](#range.cache.latest.sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17664) *Effects*: Initializes *end_* with ranges​::​end(parent.*base_*)[.](#range.cache.latest.sentinel-1.sentence-1) [🔗](#lib:base,cache_latest_view::sentinel) `constexpr sentinel_t base() const; ` [2](#range.cache.latest.sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17675) *Returns*: *end_*[.](#range.cache.latest.sentinel-2.sentence-1) [🔗](#lib:operator==,cache_latest_view::iterator) `friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [3](#range.cache.latest.sentinel-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17687) *Returns*: x.*current_* == y.*end_*[.](#range.cache.latest.sentinel-3.sentence-1) [🔗](#lib:operator-,cache_latest_view::iterator) `friend constexpr range_difference_t operator-(const iterator& x, const sentinel& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [4](#range.cache.latest.sentinel-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17700) *Returns*: x.*current_* - y.*end_*[.](#range.cache.latest.sentinel-4.sentence-1) [🔗](#lib:operator-,cache_latest_view::iterator_) `friend constexpr range_difference_t operator-(const sentinel& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [5](#range.cache.latest.sentinel-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17713) *Returns*: x.*end_* - y.*current_*[.](#range.cache.latest.sentinel-5.sentence-1) ### [25.7.35](#range.to.input) To input view [[range.to.input]](range.to.input) #### [25.7.35.1](#range.to.input.overview) Overview [[range.to.input.overview]](range.to.input.overview) [1](#range.to.input.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17722) to_input_view presents a view of an underlying sequence as an input-only non-common range[.](#range.to.input.overview-1.sentence-1) [*Note [1](#range.to.input.overview-note-1)*: This is useful to avoid overhead that can be necessary to provide support for the operations needed for greater iterator strength[.](#range.to.input.overview-1.sentence-2) — *end note*] [2](#range.to.input.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17731) The name views​::​to_input denotes a range adaptor object ([[range.adaptor.object]](#range.adaptor.object "25.7.2 Range adaptor objects"))[.](#range.to.input.overview-2.sentence-1) Let E be an expression and let T be decltype((E))[.](#range.to.input.overview-2.sentence-2) The expression views​::​to_input(E) is expression-equivalent to: - [(2.1)](#range.to.input.overview-2.1) views​::​all(E) if T models [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]"), does not satisfy [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"), and does not satisfy [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#range.to.input.overview-2.1.sentence-1) - [(2.2)](#range.to.input.overview-2.2) Otherwise, to_input_view(E)[.](#range.to.input.overview-2.2.sentence-1) #### [25.7.35.2](#range.to.input.view) Class template to_input_view [[range.to.input.view]](range.to.input.view) [🔗](#lib:to_input_view) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")class to_input_view : public view_interface> { V *base_* = V(); // *exposition only*// [[range.to.input.iterator]](#range.to.input.iterator "25.7.35.3 Class template to_­input_­view​::​iterator"), class template to_input_view​::​*iterator*template class *iterator*; // *exposition only*public: to_input_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit to_input_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")); constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"); 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]"); 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]"); constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); }; template to_input_view(R&&) -> to_input_view>;} [🔗](#lib:to_input_view,constructor) `constexpr explicit to_input_view(V base); ` [1](#range.to.input.view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17790) *Effects*: Initializes *base_* with std​::​move(base)[.](#range.to.input.view-1.sentence-1) [🔗](#lib:begin,to_input_view) `constexpr auto begin() requires (![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")); ` [2](#range.to.input.view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17801) *Effects*: Equivalent to: return *iterator*(ranges​::​begin(*base_*)); [🔗](#lib:begin,to_input_view_) `constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]"); ` [3](#range.to.input.view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17812) *Effects*: Equivalent to: return *iterator*(ranges​::​begin(*base_*)); [🔗](#lib:end,to_input_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]"); ` [4](#range.to.input.view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17824) *Effects*: Equivalent to: return ranges​::​end(*base_*); [🔗](#lib:size,to_input_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]"); ` [5](#range.to.input.view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17836) *Effects*: Equivalent to: return ranges​::​size(*base_*); [🔗](#lib:reserve_hint,to_input_view) `constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]"); ` [6](#range.to.input.view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17848) *Effects*: Equivalent to: return ranges​::​reserve_hint(*base_*); #### [25.7.35.3](#range.to.input.iterator) Class template to_input_view​::​*iterator* [[range.to.input.iterator]](range.to.input.iterator) [🔗](#lib:to_input_view::iterator) namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V>requires [view](range.view#concept:view "25.4.5 Views [range.view]")templateclass to_input_view::*iterator* {using *Base* = *maybe-const*; // *exposition only* iterator_t<*Base*> *current_* = iterator_t<*Base*>(); // *exposition only*constexpr explicit *iterator*(iterator_t<*Base*> current); // *exposition only*public:using difference_type = range_difference_t<*Base*>; using value_type = range_value_t<*Base*>; using iterator_concept = input_iterator_tag; *iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")> = default; *iterator*(*iterator*&&) = default; *iterator*& operator=(*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<*Base*>>; constexpr iterator_t<*Base*> base() &&; constexpr const iterator_t<*Base*>& base() const & noexcept; constexpr decltype(auto) operator*() const { return **current_*; }constexpr *iterator*& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const *iterator*& x, const sentinel_t<*Base*>& y); friend constexpr difference_type operator-(const sentinel_t<*Base*>& y, const *iterator*& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr difference_type operator-(const *iterator*& x, const sentinel_t<*Base*>& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t<*Base*>>; friend constexpr range_rvalue_reference_t<*Base*> iter_move(const *iterator*& i)noexcept(noexcept(ranges::iter_move(i.*current_*))); friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)noexcept(noexcept(ranges::iter_swap(x.*current_*, y.*current_*)))requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; };} [🔗](#lib:to_input_view::iterator,constructor) `constexpr explicit iterator(iterator_t current); ` [1](#range.to.input.iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17912) *Effects*: Initializes *current_* with std​::​move(current)[.](#range.to.input.iterator-1.sentence-1) [🔗](#lib:to_input_view::iterator,constructor_) `constexpr iterator(iterator i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), iterator_t>; ` [2](#range.to.input.iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17924) *Effects*: Initializes *current_* with std​::​move(i.*current_*)[.](#range.to.input.iterator-2.sentence-1) [🔗](#lib:base,to_input_view::iterator) `constexpr iterator_t base() &&; ` [3](#range.to.input.iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17935) *Returns*: std​::​move(*current_)*[.](#range.to.input.iterator-3.sentence-1) [🔗](#lib:base,to_input_view::iterator_) `constexpr const iterator_t& base() const & noexcept; ` [4](#range.to.input.iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17946) *Returns*: *current_*[.](#range.to.input.iterator-4.sentence-1) [🔗](#lib:operator++,to_input_view::iterator) `constexpr iterator& operator++(); ` [5](#range.to.input.iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17957) *Effects*: Equivalent to:++*current_*;return *this; [🔗](#lib:operator++,to_input_view::iterator_) `constexpr void operator++(int); ` [6](#range.to.input.iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17972) *Effects*: Equivalent to: ++*this; [🔗](#lib:operator==,to_input_view::iterator) `friend constexpr bool operator==(const iterator& x, const sentinel_t& y); ` [7](#range.to.input.iterator-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17983) *Returns*: x.*current_* == y[.](#range.to.input.iterator-7.sentence-1) [🔗](#lib:operator-,to_input_view::iterator) `friend constexpr difference_type operator-(const sentinel_t& y, const iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [8](#range.to.input.iterator-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17995) *Returns*: y - x.*current_*[.](#range.to.input.iterator-8.sentence-1) [🔗](#lib:operator-,to_input_view::iterator_) `friend constexpr difference_type operator-(const iterator& x, const sentinel_t& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>; ` [9](#range.to.input.iterator-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L18007) *Returns*: x.*current_* - y[.](#range.to.input.iterator-9.sentence-1) [🔗](#lib:iter_move,to_input_view::iterator) `friend constexpr range_rvalue_reference_t iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); ` [10](#range.to.input.iterator-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L18019) *Effects*: Equivalent to: return ranges​::​iter_move(i.*current_*); [🔗](#lib:iter_swap,to_input_view::iterator) `friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")>; ` [11](#range.to.input.iterator-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L18032) *Effects*: Equivalent to: ranges​::​iter_swap(x.*current_*, y.*current_*);