[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<int> 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<decltype((D))> 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<decltype((C))> 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]")<range_adaptor_closure<T>>,

- [(2.3)](#range.adaptor.object-2.3)

T has no other base classes of type range_adaptor_closure<U> 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_closure<D>>[.](#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<T> 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<decltype((args))>...[.](#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<decltype((args))>(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*<T> behaves exactly like optional<T> with the following differences:

- [(1.1)](#range.move.wrap-1.1)

*movable-box*<T> constrains
its type parameter T with[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")<T> && is_object_v<T>.

- [(1.2)](#range.move.wrap-1.2)

The default
constructor of *movable-box*<T> is equivalent to:constexpr *movable-box*() noexcept(is_nothrow_default_constructible_v<T>)requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<T>: *movable-box*{in_place} {}

- [(1.3)](#range.move.wrap-1.3)

If [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<T> is not
modeled, the copy assignment operator is equivalent to:constexpr *movable-box*& operator=(const *movable-box*& that)noexcept(is_nothrow_copy_constructible_v<T>)requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<T> {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]")<T> is not modeled,
the move assignment operator is equivalent to:constexpr *movable-box*& operator=(*movable-box*&& that)noexcept(is_nothrow_move_constructible_v<T>) {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]")<T> is true,*movable-box*<T> 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<T> && is_nothrow_copy_constructible_v<T> is true[.](#range.move.wrap-2.1.sentence-1)

- [(2.2)](#range.move.wrap-2.2)

  Otherwise, *movable-box*<T> 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<T> 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*<T> behaves exactly like optional<T> with the following differences:

- [(1.1)](#range.nonprop.cache-1.1)

*non-propagating-cache*<T> constrains its type parameter T with is_object_v<T>.

- [(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*<T> has an additional member function template
specified as follows:
  [ð](#range.nonprop.cache-1.6.itemdecl:1)
`template<class I>
  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 {template<class F, class Tuple>constexpr auto *tuple-transform*(F&& f, Tuple&& t) { // *exposition only*return apply([&]<class... Ts>(Ts&&... elements) {return tuple<invoke_result_t<F&, Ts>...>(invoke(f, std::forward<Ts>(elements))...); }, std::forward<Tuple>(t)); }template<class F, class Tuple>constexpr void *tuple-for-each*(F&& f, Tuple&& t) { // *exposition only* apply([&]<class... Ts>(Ts&&... elements) {(static_cast<void>(invoke(f, std::forward<Ts>(elements))), ...); }, std::forward<Tuple>(t)); }template<class T>constexpr T& *as-lvalue*(T&& t) { // *exposition only*return static_cast<T&>(t); }template<bool Const, class... Views>concept [*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*<Const, Views>> && ...); template<bool Const, class... Views>concept [*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*<Const, Views>> && ...); template<bool Const, class... Views>concept [*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*<Const, Views>> && ...);}

### [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_v<R>class ref_view : public view_interface<ref_view<R>> {private: R* *r_*; // *exposition only*public:template<[*different-from*](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]")<ref_view> T>requires *see below*constexpr ref_view(T&& t); constexpr R& base() const { return **r_*; }constexpr iterator_t<R> begin() const { return ranges::begin(**r_*); }constexpr sentinel_t<R> 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]")<R>{ 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]")<R>{ 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]")<R>{ return ranges::data(**r_*); }}; template<class R> ref_view(R&) -> ref_view<R>;}

[ð](#lib:ref_view,constructor)

`template<[different-from](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]")<ref_view> 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<R&>(std​::​forward<T>(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]")<T, R&> && requires { *FUN*(declval<T>()); }

#### [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]")<R> && (!*is-initializer-list*<R>) // see [[range.refinements]](range.refinements "25.4.6 Other range refinements")class owning_view : public view_interface<owning_view<R>> {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]")<R> = 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<R> begin() { return ranges::begin(*r_*); }constexpr sentinel_t<R> end() { return ranges::end(*r_*); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const R>{ return ranges::begin(*r_*); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const R>{ 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]")<R>{ return ranges::size(*r_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const R>{ 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]")<R>{ 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]")<const R>{ return ranges::reserve_hint(*r_*); }constexpr auto data() requires [contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]")<R>{ return ranges::data(*r_*); }constexpr auto data() const requires [contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]")<const R>{ 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_rvalue_reference_t<T>, range_reference_t<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<string> words = {"the", "quick", "brown", "fox", "ate", "a", "pterodactyl"};
vector<string> 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]")<V>class [as_rvalue_view](#lib:as_rvalue_view "25.7.7.2 Class template as_­rvalue_­view [range.as.rvalue.view]") : public view_interface<as_rvalue_view<V>> { 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]")<V> = 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]")<V> { 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]")<V>){ return move_iterator(ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>{ 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]")<V>) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>) {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]")<const V> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>) {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]")<V> { return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V> { 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]")<V>{ 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]")<const V>{ return ranges::reserve_hint(*base_*); }}; template<class R> as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>;}

[ð](#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<int> 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]")<iterator_t<V>> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && is_object_v<Pred>class filter_view : public view_interface<filter_view<V, Pred>> {private: V *base_* = V(); // *exposition only**movable-box*<Pred> *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]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pred> = 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]")<V> { 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]")<V>)return *iterator*{*this, ranges::end(*base_*)}; elsereturn *sentinel*{*this}; }}; template<class R, class Pred> filter_view(R&&, Pred) -> filter_view<views::all_t<R>, 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]")<iterator_t<V>> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && is_object_v<Pred>class filter_view<V, Pred>::*iterator* {private: iterator_t<V> *current_* = iterator_t<V>(); // *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<V>; using difference_type = range_difference_t<V>; *iterator*() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<iterator_t<V>> = default; constexpr *iterator*(filter_view& parent, iterator_t<V> current); constexpr const iterator_t<V>& base() const & noexcept; constexpr iterator_t<V> base() &&; constexpr range_reference_t<V> operator*() const; constexpr iterator_t<V> operator->() constrequires [*has-arrow*](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]")<iterator_t<V>> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<iterator_t<V>>; 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]")<V>; constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>; 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]")<iterator_t<V>>; friend constexpr range_rvalue_reference_t<V> 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]")<iterator_t<V>>; };}

[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_t<V>>​::​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]")<bidirectional_iterator_tag>,
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]")<forward_iterator_tag>,
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<V> 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<V>& 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<V> 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<V> 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<V> operator->() const
  requires [has-arrow](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]")<iterator_t<V>> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<iterator_t<V>>;
`

[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]")<V>;
`

[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]")<V>;
`

[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]")<V>;
`

[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]")<iterator_t<V>>;
`

[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<V> 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]")<iterator_t<V>>;
`

[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]")<iterator_t<V>> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && is_object_v<Pred>class filter_view<V, Pred>::*sentinel* {private: sentinel_t<V> *end_* = sentinel_t<V>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(filter_view& parent); constexpr sentinel_t<V> 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<V> 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<int> 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]")<V> && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, range_reference_t<V>> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, range_reference_t<V>>>class transform_view : public view_interface<transform_view<V, F>> {private:// [[range.transform.iterator]](#range.transform.iterator "25.7.9.3 Class template transform_­view​::​iterator"), class template transform_view​::​*iterator*template<bool> 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<bool> struct *sentinel*; // *exposition only* V *base_* = V(); // *exposition only**movable-box*<F> *fun_*; // *exposition only*public: transform_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<F> = 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]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr *iterator*<false> begin(); constexpr *iterator*<true> begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const V>>; constexpr *sentinel*<false> end(); constexpr *iterator*<false> end() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>; constexpr *sentinel*<true> end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const V>>; constexpr *iterator*<true> end() constrequires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const V>>; constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> { return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>{ 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]")<V>{ 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]")<const V>{ return ranges::reserve_hint(*base_*); }}; template<class R, class F> transform_view(R&&, F) -> transform_view<views::all_t<R>, 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<false> begin();
`

[2](#range.transform.view-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5276)

*Effects*: Equivalent to:return *iterator*<false>{*this, ranges::begin(*base_*)};

[ð](#lib:begin,transform_view_)

`constexpr iterator<true> begin() const
  requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> &&
           [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const V>>;
`

[3](#range.transform.view-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5292)

*Effects*: Equivalent to:return *iterator*<true>{*this, ranges::begin(*base_*)};

[ð](#lib:end,transform_view)

`constexpr sentinel<false> end();
`

[4](#range.transform.view-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5306)

*Effects*: Equivalent to:return *sentinel*<false>{ranges::end(*base_*)};

[ð](#lib:end,transform_view_)

`constexpr iterator<false> end() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>;
`

[5](#range.transform.view-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5320)

*Effects*: Equivalent to:return *iterator*<false>{*this, ranges::end(*base_*)};

[ð](#lib:end,transform_view__)

`constexpr sentinel<true> end() const
  requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> &&
           [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const V>>;
`

[6](#range.transform.view-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5336)

*Effects*: Equivalent to:return *sentinel*<true>{ranges::end(*base_*)};

[ð](#lib:end,transform_view___)

`constexpr iterator<true> end() const
  requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> &&
           [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const V>>;
`

[7](#range.transform.view-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5352)

*Effects*: Equivalent to:return *iterator*<true>{*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]")<V> && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, range_reference_t<V>> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, range_reference_t<V>>>template<bool Const>class transform_view<V, F>::*iterator* {private:using *Parent* = *maybe-const*<Const, transform_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *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<invoke_result_t<*maybe-const*<Const, F>&, 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]")<iterator_t<*Base*>> = default; constexpr *iterator*(*Parent*& parent, iterator_t<*Base*> current); constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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]")<iterator_t<*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 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]")<iterator_t<*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 *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*>, 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_t<*Base*>>​::​iterator_category[.](#range.transform.iterator-2.sentence-2)

- [(2.1)](#range.transform.iterator-2.1)

  If is_reference_v<invoke_result_t<*maybe-const*<Const, F>&, 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]")<contiguous_iterator_tag>,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<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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>& 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> 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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<iterator_t<Base>>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<Base>>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Base>, iterator_t<Base>>;
`

[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]")<V> && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, range_reference_t<V>> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, range_reference_t<V>>>template<bool Const>class transform_view<V, F>::*sentinel* {private:using *Parent* = *maybe-const*<Const, transform_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *sentinel*& y, const *iterator*<OtherConst>& x); };}

[ð](#lib:transform_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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> 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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const sentinel& y, const iterator<OtherConst>& 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<decltype((E))>, and
let D be range_difference_t<decltype((E))>[.](#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]")<D>,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<D>(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<typename T​::​element_type>;

  * [(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<iterator_t<T>>;

- [(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<D>(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<D>(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<D>(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<int> 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<take_view<V>> {private: V *base_* = V(); // *exposition only* range_difference_t<V> *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<bool> 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]")<V> = default; constexpr explicit take_view(V base, range_difference_t<V> count); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V>) {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<V>) {return ranges::begin(*base_*); } else {auto sz = range_difference_t<V>(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]")<sentinel_t<V>, iterator_t<V>>) {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]")<const V> {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V>) {return ranges::begin(*base_*); } else {auto sz = range_difference_t<const V>(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]")<sentinel_t<const V>, iterator_t<const V>>) {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]")<V>) {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<V>)return ranges::begin(*base_*) + range_difference_t<V>(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]")<sentinel_t<V>, iterator_t<V>>) {return default_sentinel; } else {return *sentinel*<false>{ranges::end(*base_*)}; }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V>)return ranges::begin(*base_*) + range_difference_t<const V>(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]")<sentinel_t<const V>, iterator_t<const V>>) {return default_sentinel; } else {return *sentinel*<true>{ranges::end(*base_*)}; }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> {auto n = ranges::size(*base_*); return ranges::min(n, static_cast<decltype(n)>(*count_*)); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V> {auto n = ranges::size(*base_*); return ranges::min(n, static_cast<decltype(n)>(*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]")<V>) {auto n = static_cast<range_difference_t<V>>(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]")<const V>) {auto n = static_cast<range_difference_t<const V>>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(ranges::min(n, *count_*)); }return *to-unsigned-like*(*count_*); }}; template<class R> take_view(R&&, range_difference_t<R>)-> take_view<views::all_t<R>>;}

[ð](#lib:take_view,constructor)

`constexpr explicit take_view(V base, range_difference_t<V> 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>template<bool Const>class take_view<V>::*sentinel* {private:using *Base* = *maybe-const*<Const, V>; // *exposition only*template<bool OtherConst>using *CI* = counted_iterator<iterator_t<*maybe-const*<OtherConst, V>>>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel*<!Const> s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; friend constexpr bool operator==(const *CI*<Const>& y, const *sentinel*& x); template<bool OtherConst = !Const>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *CI*<OtherConst>& y, const *sentinel*& x); };}

[ð](#lib:take_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<Base> 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<!Const> s)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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> 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<Const>& y, const sentinel& x);

template<bool OtherConst = !Const>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const CI<OtherConst>& 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<int>(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]")<V> && is_object_v<Pred> &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")<const Pred, iterator_t<V>>class take_while_view : public view_interface<take_while_view<V, Pred>> {// [[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<bool> class *sentinel*; // *exposition only* V *base_* = V(); // *exposition only**movable-box*<Pred> *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]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pred> = 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]")<V> { 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]")<V>){ return ranges::begin(*base_*); }constexpr auto begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")<const Pred, iterator_t<const V>>{ return ranges::begin(*base_*); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>){ return *sentinel*<false>(ranges::end(*base_*), addressof(**pred_*)); }constexpr auto end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")<const Pred, iterator_t<const V>>{ return *sentinel*<true>(ranges::end(*base_*), addressof(**pred_*)); }}; template<class R, class Pred> take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, 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]")<V> && is_object_v<Pred> &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")<const Pred, iterator_t<V>>template<bool Const>class take_while_view<V, Pred>::*sentinel* {using *Base* = *maybe-const*<Const, V>; // *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*<!Const> s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const { return *end_*; }friend constexpr bool operator==(const iterator_t<*Base*>& x, const *sentinel*& y); template<bool OtherConst = !Const>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const iterator_t<*maybe-const*<OtherConst, V>>& x, const *sentinel*& y); };}

[ð](#lib:take_while_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<Base> 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<!Const> s)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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<Base>& x, const sentinel& y);

template<bool OtherConst = !Const>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& 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<decltype((E))>, and
let D be range_difference_t<decltype((E))>[.](#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]")<D>,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<D>(ranges​::​distance(E), F), ranges​::​end(E)),
except that E is evaluated only once,
where U is span<typename T​::​element_type> 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<D>(ranges​::​distance(E), F), ranges​::​end(E),*to-unsigned-like*(ranges​::​distance(E) - std​::​min<D>(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<D>(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<drop_view<V>> {public: drop_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<V> = default; constexpr explicit drop_view(V base, range_difference_t<V> count); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V> &&[random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>)); constexpr auto begin() constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>){ return ranges::end(*base_*); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>{ return ranges::end(*base_*); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> {const auto s = ranges::size(*base_*); const auto c = static_cast<decltype(s)>(*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 V> {const auto s = ranges::size(*base_*); const auto c = static_cast<decltype(s)>(*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]")<V> {const auto s = static_cast<range_difference_t<V>>(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 V> {const auto s = static_cast<range_difference_t<const V>>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(s < *count_* ? 0 : s - *count_*); }private: V *base_* = V(); // *exposition only* range_difference_t<V> *count_* = 0; // *exposition only*}; template<class R> drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;}

[ð](#lib:drop_view,constructor)

`constexpr explicit drop_view(V base, range_difference_t<V> 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]")<V> &&
              [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>));
constexpr auto begin() const
  requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V> && is_object_v<Pred> &&[indirect_unary_predicate](indirectcallable.indirectinvocable#concept:indirect_unary_predicate "24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]")<const Pred, iterator_t<V>>class drop_while_view : public view_interface<drop_while_view<V, Pred>> {public: drop_while_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pred> = 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]")<V> { 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> *pred_*; // *exposition only*}; template<class R, class Pred> drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, 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<views​::​all_t<decltype((E))>>{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<string> 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]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>class join_view : public view_interface<join_view<V>> {private:using *InnerRng* = range_reference_t<V>; // *exposition only*// [[range.join.iterator]](#range.join.iterator "25.7.14.3 Class template join_­view​::​iterator"), class template join_view​::​*iterator*template<bool Const>struct *iterator*; // *exposition only*// [[range.join.sentinel]](#range.join.sentinel "25.7.14.4 Class template join_­view​::​sentinel"), class template join_view​::​*sentinel*template<bool Const>struct *sentinel*; // *exposition only* V *base_* = V(); // *exposition only**non-propagating-cache*<iterator_t<V>> *outer_*; // *exposition only*, present only// when ![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V>*non-propagating-cache*<remove_cv_t<*InnerRng*>> *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]")<V> = 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]")<V> { 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]")<V>) {constexpr bool use_const = [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && is_reference_v<*InnerRng*>; return *iterator*<use_const>{*this, ranges::begin(*base_*)}; } else {*outer_* = ranges::begin(*base_*); return *iterator*<false>{*this}; }}constexpr auto begin() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> && is_reference_v<range_reference_t<const V>> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>>{ return *iterator*<true>{*this, ranges::begin(*base_*)}; }constexpr auto end() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> && 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]")<V> && [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]")<V>>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>>{*this}; }constexpr auto end() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> && is_reference_v<range_reference_t<const V>> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>> {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>>)return *iterator*<true>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<true>{*this}; }}; template<class R>explicit join_view(R&&) -> join_view<views::all_t<R>>;}

[ð](#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]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>template<bool Const>struct join_view<V>::*iterator* {private:using *Parent* = *maybe-const*<Const, join_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only*using *OuterIter* = iterator_t<*Base*>; // *exposition only*using *InnerIter* = iterator_t<range_reference_t<*Base*>>; // *exposition only*static constexpr bool *ref-is-glvalue* = // *exposition only* is_reference_v<range_reference_t<*Base*>>; *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<range_reference_t<*Base*>>; using difference_type = *see below*; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i)requires Const &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, *OuterIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<*InnerRng*>, *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]")<range_reference_t<*Base*>>; 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]")<range_reference_t<*Base*>> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<*Base*>>; 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]")<range_reference_t<*Base*>> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<*Base*>>; 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]")<iterator_t<range_reference_t<*Base*>>>; 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_t<*Base*>>​::​iterator_category, and
 let *INNERC* denote iterator_traits<iterator_t<range_reference_t<*Base*>>>​::​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]")<bidirectional_iterator_tag> 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]")<forward_iterator_tag>, 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<range_reference_t<*Base*>>>

[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]")<Base>;
`

[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]")<Base>);
`

[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<!Const> i)
  requires Const &&
           [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, OuterIter> &&
           [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<InnerRng>, 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]")<InnerIter> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<InnerIter>;
`

[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]")<Base> &&
           [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<Base>>;
`

[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]")<Base> &&
           [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<Base>> &&
           [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<Base>>;
`

[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]")<Base> &&
           [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<Base>> &&
           [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<Base>>;
`

[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]")<Base> &&
           [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<iterator_t<range_reference_t<Base>>>;
`

[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]")<InnerIter>;
`

[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]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>template<bool Const>struct join_view<V>::*sentinel* {private:using *Parent* = *maybe-const*<Const, join_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(*Parent*& parent); constexpr *sentinel*(*sentinel*<!Const> s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& 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<!Const> s)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<string> 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 {template<class R>concept [*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]")<R> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<R>; // *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]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>&& [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern>&& [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<range_reference_t<V>, Pattern>class join_with_view : public view_interface<join_with_view<V, Pattern>> {using *InnerRng* = range_reference_t<V>; // *exposition only* V *base_* = V(); // *exposition only**non-propagating-cache*<iterator_t<V>> *outer_it_*; // *exposition only*, present only// when ![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V>*non-propagating-cache*<remove_cv_t<*InnerRng*>> *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<bool Const> 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<bool Const> 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]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pattern> = 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]")<V, views::all_t<R>> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<Pattern, single_view<range_value_t<*InnerRng*>>>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]")<V> { 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]")<V>) {constexpr bool use_const =[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && is_reference_v<*InnerRng*> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>; return *iterator*<use_const>{*this, ranges::begin(*base_*)}; }else {*outer_it_* = ranges::begin(*base_*); return *iterator*<false>{*this}; }}constexpr auto begin() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> &&[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const Pattern> && is_reference_v<range_reference_t<const V>> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>> &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<range_reference_t<const V>, const Pattern> {return *iterator*<true>{*this, ranges::begin(*base_*)}; }constexpr auto end() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> && 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]")<V> && [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]")<V> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>>{*this}; }constexpr auto end() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const Pattern> && is_reference_v<range_reference_t<const V>> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>> &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<range_reference_t<const V>, const Pattern> {using InnerConstRng = range_reference_t<const V>; if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<InnerConstRng> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<InnerConstRng>)return *iterator*<true>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<true>{*this}; }}; template<class R, class P> join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>; template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> join_with_view(R&&, range_value_t<range_reference_t<R>>)-> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>;}

[ð](#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]")<V, views::all_t<R>> &&
           [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<Pattern, single_view<range_value_t<InnerRng>>>
constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> 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>(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]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>&& [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<range_reference_t<V>, Pattern>template<bool Const>class join_with_view<V, Pattern>::*iterator* {using *Parent* = *maybe-const*<Const, join_with_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only*using *InnerBase* = range_reference_t<*Base*>; // *exposition only*using *PatternBase* = *maybe-const*<Const, Pattern>; // *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*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, *OuterIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<*InnerRng*>, *InnerIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Pattern>, *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<rvalue_reference>(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<common_reference_t<iter_reference_t<*InnerIter*>,
 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]")<bidirectional_iterator_tag> 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]")<forward_iterator_tag>,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<*InnerIter*>, 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]")<Base>;
constexpr explicit iterator(Parent& parent)
  requires (![forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<Base>);
`

[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<!Const> i)
    requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, OuterIter> &&
             [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<InnerRng>, InnerIter> &&
             [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Pattern>, 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<*InnerIter*>, 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]")<OuterIter> && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]")<InnerIter>;
`

[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]")<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>;
`

[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]")<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>;
`

[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]")<Base> &&
           [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<InnerIter>;
`

[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]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>&& [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<range_reference_t<V>, Pattern>template<bool Const>class join_with_view<V, Pattern>::*sentinel* {using *Parent* = *maybe-const*<Const, join_with_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*constexpr explicit *sentinel*(*Parent*& parent); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel*<!Const> s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& 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<!Const> s)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<auto> struct *require-constant*; // *exposition only*template<class R>concept [*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]")<R> &&requires { typename *require-constant*<remove_reference_t<R>::size()>; } &&(remove_reference_t<R>::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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]")<Pattern>)class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {private: V *base_* = V(); // *exposition only* Pattern *pattern_* = Pattern(); // *exposition only**non-propagating-cache*<iterator_t<V>> *current_*; // *exposition only*, present only// if [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> 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<bool> 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<bool> 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]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pattern> = 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]")<V, views::all_t<R>> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<Pattern, single_view<range_value_t<R>>>constexpr explicit lazy_split_view(R&& r, range_value_t<R> e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V>) {return *outer-iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>>{*this, ranges::begin(*base_*)}; } else {*current_* = ranges::begin(*base_*); return *outer-iterator*<false>{*this}; }}constexpr auto begin() const requires [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]")<const V> {return *outer-iterator*<true>{*this, ranges::begin(*base_*)}; }constexpr auto end() requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> {return *outer-iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>>{*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]")<V> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>)return *outer-iterator*<true>{*this, ranges::end(*base_*)}; elsereturn default_sentinel; }}; template<class R, class P> lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>; template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> lazy_split_view(R&&, range_value_t<R>)-> lazy_split_view<views::all_t<R>, single_view<range_value_t<R>>>;}

[ð](#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]")<V, views::all_t<R>> &&
           [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<Pattern, single_view<range_value_t<R>>>
constexpr explicit lazy_split_view(R&& r, range_value_t<R> 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>(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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]")<Pattern>)template<bool Const>struct lazy_split_view<V, Pattern>::*outer-iterator* {private:using *Parent* = *maybe-const*<Const, lazy_split_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *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*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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]")<Base>);
`

[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<Base> current)
  requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<Base>;
`

[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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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]")<Pattern>) {*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]")<Base>;
`

[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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]")<Pattern>)template<bool Const>struct lazy_split_view<V, Pattern>::*outer-iterator*<Const>::value_type : view_interface<value_type> {private:*outer-iterator* *i_* = *outer-iterator*(); // *exposition only*constexpr explicit value_type(*outer-iterator* i); // *exposition only*public:constexpr *inner-iterator*<Const> 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<Const> 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*<Const>{*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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> || [*tiny-range*](#concept:tiny-range "25.7.16.2 Class template lazy_­split_­view [range.lazy.split.view]")<Pattern>)template<bool Const>struct lazy_split_view<V, Pattern>::*inner-iterator* {private:using *Base* = *maybe-const*<Const, V>; // *exposition only**outer-iterator*<Const> *i_* = *outer-iterator*<Const>(); // *exposition only*bool *incremented_* = false; // *exposition only*public:using iterator_concept = typename *outer-iterator*<Const>::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*<Const> 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]")<V>; 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]")<iterator_t<*Base*>>; };}

[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_t<*Base*>>​::​iterator_category models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")<forward_iterator_tag>;

- [(1.2)](#range.lazy.split.inner-1.2)

otherwise, iterator_traits<iterator_t<*Base*>>​::​iterator_category[.](#range.lazy.split.inner-1.sentence-2)

[ð](#lib:lazy_split_view::inner-iterator,constructor)

`constexpr explicit inner-iterator(outer-iterator<Const> 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>& 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> base() && requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V>;
`

[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]")<Base>;
`

[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]")<Pattern>) {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]")<iterator_t<Base>>;
`

[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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>class split_view : public view_interface<split_view<V, Pattern>> {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]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pattern> = 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]")<V, views::all_t<R>> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<Pattern, single_view<range_value_t<R>>>constexpr explicit split_view(R&& r, range_value_t<R> e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V>) {return *iterator*{*this, ranges::end(*base_*), {}}; } else {return *sentinel*{*this}; }}constexpr subrange<iterator_t<V>> *find-next*(iterator_t<V>); // *exposition only*}; template<class R, class P> split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>; template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R> split_view(R&&, range_value_t<R>)-> split_view<views::all_t<R>, single_view<range_value_t<R>>>;}

[ð](#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]")<V, views::all_t<R>> &&
           [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<Pattern, single_view<range_value_t<R>>>
constexpr explicit split_view(R&& r, range_value_t<R> 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>(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<iterator_t<V>> find-next(iterator_t<V> 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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>class split_view<V, Pattern>::*iterator* {private: split_view* *parent_* = nullptr; // *exposition only* iterator_t<V> *cur_* = iterator_t<V>(); // *exposition only* subrange<iterator_t<V>> *next_* = subrange<iterator_t<V>>(); // *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<iterator_t<V>>; using difference_type = range_difference_t<V>; *iterator*() = default; constexpr *iterator*(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next); constexpr iterator_t<V> 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<V> current, subrange<iterator_t<V>> 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<V> 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]")<V> && [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]")<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>struct split_view<V, Pattern>::*sentinel* {private: sentinel_t<V> *end_* = sentinel_t<V>(); // *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<int> 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 {template<class... Rs>using *concat-reference-t* = common_reference_t<range_reference_t<Rs>...>; // *exposition only*template<class... Rs>using *concat-value-t* = common_type_t<range_value_t<Rs>...>; // *exposition only*template<class... Rs>using *concat-rvalue-reference-t* = // *exposition only* common_reference_t<range_rvalue_reference_t<Rs>...>; template<class... Rs>concept [*concat-indirectly-readable*](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]") = *see below*; // *exposition only*template<class... Rs>concept [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]") = *see below*; // *exposition only*template<bool Const, class... Rs>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*template<bool Const, class... Rs>concept [*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]")<Views> && ...) && (sizeof...(Views) > 0) &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<Views...>class concat_view : public view_interface<concat_view<Views...>> { tuple<Views...> *views_*; // *exposition only*// [[range.concat.iterator]](#range.concat.iterator "25.7.18.3 Class concat_­view​::​iterator"), class template concat_view​::​*iterator*template<bool> class *iterator*; // *exposition only*public:constexpr concat_view() = default; constexpr explicit concat_view(Views... views); constexpr *iterator*<false> begin() requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Views> && ...)); constexpr *iterator*<true> begin() constrequires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Views> && ...) && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<const Views...>; constexpr auto end() requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Views> && ...)); constexpr auto end() constrequires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Views> && ...) && [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<const Views...>; constexpr auto size() requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<Views> && ...); constexpr auto size() const requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const Views> && ...); }; template<class... R> concat_view(R&&...) -> concat_view<views::all_t<R>...>;}

[ð](#concept:concat-indirectly-readable)

`template<class... Rs>
  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:template<class Ref, class RRef, class It>concept [*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]")<Ref>; { ranges::iter_move(it) } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<RRef>; };

template<class... Rs>concept [*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*<Rs...>&&, *concat-value-t*<Rs...>&> &&[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<*concat-reference-t*<Rs...>&&, *concat-rvalue-reference-t*<Rs...>&&> &&[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")<*concat-rvalue-reference-t*<Rs...>&&, *concat-value-t*<Rs...> const&> &&([*concat-indirectly-readable-impl*](#concept:concat-indirectly-readable-impl "25.7.18.2 Class template concat_­view [range.concat.view]")<*concat-reference-t*<Rs...>, *concat-rvalue-reference-t*<Rs...>,
 iterator_t<Rs>> && ...);

[ð](#concept:concatable)

`template<class... Rs>
  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:template<class... Rs>concept [*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]") = requires { // *exposition only*typename *concat-reference-t*<Rs...>; typename *concat-value-t*<Rs...>; typename *concat-rvalue-reference-t*<Rs...>; } && [*concat-indirectly-readable*](#concept:concat-indirectly-readable "25.7.18.2 Class template concat_­view [range.concat.view]")<Rs...>;

[ð](#concept:concat-is-random-access)

`template<bool Const, class... Rs>
  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:template<bool Const, class... Rs>concept [*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]")<Const, Rs...> &&([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, Fs>> && ...);

[ð](#concept:concat-is-bidirectional)

`template<bool Const, class... Rs>
  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:template<bool Const, class... Rs>concept [*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]")<Const, Rs...> &&([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, Fs>> && ...);

[ð](#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<false> begin() requires (!([simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Views> && ...));
constexpr iterator<true> begin() const
  requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Views> && ...) && [concatable](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<const Views...>;
`

[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]")<Views> && ...));
constexpr auto end() const
  requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Views> && ...) && [concatable](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<const Views...>;
`

[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<N - 1>,
 ranges::end(std::get<N - 1>(*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]")<Views> && ...);
constexpr auto size() const requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const Views> && ...);
`

[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*<common_type_t<decltype(sizes)...>>; 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]")<Views> && ...) && (sizeof...(Views) > 0) &&[*concatable*](#concept:concatable "25.7.18.2 Class template concat_­view [range.concat.view]")<Views...>template<bool Const>class concat_view<Views...>::*iterator* {public:using iterator_category = *see below*; // not always presentusing iterator_concept = *see below*; using value_type = *concat-value-t*<*maybe-const*<Const, Views>...>; using difference_type = common_type_t<range_difference_t<*maybe-const*<Const, Views>>...>; private:using *base-iter* = // *exposition only* variant<iterator_t<*maybe-const*<Const, Views>>...>; *maybe-const*<Const, concat_view>* *parent_* = nullptr; // *exposition only**base-iter* *it_*; // *exposition only*template<size_t N>constexpr void *satisfy*(); // *exposition only*template<size_t N>constexpr void *prev*(); // *exposition only*template<size_t N>constexpr void *advance-fwd*(difference_type offset, // *exposition only* difference_type steps); template<size_t N>constexpr void *advance-bwd*(difference_type offset, // *exposition only* difference_type steps); template<class... Args>constexpr explicit *iterator*(*maybe-const*<Const, concat_view>* 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*<!Const> i)requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Views>, iterator_t<const Views>> && ...); 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]")<Const, Views...>; constexpr *iterator*& operator--()requires [*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]")<Const, Views...>; constexpr *iterator* operator--(int)requires [*concat-is-bidirectional*](#concept:concat-is-bidirectional "25.7.18.2 Class template concat_­view [range.concat.view]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<iterator_t<*maybe-const*<Const, Views>>> && ...); 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...> &&([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<*maybe-const*<Const, Views>>> && ...)); 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...> 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]")<Const, Views...> 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]")<Const, Views...> 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]")<Const, Views...> 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*<Const, Views>...>> 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_t<*maybe-const*<Const, Views>>>​::​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]")<Cs, random_access_iterator_tag> && ...) && *concat-is-random-access*<Const, Views...> 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]")<Cs, bidirectional_iterator_tag> && ...) && *concat-is-bidirectional*<Const, Views...> 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]")<Cs, forward_iterator_tag> && ...) 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<size_t N>
  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<N>(*it_*) == ranges::end(std::get<N>(*parent_*->*views_*))) {*it_*.template emplace<N + 1>(ranges::begin(std::get<N + 1>(*parent_*->*views_*))); *satisfy*<N + 1>(); }}

[ð](#lib:prev,concat_view::iterator)

`template<size_t N>
  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<N>(*it_*) == ranges::begin(std::get<N>(*parent_*->*views_*))) {*it_*.template emplace<N - 1>(ranges::end(std::get<N - 1>(*parent_*->*views_*))); *prev*<N - 1>(); } else {--std::get<N>(*it_*); }}

[ð](#lib:advance-fwd,concat_view::iterator)

`template<size_t N>
  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<variant_alternative_t<N, *base-iter*>>;if constexpr (N == sizeof...(Views) - 1) { std::get<N>(*it_*) += static_cast<underlying_diff_type>(steps);} else {auto n_size = ranges::distance(std::get<N>(*parent_*->*views_*)); if (offset + steps < n_size) { std::get<N>(*it_*) += static_cast<underlying_diff_type>(steps); } else {*it_*.template emplace<N + 1>(ranges::begin(std::get<N + 1>(*parent_*->*views_*))); *advance-fwd*<N + 1>(0, offset + steps - n_size); }}

[ð](#lib:advance-bwd,concat_view::iterator)

`template<size_t N>
  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<variant_alternative_t<N, *base-iter*>>;if constexpr (N == 0) { std::get<N>(*it_*) -= static_cast<underlying_diff_type>(steps);} else {if (offset >= steps) { std::get<N>(*it_*) -= static_cast<underlying_diff_type>(steps); } else {auto prev_size = ranges::distance(std::get<N - 1>(*parent_*->*views_*)); *it_*.template emplace<N - 1>(ranges::end(std::get<N - 1>(*parent_*->*views_*))); *advance-bwd*<N - 1>(prev_size, steps - offset); }}

[ð](#lib:concat_view::iterator,constructor)

`template<class... Args>
  constexpr explicit iterator(maybe-const<Const, concat_view>* parent,
                              Args&&... args)
    requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<base-iter, Args&&...>;
`

[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>(args)...[.](#range.concat.iterator-7.sentence-1)

[ð](#lib:concat_view::iterator,constructor_)

`constexpr iterator(iterator<!Const> it)
  requires Const &&
           ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Views>, iterator_t<const Views>> && ...);
`

[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<i>, std​::​get<i>(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*<Const, Views>...>;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<i>(*it_*);*satisfy*<i>();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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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*<i>();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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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*<i>(std::get<i>(*it_*) - ranges::begin(std::get<i>(*parent_*->*views_*)), n);} else if (n < 0) {*advance-bwd*<i>(std::get<i>(*it_*) - ranges::begin(std::get<i>(*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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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]")<iterator_t<maybe-const<Const, Views>>> && ...);
`

[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<last_idx>(it.*it_*) == ranges::end(std::get<last_idx>(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]")<Const, Views...>;
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]")<Const, Views...>;
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]")<Const, Views...>;
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]")<Const, Views...>;
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]")<Const, Views...> &&
            ([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<maybe-const<Const, Views>>> && ...));
`

[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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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<iy>(y.*it_*), ranges​::​end(std​::​get<iy>(y.*parent_*->*views_*))),dx beranges​::​distance(ranges​::​begin(std​::​get<ix>(x.*parent_*->*views_*)), std​::​get<ix>(x.*it_*)). Let s denote the sum of the sizes of all the rangesstd​::​get<i>(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<ix>(x.*it_*) - std::get<iy>(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<ix>(x.*it_*), ranges​::​end(std​::​get<ix>(x.*parent_*->*views_*)))[.](#range.concat.iterator-36.sentence-1)

Let s denote the sum of the sizes of all the rangesstd​::​get<i>(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]")<sentinel_t<*maybe-const*<Const, Views>>,
 iterator_t<*maybe-const*<Const, Views>>> && ...) &&([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*<Const, Fs>> && ...)

[ð](#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]")<sentinel_t<*maybe-const*<Const, Views>>,
 iterator_t<*maybe-const*<Const, Views>>> && ...) &&([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*<Const, Fs>> && ...)

[ð](#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*<Const, Views>...> {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<decltype(ranges::iter_move), const iterator_t<*maybe-const*<Const, Views>>&> && is_nothrow_convertible_v<range_rvalue_reference_t<*maybe-const*<Const, Views>>, *concat-rvalue-reference-t*<*maybe-const*<Const, Views>...>>) &&...)

[ð](#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<decltype(it1), decltype(it2)>) { 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*<Const, Views>> 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*>, iter_reference_t<*iterator*>> &&(... && [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<iterator_t<*maybe-const*<Const, Views>>>)

### [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<decltype((E))>, and
let D be iter_difference_t<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]")<D>,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<size_t>(static_cast<D>(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<D>(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<class ForwardIterator> 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]")<V> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<iterator_t<V>>)class common_view : public view_interface<common_view<V>> {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]")<V> = 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]")<V> { 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]")<V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>)return ranges::begin(*base_*); elsereturn common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>)return ranges::begin(*base_*); elsereturn common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>)return ranges::begin(*base_*) + ranges::distance(*base_*); elsereturn common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(*base_*)); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>)return ranges::begin(*base_*) + ranges::distance(*base_*); elsereturn common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(*base_*)); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> {return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V> {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]")<V> {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]")<const V> {return ranges::reserve_hint(*base_*); }}; template<class R> common_view(R&&) -> common_view<views::all_t<R>>;}

[ð](#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<I>, reverse_iterator<I>, 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<I, I, K>(E.end().base(), E.begin().base(), E.size());

  * [(2.2.2)](#range.reverse.overview-2.2.2)

otherwise, subrange<I, I, K>(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<int> 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]")<V>class reverse_view : public view_interface<reverse_view<V>> {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]")<V> = 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]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr reverse_iterator<iterator_t<V>> begin(); constexpr reverse_iterator<iterator_t<V>> begin() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>; constexpr auto begin() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>; constexpr reverse_iterator<iterator_t<V>> end(); constexpr auto end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>; constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> {return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V> {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]")<V> {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]")<const V> {return ranges::reserve_hint(*base_*); }}; template<class R> reverse_view(R&&) -> reverse_view<views::all_t<R>>;}

[ð](#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<iterator_t<V>> 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<iterator_t<V>> begin() requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>;
constexpr auto begin() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>;
`

[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<iterator_t<V>> end();
constexpr auto end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>;
`

[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<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<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<X> for some type X, then auto(views​::​empty<const X>)[.](#range.as.const.overview-2.2.sentence-1)

- [(2.3)](#range.as.const.overview-2.3)

  Otherwise,
if U denotes span<X, Extent> for some type X and some extent Extent,
then span<const X, Extent>(E)[.](#range.as.const.overview-2.3.sentence-1)

- [(2.4)](#range.as.const.overview-2.4)

  Otherwise,
if U denotes ref_view<X> 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<const X&>(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<const U&>(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<char> hammer = {'m', 'c'};
span<char> 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]")<V>class as_const_view : public view_interface<as_const_view<V>> { 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]")<V> = 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]")<V> { 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]")<V>) { return ranges::cbegin(*base_*); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> { return ranges::cbegin(*base_*); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>) { return ranges::cend(*base_*); }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> { return ranges::cend(*base_*); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> { return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V> { 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]")<V>{ 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]")<const V>{ return ranges::reserve_hint(*base_*); }}; template<class R> as_const_view(R&&) -> as_const_view<views::all_t<R>>;}

[ð](#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<N> 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<N>(E) is expression-equivalent toelements_view<views​::​all_t<decltype((E))>, 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<R, 0>, 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<R, 1>, 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 {template<class T, size_t N>concept [*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]")<T> && N < tuple_size_v<T>; template<class T, size_t N>concept [*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]") = // *exposition only* is_reference_v<T> || [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")<tuple_element_t<N, T>>; 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]")<V> && [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")<range_value_t<V>, N> &&[*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")<remove_reference_t<range_reference_t<V>>, N> &&[*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]")<range_reference_t<V>, N>class elements_view : public view_interface<elements_view<V, N>> {public: elements_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<V> = 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]")<V> { 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]")<V>){ return *iterator*<false>(ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>{ return *iterator*<true>(ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && ![common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>){ return *sentinel*<false>{ranges::end(*base_*)}; }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>){ return *iterator*<false>{ranges::end(*base_*)}; }constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>{ return *sentinel*<true>{ranges::end(*base_*)}; }constexpr auto end() const requires [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>{ return *iterator*<true>{ranges::end(*base_*)}; }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>{ return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>{ 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]")<V>{ 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]")<const V>{ 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<bool> 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<bool> 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]")<V> && [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")<range_value_t<V>, N> &&[*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")<remove_reference_t<range_reference_t<V>>, N> &&[*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]")<range_reference_t<V>, N>template<bool Const>class elements_view<V, N>::*iterator* {using *Base* = *maybe-const*<Const, V>; // *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<tuple_element_t<N, range_value_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]")<iterator_t<*Base*>> = default; constexpr explicit *iterator*(iterator_t<*Base*> current); constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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]")<iterator_t<*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 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]")<iterator_t<*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 *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*>, 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_t<*Base*>>​::​iterator_category[.](#range.elements.iterator-2.sentence-2)

- [(2.1)](#range.elements.iterator-2.1)

  If std​::​get<N>(**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]")<random_access_iterator_tag>,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<Base>& 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<range_reference_t<*Base*>>) {return std::get<N>(*i);} else {using E = remove_cv_t<tuple_element_t<N, range_reference_t<*Base*>>>; return static_cast<E>(std::get<N>(*i));}

[ð](#lib:elements_view::iterator,constructor)

`constexpr explicit iterator(iterator_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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>& 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> 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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<Base>>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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<Base>, iterator_t<Base>>;
`

[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]")<V> && [*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")<range_value_t<V>, N> &&[*has-tuple-element*](#concept:has-tuple-element "25.7.23.2 Class template elements_­view [range.elements.view]")<remove_reference_t<range_reference_t<V>>, N> &&[*returnable-element*](#concept:returnable-element "25.7.23.2 Class template elements_­view [range.elements.view]")<range_reference_t<V>, N>template<bool Const>class elements_view<V, N>::*sentinel* {private:using *Base* = *maybe-const*<Const, V>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel*<!Const> other)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *sentinel*& x, const *iterator*<OtherConst>& y); };}

[ð](#lib:elements_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<Base> 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<!Const> other)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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> 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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const sentinel& x, const iterator<OtherConst>& 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<views​::​all_t<decltype((E))>>(E)[.](#range.enumerate.overview-2.sentence-2)

[*Example [1](#range.enumerate.overview-example-1)*: vector<int> 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]")<V>class enumerate_view : public view_interface<enumerate_view<V>> { 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*template<bool Const>class *iterator*; // *exposition only*// [[range.enumerate.sentinel]](#range.enumerate.sentinel "25.7.24.4 Class template enumerate_­view​::​sentinel"), class template enumerate_view​::​*sentinel*template<bool Const>class *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]")<V> = 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]")<V>){ return *iterator*<false>(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]")<const V>{ return *iterator*<true>(ranges::begin(*base_*), 0); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>) {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>)return *iterator*<false>(ranges::end(*base_*), ranges::distance(*base_*)); elsereturn *sentinel*<false>(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]")<const V> {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>)return *iterator*<true>(ranges::end(*base_*), ranges::distance(*base_*)); elsereturn *sentinel*<true>(ranges::end(*base_*)); }constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>{ return ranges::size(*base_*); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>{ 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]")<V>{ 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]")<const V>{ 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]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }}; template<class R> enumerate_view(R&&) -> enumerate_view<views::all_t<R>>;}

[ð](#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]")<V>template<bool Const>class enumerate_view<V>::*iterator* {using *Base* = *maybe-const*<Const, V>; // *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<difference_type, range_value_t<*Base*>>; private:using *reference-type* = // *exposition only* tuple<difference_type, range_reference_t<*Base*>>;
 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]")<iterator_t<*Base*>> = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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<range_rvalue_reference_t<*Base*>>) {return tuple<difference_type,
 range_rvalue_reference_t<*Base*>>(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<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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>& 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> 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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<V>template<bool Const>class enumerate_view<V>::*sentinel* {using *Base* = *maybe-const*<Const, V>; // *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*<!Const> other)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *sentinel*& x, const *iterator*<OtherConst>& y); };}

[ð](#lib:enumerate_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<Base> 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<!Const> other)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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> 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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const sentinel& x, const iterator<OtherConst>& 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<tuple<>>) if Es is an empty pack,

- [(2.2)](#range.zip.overview-2.2)

otherwise, zip_view<views​::​all_t<decltype((Es))>...>(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<decltype(z)> f = z.front(); // f is a tuple<int&, char&>// 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 {template<class... Rs>concept [*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]")<Rs> && ...)) ||(!([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<Rs> && ...) && ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<Rs> && ...)) ||(([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Rs> && ...) && ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<Rs> && ...)); 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]")<Views> && ...) && (sizeof...(Views) > 0)class zip_view : public view_interface<zip_view<Views...>> { tuple<Views...> *views_*; // *exposition only*// [[range.zip.iterator]](#range.zip.iterator "25.7.25.3 Class template zip_­view​::​iterator"), class template zip_view​::​*iterator*template<bool> 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<bool> 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]")<Views> && ...)) {return *iterator*<false>(*tuple-transform*(ranges::begin, *views_*)); }constexpr auto begin() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Views> && ...) {return *iterator*<true>(*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]")<Views> && ...)) {if constexpr (![*zip-is-common*](#concept:zip-is-common "25.7.25.2 Class template zip_­view [range.zip.view]")<Views...>) {return *sentinel*<false>(*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]")<Views> && ...)) {return begin() + iter_difference_t<*iterator*<false>>(size()); } else {return *iterator*<false>(*tuple-transform*(ranges::end, *views_*)); }}constexpr auto end() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Views> && ...) {if constexpr (![*zip-is-common*](#concept:zip-is-common "25.7.25.2 Class template zip_­view [range.zip.view]")<const Views...>) {return *sentinel*<true>(*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]")<const Views> && ...)) {return begin() + iter_difference_t<*iterator*<true>>(size()); } else {return *iterator*<true>(*tuple-transform*(ranges::end, *views_*)); }}constexpr auto size() requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<Views> && ...); constexpr auto size() const requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const Views> && ...); }; template<class... Rs> zip_view(Rs&&...) -> zip_view<views::all_t<Rs>...>;}

[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]")<Views> && ...);
constexpr auto size() const requires ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const Views> && ...);
`

[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*<common_type_t<decltype(sizes)...>>; 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]")<Views> && ...) && (sizeof...(Views) > 0)template<bool Const>class zip_view<Views...>::*iterator* { tuple<iterator_t<*maybe-const*<Const, Views>>...> *current_*; // *exposition only*constexpr explicit *iterator*(tuple<iterator_t<*maybe-const*<Const, Views>>...>); // *exposition only*public:using iterator_category = input_iterator_tag; // not always presentusing iterator_concept = *see below*; using value_type = tuple<range_value_t<*maybe-const*<Const, Views>>...>; using difference_type = common_type_t<range_difference_t<*maybe-const*<Const, Views>>...>; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Views>, iterator_t<const Views>> && ...); 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]")<Const, Views...>; constexpr *iterator*& operator--() requires [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, Views...>; constexpr *iterator* operator--(int) requires [*all-bidirectional*](#concept:all-bidirectional "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, Views...>; constexpr *iterator*& operator+=(difference_type x)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, Views...>; constexpr *iterator*& operator-=(difference_type x)requires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, Views...>; constexpr auto operator[](difference_type n) constrequires [*all-random-access*](#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, Views...>; 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]")<iterator_t<*maybe-const*<Const, Views>>> && ...); 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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]")<Const, Views...>; 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*<Const, Views>>,
 iterator_t<*maybe-const*<Const, Views>>> && ...); 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]")<iterator_t<*maybe-const*<Const, Views>>> && ...); };}

[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]")<Const, Views...> 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]")<Const, Views...> 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]")<Const, Views...> 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]")<Const, Views...> 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<iterator_t<maybe-const<Const, Views>>...> 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<!Const> i)
  requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Views>, iterator_t<const Views>> && ...);
`

[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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[12](#range.zip.iterator-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11684)

*Effects*: Equivalent to:*tuple-for-each*([&]<class I>(I& i) { i += iter_difference_t<I>(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]")<Const, Views...>;
`

[13](#range.zip.iterator-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11700)

*Effects*: Equivalent to:*tuple-for-each*([&]<class I>(I& i) { i -= iter_difference_t<I>(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]")<Const, Views...>;
`

[14](#range.zip.iterator-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11716)

*Effects*: Equivalent to:return *tuple-transform*([&]<class I>(I& i) -> decltype(auto) {return i[iter_difference_t<I>(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]")<iterator_t<maybe-const<Const, Views>>> && ...);
`

[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]")<Const, Views...> 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<sizeof...(Views) such that bool(std​::​​get<i>(x.*current_*) == std​::​get<i>(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]")<Const, Views...>;
`

[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]")<Const, Views...>;
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]")<Const, Views...>;
`

[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]")<Const, Views...>;
`

[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<maybe-const<Const, Views>>,
                               iterator_t<maybe-const<Const, Views>>> && ...);
`

[19](#range.zip.iterator-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11809)

Let *DIST*(i) be difference_type(std​::​get<i>(x.*current_*) - std​::​get<i>(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<sizeof...(Views)[.](#range.zip.iterator-20.sentence-1)

[ð](#lib:iter_move,izip_view::iterator)

`friend constexpr auto iter_move(const iterator& i) noexcept(see below);
`

[21](#range.zip.iterator-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11824)

*Effects*: Equivalent to:return *tuple-transform*(ranges::iter_move, i.*current_*);

[22](#range.zip.iterator-22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11831)

*Remarks*: The exception specification is equivalent to:(noexcept(ranges::iter_move(declval<const iterator_t<*maybe-const*<Const,
 Views>>&>())) && ...) &&(is_nothrow_move_constructible_v<range_rvalue_reference_t<*maybe-const*<Const,
 Views>>> && ...)

[ð](#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]")<iterator_t<maybe-const<Const, Views>>> && ...);
`

[23](#range.zip.iterator-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L11849)

*Effects*: For every integer 0â¤i<sizeof...(Views),
performs:ranges::iter_swap(std::get<i>(l.*current_*), std::get<i>(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<i>(l.*current_*), std::get<i>(r.*current_*))) for every integer 0â¤i<sizeof...(Views)[.](#range.zip.iterator-24.sentence-1)

#### [25.7.25.4](#range.zip.sentinel) Class template zip_view​::​*sentinel* [[range.zip.sentinel]](range.zip.sentinel)

[ð](#lib:zip_view::sentinel)

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]")<Views> && ...) && (sizeof...(Views) > 0)template<bool Const>class zip_view<Views...>::*sentinel* { tuple<sentinel_t<*maybe-const*<Const, Views>>...> *end_*; // *exposition only*constexpr explicit *sentinel*(tuple<sentinel_t<*maybe-const*<Const, Views>>...> end); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel*<!Const> i)requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<Views>, sentinel_t<const Views>> && ...); template<bool OtherConst>requires ([sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*maybe-const*<Const, Views>>,
 iterator_t<*maybe-const*<OtherConst, Views>>> && ...)friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*maybe-const*<Const, Views>>,
 iterator_t<*maybe-const*<OtherConst, Views>>> && ...)friend constexpr common_type_t<range_difference_t<*maybe-const*<OtherConst, Views>>...>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*maybe-const*<Const, Views>>,
 iterator_t<*maybe-const*<OtherConst, Views>>> && ...)friend constexpr common_type_t<range_difference_t<*maybe-const*<OtherConst, Views>>...>operator-(const *sentinel*& y, const *iterator*<OtherConst>& x); };}

[ð](#lib:zip_view::sentinel,constructor)

`constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> 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<!Const> i)
  requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<Views>, sentinel_t<const Views>> && ...);
`

[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<bool OtherConst>
  requires ([sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<maybe-const<Const, Views>>,
                         iterator_t<maybe-const<OtherConst, Views>>> && ...)
friend constexpr bool operator==(const iterator<OtherConst>& 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<sizeof...(Views) such that bool(std​::​get<i>(x.​*current_*) == std​::​get<i>(y.*end_*)) is true[.](#range.zip.sentinel-3.sentence-1)

Otherwise, false[.](#range.zip.sentinel-3.sentence-2)

[ð](#lib:operator-,zip_view::sentinel)

`template<bool OtherConst>
  requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<maybe-const<Const, Views>>,
                               iterator_t<maybe-const<OtherConst, Views>>> && ...)
friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
  operator-(const iterator<OtherConst>& 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<i>(x.*current_*) - std​::​get<i>(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<sizeof...(Views)[.](#range.zip.sentinel-5.sentence-1)

[ð](#lib:operator-,zip_view::sentinel_)

`template<bool OtherConst>
  requires ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<maybe-const<Const, Views>>,
                               iterator_t<maybe-const<OtherConst, Views>>> && ...)
friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
  operator-(const sentinel& y, const iterator<OtherConst>& 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<decltype((F))>[.](#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]")<FD> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<FD&> is false, or
if decay_t<invoke_result_t<FD&>> 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<decay_t<invoke_result_t<FD&>>>))

- [(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]")<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, range_reference_t<Views>...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, range_reference_t<Views>...>>class zip_transform_view : public view_interface<zip_transform_view<F, Views...>> {*movable-box*<F> *fun_*; // *exposition only* zip_view<Views...> *zip_*; // *exposition only*using *InnerView* = zip_view<Views...>; // *exposition only*template<bool Const>using *ziperator* = iterator_t<*maybe-const*<Const, *InnerView*>>; // *exposition only*template<bool Const>using *zentinel* = sentinel_t<*maybe-const*<Const, *InnerView*>>; // *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<bool> 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<bool> class *sentinel*; // *exposition only*public: zip_transform_view() = default; constexpr explicit zip_transform_view(F fun, Views... views); constexpr auto begin() { return *iterator*<false>(*this, *zip_*.begin()); }constexpr auto begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const *InnerView*> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const Views>...> {return *iterator*<true>(*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*<false>(*this, *zip_*.end()); } else {return *sentinel*<false>(*zip_*.end()); }}constexpr auto end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const *InnerView*> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, range_reference_t<const Views>...> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const *InnerView*>) {return *iterator*<true>(*this, *zip_*.end()); } else {return *sentinel*<true>(*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]")<const *InnerView*> {return *zip_*.size(); }}; template<class F, class... Rs> zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>;}

[ð](#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]")<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, range_reference_t<Views>...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, range_reference_t<Views>...>>template<bool Const>class zip_transform_view<F, Views...>::*iterator* {using *Parent* = *maybe-const*<Const, zip_transform_view>; // *exposition only*using *Base* = *maybe-const*<Const, *InnerView*>; // *exposition only**Parent** *parent_* = nullptr; // *exposition only**ziperator*<Const> *inner_*; // *exposition only*constexpr *iterator*(*Parent*& parent, *ziperator*<Const> inner); // *exposition only*public:using iterator_category = *see below*; // not always presentusing iterator_concept = typename *ziperator*<Const>::iterator_concept; using value_type = remove_cvref_t<invoke_result_t<*maybe-const*<Const, F>&,
 range_reference_t<*maybe-const*<Const, Views>>...>>; using difference_type = range_difference_t<*Base*>; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*ziperator*<false>, *ziperator*<Const>>; 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*<Const>>; 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*<Const>, *ziperator*<Const>>; };}

[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*<Const, F>&, range_reference_t<*maybe-const*<Const, Views>>...> 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_t<*maybe-const*<Const, Views>>>​::​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]")<Cs, random_access_iterator_tag> && ...) 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]")<Cs, bidirectional_iterator_tag> && ...) 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]")<Cs, forward_iterator_tag> && ...) 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<Const> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<ziperator<false>, ziperator<Const>>;
`

[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<Is>(*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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[13](#range.zip.transform.iterator-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12376)

*Effects*: Equivalent to:return apply([&]<class... Is>(const Is&... iters) -> decltype(auto) {return invoke(**parent_*->*fun_*, iters[iter_difference_t<Is>(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]")<ziperator<Const>>;
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>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Const>, ziperator<Const>>;
`

[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]")<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, range_reference_t<Views>...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, range_reference_t<Views>...>>template<bool Const>class zip_transform_view<F, Views...>::*sentinel* {*zentinel*<Const> *inner_*; // *exposition only*constexpr explicit *sentinel*(*zentinel*<Const> inner); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*zentinel*<false>, *zentinel*<Const>>; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<*zentinel*<Const>, *ziperator*<OtherConst>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*zentinel*<Const>, *ziperator*<OtherConst>>friend constexpr range_difference_t<*maybe-const*<OtherConst, *InnerView*>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*zentinel*<Const>, *ziperator*<OtherConst>>friend constexpr range_difference_t<*maybe-const*<OtherConst, *InnerView*>>operator-(const *sentinel*& x, const *iterator*<OtherConst>& y); };}

[ð](#lib:zip_transform_view::sentinel,constructor)

`constexpr explicit sentinel(zentinel<Const> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<zentinel<false>, zentinel<Const>>;
`

[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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<zentinel<Const>, ziperator<OtherConst>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<zentinel<Const>, ziperator<OtherConst>>
friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
  operator-(const iterator<OtherConst>& x, const sentinel& y);
template<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<zentinel<Const>, ziperator<OtherConst>>
friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
  operator-(const sentinel& x, const iterator<OtherConst>& 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<N> 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<N>(E) is expression-equivalent to

- [(2.1)](#range.adjacent.overview-2.1)

((void)E, auto(views​::​empty<tuple<>>)) 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<views​::​all_t<decltype((E))>, 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]")<V> && (N > 0)class adjacent_view : public view_interface<adjacent_view<V, N>> { 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<bool> 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<bool> 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]")<V> = 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]")<V> { 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]")<V>) {return *iterator*<false>(ranges::begin(*base_*), ranges::end(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {return *iterator*<true>(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]")<V>) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>) {return *iterator*<false>(*as-sentinel*{}, ranges::begin(*base_*), ranges::end(*base_*)); } else {return *sentinel*<false>(ranges::end(*base_*)); }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V>) {return *iterator*<true>(*as-sentinel*{}, ranges::begin(*base_*), ranges::end(*base_*)); } else {return *sentinel*<true>(ranges::end(*base_*)); }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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 V>; };}

[ð](#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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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<ST, size_t>;auto sz = static_cast<CT>(ranges::size(*base_*));
sz -= std::min<CT>(sz, N - 1);return static_cast<ST>(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]")<V>;
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 V>;
`

[3](#range.adjacent.view-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12673)

*Effects*: Equivalent to:using DT = range_difference_t<decltype((*base_*))>;using CT = common_type_t<DT, size_t>;auto sz = static_cast<CT>(ranges::reserve_hint(*base_*));
sz -= std::min<CT>(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]")<V> && (N > 0)template<bool Const>class adjacent_view<V, N>::*iterator* {using *Base* = *maybe-const*<Const, V>; // *exposition only* array<iterator_t<*Base*>, N> *current_* = array<iterator_t<*Base*>, 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*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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]")<iterator_t<*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]")<iterator_t<*Base*>, 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]")<iterator_t<*Base*>>; };}

[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<Base> first, sentinel_t<Base> 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<N,*current_*[i] == ranges​::​next(*current_*[i-1], 1, last) is true[.](#range.adjacent.iterator-3.sentence-1)

[ð](#lib:adjacent_view::iterator,constructor_)

`constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base> &&
           [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<Base>>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Base>, iterator_t<Base>>;
`

[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<const iterator_t<*Base*>&>())) && is_nothrow_move_constructible_v<range_rvalue_reference_t<*Base*>>

[ð](#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]")<iterator_t<Base>>;
`

[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<N,
performsranges​::​iter_swap(l.*current_*[i], r.*current_*[i])[.](#range.adjacent.iterator-34.sentence-1)

[35](#range.adjacent.iterator-35)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13115)

*Remarks*: The exception specification is equivalent to:noexcept(ranges::iter_swap(declval<iterator_t<*Base*>>(), declval<iterator_t<*Base*>>()))

#### [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]")<V> && (N > 0)template<bool Const>class adjacent_view<V, N>::*sentinel* {using *Base* = *maybe-const*<Const, V>; // *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*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *sentinel*& y, const *iterator*<OtherConst>& x); };}

[ð](#lib:adjacent_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
  operator-(const sentinel& y, const iterator<OtherConst>& 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<N> 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<N>(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<N>(E, F) is
expression-equivalent toadjacent_transform_view<views​::​all_t<decltype((E))>, decay_t<decltype((F))>, 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]")<V> && (N > 0) && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, *REPEAT*(range_reference_t<V>, N)...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, *REPEAT*(range_reference_t<V>, N)...>>class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {*movable-box*<F> *fun_*; // *exposition only* adjacent_view<V, N> *inner_*; // *exposition only*using *InnerView* = adjacent_view<V, N>; // *exposition only*template<bool Const>using *inner-iterator* = iterator_t<*maybe-const*<Const, *InnerView*>>; // *exposition only*template<bool Const>using *inner-sentinel* = sentinel_t<*maybe-const*<Const, *InnerView*>>; // *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<bool> 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<bool> 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]")<V> { return *inner_*.base(); }constexpr V base() && { return std::move(*inner_*).base(); }constexpr auto begin() {return *iterator*<false>(*this, *inner_*.begin()); }constexpr auto begin() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const *InnerView*> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, *REPEAT*(range_reference_t<const V>, N)...> {return *iterator*<true>(*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*<false>(*this, *inner_*.end()); } else {return *sentinel*<false>(*inner_*.end()); }}constexpr auto end() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const *InnerView*> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<const F&, *REPEAT*(range_reference_t<const V>, N)...> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const *InnerView*>) {return *iterator*<true>(*this, *inner_*.end()); } else {return *sentinel*<true>(*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]")<const *InnerView*> {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]")<const *InnerView*> {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]")<V> && (N > 0) && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, *REPEAT*(range_reference_t<V>, N)...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, *REPEAT*(range_reference_t<V>, N)...>>template<bool Const>class adjacent_transform_view<V, F, N>::*iterator* {using *Parent* = *maybe-const*<Const, adjacent_transform_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only**Parent** *parent_* = nullptr; // *exposition only**inner-iterator*<Const> *inner_*; // *exposition only*constexpr *iterator*(*Parent*& parent, *inner-iterator*<Const> inner); // *exposition only*public:using iterator_category = *see below*; using iterator_concept = typename *inner-iterator*<Const>::iterator_concept; using value_type = remove_cvref_t<invoke_result_t<*maybe-const*<Const, F>&, *REPEAT*(range_reference_t<*Base*>, N)...>>; using difference_type = range_difference_t<*Base*>; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*inner-iterator*<false>, *inner-iterator*<Const>>; 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*<Const>>; 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*<Const>, *inner-iterator*<Const>>; };}

[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*<Const, F>&,*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_t<*Base*>>​::​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]")<C, random_access_iterator_tag> 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]")<C, bidirectional_iterator_tag> 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]")<C, forward_iterator_tag> 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<Const> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<inner-iterator<false>, inner-iterator<Const>>;
`

[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<Is>(*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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<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<Const>>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Const>, inner-iterator<Const>>;
`

[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]")<V> && (N > 0) && is_object_v<F> &&[regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_­invocable [concept.regularinvocable]")<F&, *REPEAT*(range_reference_t<V>, N)...> &&[*can-reference*](iterator.synopsis#concept:can-reference "24.2 Header <iterator>&nbsp;synopsis [iterator.synopsis]")<invoke_result_t<F&, *REPEAT*(range_reference_t<V>, N)...>>template<bool Const>class adjacent_transform_view<V, F, N>::*sentinel* {*inner-sentinel*<Const> *inner_*; // *exposition only*constexpr explicit *sentinel*(*inner-sentinel*<Const> inner); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<*inner-sentinel*<false>, *inner-sentinel*<Const>>; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<*inner-sentinel*<Const>, *inner-iterator*<OtherConst>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*inner-sentinel*<Const>, *inner-iterator*<OtherConst>>friend constexpr range_difference_t<*maybe-const*<OtherConst, *InnerView*>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<*inner-sentinel*<Const>, *inner-iterator*<OtherConst>>friend constexpr range_difference_t<*maybe-const*<OtherConst, *InnerView*>>operator-(const *sentinel*& x, const *iterator*<OtherConst>& y); };}

[ð](#lib:adjacent_transform_view::sentinel,constructor)

`constexpr explicit sentinel(inner-sentinel<Const> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<inner-sentinel<false>, inner-sentinel<Const>>;
`

[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<bool OtherConst>
  requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<inner-sentinel<Const>, inner-iterator<OtherConst>>
friend constexpr bool operator==(const iterator<OtherConst>& 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<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<inner-sentinel<Const>, inner-iterator<OtherConst>>
friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
  operator-(const iterator<OtherConst>& x, const sentinel& y);

template<bool OtherConst>
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<inner-sentinel<Const>, inner-iterator<OtherConst>>
friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
  operator-(const sentinel& x, const iterator<OtherConst>& 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 {template<class I>constexpr 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]")<V>class chunk_view : public view_interface<chunk_view<V>> { V *base_*; // *exposition only* range_difference_t<V> *n_*; // *exposition only* range_difference_t<V> *remainder_* = 0; // *exposition only**non-propagating-cache*<iterator_t<V>> *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<V> n); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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 V>; }; template<class R> chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;}

[ð](#lib:chunk_view,constructor)

`constexpr explicit chunk_view(V base, range_difference_t<V> 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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V>;
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 V>;
`

[6](#range.chunk.view.input-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13920)

*Effects*: Equivalent to:auto s = static_cast<range_difference_t<decltype((*base_*))>>(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]")<V>class chunk_view<V>::*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<V>; // [[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]")<sentinel_t<V>, iterator_t<V>>; 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]")<sentinel_t<V>, iterator_t<V>>; };}

[ð](#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]")<sentinel_t<V>, iterator_t<V>>;
`

[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]")<sentinel_t<V>, iterator_t<V>>;
`

[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]")<V>struct chunk_view<V>::*outer-iterator*::value_type : view_interface<value_type> {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]")<sentinel_t<V>, iterator_t<V>>; 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]")<sentinel_t<V>, iterator_t<V>>;
`

[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]")<V>class chunk_view<V>::*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<V>; using value_type = range_value_t<V>; *inner-iterator*(*inner-iterator*&&) = default; *inner-iterator*& operator=(*inner-iterator*&&) = default; constexpr const iterator_t<V>& base() const &; constexpr range_reference_t<V> 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]")<sentinel_t<V>, iterator_t<V>>; 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]")<sentinel_t<V>, iterator_t<V>>; friend constexpr range_rvalue_reference_t<V> 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]")<iterator_t<V>>; };}

[ð](#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<V>& 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<V> 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]")<sentinel_t<V>, iterator_t<V>>;
`

[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]")<sentinel_t<V>, iterator_t<V>>;
`

[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<V> 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]")<iterator_t<V>>;
`

[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]")<V>class chunk_view<V> : public view_interface<chunk_view<V>> { V *base_*; // *exposition only* range_difference_t<V> *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<bool> class *iterator*; // *exposition only*public:constexpr explicit chunk_view(V base, range_difference_t<V> n); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V>) {return *iterator*<false>(this, ranges::begin(*base_*)); }constexpr auto begin() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> {return *iterator*<true>(this, ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>) {auto missing = (*n_* - ranges::distance(*base_*) % *n_*) % *n_*; return *iterator*<false>(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>) {return *iterator*<false>(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]")<const V> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>) {auto missing = (*n_* - ranges::distance(*base_*) % *n_*) % *n_*; return *iterator*<true>(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<const V>) {return *iterator*<true>(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]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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 V>; };}

[ð](#lib:chunk_view,constructor_)

`constexpr explicit chunk_view(V base, range_difference_t<V> 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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V>;
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 V>;
`

[4](#range.chunk.view.fwd-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L14432)

*Effects*: Equivalent to:auto s = static_cast<range_difference_t<decltype((*base_*))>>(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]")<V>template<bool Const>class chunk_view<V>::*iterator* {using *Parent* = *maybe-const*<Const, chunk_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *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*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<*Base*>>&& [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, 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]")<iterator_t<*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]")<iterator_t<*Base*>, 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]")<sentinel_t<*Base*>, 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]")<sentinel_t<*Base*>, 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<Base> current,
                   range_difference_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>
                 && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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> 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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base> &&
           [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<Base>>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Base>, iterator_t<Base>>;
`

[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]")<sentinel_t<Base>, iterator_t<Base>>;
`

[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]")<sentinel_t<Base>, iterator_t<Base>>;
`

[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 {template<class V>concept [*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]")<V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>; // *exposition only*template<class V>concept [*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]")<V> && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V>; template<class V>concept [*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]")<V> && ![*slide-caches-last*](#concept:slide-caches-last "25.7.30.2 Class template slide_­view [range.slide.view]")<V>; 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]")<V>class slide_view : public view_interface<slide_view<V>> { V *base_*; // *exposition only* range_difference_t<V> *n_*; // *exposition only*// [[range.slide.iterator]](#range.slide.iterator "25.7.30.3 Class template slide_­view​::​iterator"), class template slide_view​::​*iterator*template<bool> 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<V> n); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { 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]")<V> && [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]")<const V>)); constexpr auto begin() const requires [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]")<const V>; constexpr auto end()requires (!([*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]")<const V>)); constexpr auto end() const requires [*slide-caches-nothing*](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]")<const V>; constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hintsize() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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]")<const V>; }; template<class R> slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>;}

[ð](#lib:slide_view,constructor_)

`constexpr explicit slide_view(V base, range_difference_t<V> 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]")<V> && [slide-caches-nothing](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]")<const V>));
`

[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*<false>(ranges::begin(*base_*),
 ranges::next(ranges::begin(*base_*), *n_* - 1, ranges::end(*base_*)), *n_*)

- [(3.2)](#range.slide.view-3.2)

Otherwise, *iterator*<false>(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]")<const V>;
`

[5](#range.slide.view-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15005)

*Returns*: *iterator*<true>(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]")<V> && [slide-caches-nothing](#concept:slide-caches-nothing "25.7.30.2 Class template slide_­view [range.slide.view]")<const V>));
`

[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*<false>(ranges::begin(*base_*) + range_difference_t<V>(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*<false>(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*<false>(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]")<const V>;
`

[8](#range.slide.view-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15054)

*Returns*: begin() + range_difference_t<const V>(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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V>;
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 V>;
`

[10](#range.slide.view-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L15083)

*Effects*: Equivalent to:auto sz = static_cast<range_difference_t<decltype((*base_*))>>(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]")<V>template<bool Const>class slide_view<V>::*iterator* {using *Base* = *maybe-const*<Const, V>; // *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*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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]")<iterator_t<*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]")<iterator_t<*Base*>, 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<Base> current, 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>);
`

[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<Base> current, iterator_t<Base> last_ele,
                   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>;
`

[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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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*<true> 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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base> &&
           [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<Base>>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Base>, iterator_t<Base>>;
`

[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]")<V>class slide_view<V>::*sentinel* { sentinel_t<V> *end_* = sentinel_t<V>(); // *exposition only*constexpr explicit *sentinel*(sentinel_t<V> end); // *exposition only*public:*sentinel*() = default; friend constexpr bool operator==(const *iterator*<false>& x, const *sentinel*& y); friend constexpr range_difference_t<V>operator-(const *iterator*<false>& 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]")<sentinel_t<V>, iterator_t<V>>; friend constexpr range_difference_t<V>operator-(const *sentinel*& y, const *iterator*<false>& x)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>; };}

[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]")<V> is true[.](#range.slide.sentinel-1.sentence-1)

â *end note*]

[ð](#lib:slide_view::sentinel,constructor)

`constexpr explicit sentinel(sentinel_t<V> 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<false>& 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<V>
  operator-(const iterator<false>& 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]")<sentinel_t<V>, iterator_t<V>>;
`

[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<V>
  operator-(const sentinel& y, const iterator<false>& x)
    requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;
`

[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<V>, iterator_t<V>> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && is_object_v<Pred>class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> { V *base_* = V(); // *exposition only**movable-box*<Pred> *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]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]")<Pred> = 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]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr const Pred& pred() const; constexpr *iterator* begin(); constexpr auto end(); constexpr iterator_t<V> *find-next*(iterator_t<V>); // *exposition only*constexpr iterator_t<V> *find-prev*(iterator_t<V>) // *exposition only*requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>; }; template<class R, class Pred> chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, 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]")<V>) {return *iterator*(*this, ranges::end(*base_*), ranges::end(*base_*));} else {return default_sentinel;}

[ð](#lib:find-next,chunk_by_view)

`constexpr iterator_t<V> find-next(iterator_t<V> 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<V> find-prev(iterator_t<V> current) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>;
`

[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<V>, iterator_t<V>> Pred>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && is_object_v<Pred>class chunk_by_view<V, Pred>::*iterator* { chunk_by_view* *parent_* = nullptr; // *exposition only* iterator_t<V> *current_* = iterator_t<V>(); // *exposition only* iterator_t<V> *next_* = iterator_t<V>(); // *exposition only*constexpr *iterator*(chunk_by_view& parent, iterator_t<V> current, // *exposition only* iterator_t<V> next); public:using value_type = subrange<iterator_t<V>>; using difference_type = range_difference_t<V>; 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]")<V>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>; 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<V> current, iterator_t<V> 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]")<V>;
`

[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]")<V>;
`

[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<int>(cout, " ")); // prints 0 3 6 9 ranges::copy(input | views::reverse, ostream_iterator<int>(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]")<V>class stride_view : public view_interface<stride_view<V>> { V *base_*; // *exposition only* range_difference_t<V> *stride_*; // *exposition only*// [[range.stride.iterator]](#range.stride.iterator "25.7.32.3 Class template stride_­view​::​iterator"), class template stride_view​::​*iterator*template<bool> class *iterator*; // *exposition only*public:constexpr explicit stride_view(V base, range_difference_t<V> stride); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr range_difference_t<V> stride() const noexcept; constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>) {return *iterator*<false>(this, ranges::begin(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {return *iterator*<true>(this, ranges::begin(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V>) {auto missing = (*stride_* - ranges::distance(*base_*) % *stride_*) % *stride_*; return *iterator*<false>(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<V>) {return *iterator*<false>(this, ranges::end(*base_*)); } else {return default_sentinel; }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V>) {auto missing = (*stride_* - ranges::distance(*base_*) % *stride_*) % *stride_*; return *iterator*<true>(this, ranges::end(*base_*), missing); } else if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && ![bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<const V>) {return *iterator*<true>(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]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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 V>; }; template<class R> stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;}

[ð](#lib:stride_view,constructor)

`constexpr stride_view(V base, range_difference_t<V> 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<V> 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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V>;
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 V>;
`

[5](#range.stride.view-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16058)

*Effects*: Equivalent to:auto s = static_cast<range_difference_t<decltype((*base_*))>>(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]")<V>template<bool Const>class stride_view<V>::*iterator* {using *Parent* = *maybe-const*<Const, stride_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *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]")<iterator_t<*Base*>> = default; constexpr *iterator*(*iterator*<!Const> other)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<*Base*>>&& [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, 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]")<iterator_t<*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 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]")<iterator_t<*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 *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*>, 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]")<sentinel_t<*Base*>, 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]")<sentinel_t<*Base*>, 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]")<iterator_t<*Base*>>; };}

[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_t<*Base*>>​::​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]")<random_access_iterator_tag>,
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<Base> current,
                   range_difference_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>
                 && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`

[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> 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>& 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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<iterator_t<Base>>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base>;
`

[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]")<Base> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<iterator_t<Base>>;
`

[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]")<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>;
`

[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]")<Base>;
`

[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<Base>, iterator_t<Base>>;
`

[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]")<sentinel_t<Base>, iterator_t<Base>>;
`

[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]")<sentinel_t<Base>, iterator_t<Base>>;
`

[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<Base> 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]")<iterator_t<Base>>;
`

[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<views​::​all_t<decltype((Es))>...>(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<int> 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 {template<bool Const, class First, class... Vs>concept [*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*<Const, First>> && ... &&([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, Vs>>&& [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*<Const, Vs>>)); template<class R>concept [*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]")<R> || ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> && [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<R>); template<bool Const, class First, class... Vs>concept [*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*<Const, First>> && ... &&([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, Vs>>&& [*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")<*maybe-const*<Const, Vs>>)); template<class First, class...>concept [*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]")<First>; template<class... Vs>concept [*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]")<Vs> && ...); template<bool Const, template<class> 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]")<FirstSent<*maybe-const*<Const, First>>,
 iterator_t<*maybe-const*<Const, First>>> && ...&& ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*<Const, Vs>>&& [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*<Const, Vs>>,
 iterator_t<*maybe-const*<Const, Vs>>>)); 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]")<R>) {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]")<First> && ... && [view](range.view#concept:view "25.4.5 Views [range.view]")<Vs>)class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {private: tuple<First, Vs...> *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<bool Const> class *iterator*; // *exposition only*public:constexpr cartesian_product_view() = default; constexpr explicit cartesian_product_view(First first_base, Vs... bases); constexpr *iterator*<false> begin()requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<First> || ... || ![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Vs>); constexpr *iterator*<true> begin() constrequires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const First> && ... && [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Vs>); constexpr *iterator*<false> end()requires ((![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<First> || ... || ![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Vs>) &&[*cartesian-product-is-common*](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")<First, Vs...>); constexpr *iterator*<true> end() constrequires [*cartesian-product-is-common*](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")<const First, const Vs...>; 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]")<First, Vs...>; 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]")<const First, const Vs...>; }; template<class... Vs> cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>;}

[ð](#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<false> begin()
  requires (![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<First> || ... || ![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Vs>);
`

[2](#range.cartesian.view-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16698)

*Effects*: Equivalent to:return *iterator*<false>(*this, *tuple-transform*(ranges::begin, *bases_*));

[ð](#lib:begin,cartesian_product_view_)

`constexpr iterator<true> begin() const
  requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const First> && ... && [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Vs>);
`

[3](#range.cartesian.view-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16713)

*Effects*: Equivalent to:return *iterator*<true>(*this, *tuple-transform*(ranges::begin, *bases_*));

[ð](#lib:end,cartesian_product_view)

`constexpr iterator<false> end()
  requires ((![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<First> || ... || ![simple-view](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Vs>)
    && [cartesian-product-is-common](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")<First, Vs...>);
constexpr iterator<true> end() const
  requires [cartesian-product-is-common](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_­product_­view [range.cartesian.view]")<const First, const Vs...>;
`

[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]")<First, Vs...>;
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]")<const First, const Vs...>;
`

[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]")<First> && ... && [view](range.view#concept:view "25.4.5 Views [range.view]")<Vs>)template<bool Const>class cartesian_product_view<First, Vs...>::*iterator* {public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = tuple<range_value_t<*maybe-const*<Const, First>>,
 range_value_t<*maybe-const*<Const, Vs>>...>; using reference = tuple<range_reference_t<*maybe-const*<Const, First>>,
 range_reference_t<*maybe-const*<Const, Vs>>...>; using difference_type = *see below*; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i) requires Const &&([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<First>, iterator_t<const First>> &&... && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Vs>, iterator_t<const Vs>>); 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*<Const, First>>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<iterator_t<*maybe-const*<Const, First>>>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<Const, First, Vs...>; 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]")<Const, iterator_t, First, Vs...>; 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]")<Const, sentinel_t, First, Vs...>; 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]")<Const, sentinel_t, First, Vs...>; 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]")<iterator_t<*maybe-const*<Const, First>>> && ... &&[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<iterator_t<*maybe-const*<Const, Vs>>>); private:using *Parent* = *maybe-const*<Const, cartesian_product_view>; // *exposition only**Parent** *parent_* = nullptr; // *exposition only* tuple<iterator_t<*maybe-const*<Const, First>>,
 iterator_t<*maybe-const*<Const, Vs>>...> *current_*; // *exposition only*template<size_t N = sizeof...(Vs)>constexpr void *next*(); // *exposition only*template<size_t N = sizeof...(Vs)>constexpr void *prev*(); // *exposition only*template<class Tuple>constexpr difference_type *distance-from*(const Tuple& t) const; // *exposition only*constexpr *iterator*(*Parent*& parent, tuple<iterator_t<*maybe-const*<Const, First>>,
 iterator_t<*maybe-const*<Const, Vs>>...> 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]")<Const, First, Vs...> 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]")<Const, First, Vs...> 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*<Const, First> 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<size_t N = sizeof...(Vs)>
  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<N>(*current_*);++it;if constexpr (N > 0) {if (it == ranges::end(std::get<N>(*parent_*->*bases_*))) { it = ranges::begin(std::get<N>(*parent_*->*bases_*)); *next*<N - 1>(); }}

[ð](#lib:prev,cartesian_product_view)

`template<size_t N = sizeof...(Vs)>
  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<N>(*current_*);if constexpr (N > 0) {if (it == ranges::begin(std::get<N>(*parent_*->*bases_*))) { it = *cartesian-common-arg-end*(std::get<N>(*parent_*->*bases_*)); *prev*<N - 1>(); }}--it;

[ð](#lib:distance-from,cartesian_product_view)

`template<class Tuple>
  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<difference_type>(ranges​::​size(std​::​get<​N>(*parent_*->*bases_*))) andscaled-size(N+1) if N â¤ sizeof...(Vs), otherwise static_cast<difference_type>(1);

- [(6.2)](#range.cartesian.iterator-6.2)

*scaled-distance*(N) be the product ofstatic_cast<difference_type>(std​::​get<N>(*current_*) - std​::​get<N>(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<maybe-const<Const, First>>,
  iterator_t<maybe-const<Const, Vs>>...> 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<!Const> i) requires Const &&
  ([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<First>, iterator_t<const First>> &&
    ... && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<Vs>, iterator_t<const Vs>>);
`

[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]")<maybe-const<Const, First>>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<iterator_t<maybe-const<Const, First>>>;
`

[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<i>(x.*current_*) == ranges​::​end(std​::​get<i>(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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, First, Vs...>;
`

[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]")<Const, iterator_t, First, Vs...>;
`

[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]")<Const, sentinel_t, First, Vs...>;
`

[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<N>(*end-tuple*) has the same value asranges​::​begin(std​::​get<N>(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]")<Const, sentinel_t, First, Vs...>;
`

[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<N>(i.*current_*))) for every integer  
0 â¤ N â¤ sizeof...(Vs),

- [(35.2)](#range.cartesian.iterator-35.2)

is_nothrow_move_constructible_v<range_rvalue_reference_t<*maybe-const*<Const, T>>>  
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]")<iterator_t<maybe-const<Const, First>>> && ... &&
        [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<iterator_t<maybe-const<Const, Vs>>>);
`

[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<i>(l.*current_*), std::get<i>(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<i>(l.*current_*), std​::​get<i>(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]")<V>class [cache_latest_view](#lib:cache_latest_view "25.7.34.2 Class template cache_­latest_­view [range.cache.latest.view]") : public view_interface<cache_latest_view<V>> { V *base_* = V(); // *exposition only*using *cache-t* = conditional_t<is_reference_v<range_reference_t<V>>, // *exposition only* add_pointer_t<range_reference_t<V>>,
 range_reference_t<V>>; *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]")<V> = 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]")<V> { 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]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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 V>; }; template<class R> cache_latest_view(R&&) -> cache_latest_view<views::all_t<R>>;}

[ð](#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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V>;
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 V>;
`

[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]")<V>class cache_latest_view<V>::*iterator* { cache_latest_view* *parent_*; // *exposition only* iterator_t<V> *current_*; // *exposition only*constexpr explicit *iterator*(cache_latest_view& parent); // *exposition only*public:using difference_type = range_difference_t<V>; using value_type = range_value_t<V>; using iterator_concept = input_iterator_tag; *iterator*(*iterator*&&) = default; *iterator*& operator=(*iterator*&&) = default; constexpr iterator_t<V> base() &&; constexpr const iterator_t<V>& base() const & noexcept; constexpr range_reference_t<V>& operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); friend constexpr range_rvalue_reference_t<V> 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]")<iterator_t<V>>; };}

[ð](#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<V> 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<V>& 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<V>& 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<range_reference_t<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<V> 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]")<iterator_t<V>>;
`

[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]")<V>class cache_latest_view<V>::*sentinel* { sentinel_t<V> *end_* = sentinel_t<V>(); // *exposition only*constexpr explicit *sentinel*(cache_latest_view& parent); // *exposition only*public:*sentinel*() = default; constexpr sentinel_t<V> base() const; friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); friend constexpr range_difference_t<V> 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]")<sentinel_t<V>, iterator_t<V>>; friend constexpr range_difference_t<V> 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]")<sentinel_t<V>, iterator_t<V>>; };}

[ð](#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<V> 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<V> 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]")<sentinel_t<V>, iterator_t<V>>;
`

[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<V> 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]")<sentinel_t<V>, iterator_t<V>>;
`

[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]")<V>class to_input_view : public view_interface<to_input_view<V>> { 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<bool Const> 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]")<V> = 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]")<V> { 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]")<V>); constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>; constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V>); constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>; constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; 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 V>; }; template<class R> to_input_view(R&&) -> to_input_view<views::all_t<R>>;}

[ð](#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]")<V>);
`

[2](#range.to.input.view-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17801)

*Effects*: Equivalent to: return *iterator*<false>(ranges​::​begin(*base_*));

[ð](#lib:begin,to_input_view_)

`constexpr auto begin() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>;
`

[3](#range.to.input.view-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17812)

*Effects*: Equivalent to: return *iterator*<true>(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]")<V>);
constexpr auto end() const requires [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const V>;
`

[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]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
`

[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]")<V>;
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 V>;
`

[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]")<V>template<bool Const>class to_input_view<V>::*iterator* {using *Base* = *maybe-const*<Const, V>; // *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]")<iterator_t<*Base*>> = default; *iterator*(*iterator*&&) = default; *iterator*& operator=(*iterator*&&) = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, 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]")<sentinel_t<*Base*>, 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]")<sentinel_t<*Base*>, 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]")<iterator_t<*Base*>>; };}

[ð](#lib:to_input_view::iterator,constructor)

`constexpr explicit iterator(iterator_t<Base> 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<!Const> i)
  requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`

[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> 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>& 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<Base>& 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<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]")<sentinel_t<Base>, iterator_t<Base>>;
`

[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<Base>& y)
  requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<Base>>;
`

[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<Base> 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]")<iterator_t<Base>>;
`

[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_*);
