From Jason Turner

[range.adaptors]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp4d3n8rwt/{from.md → to.md} +3135 -0
tmp/tmp4d3n8rwt/{from.md → to.md} RENAMED
@@ -0,0 +1,3135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Range adaptors <a id="range.adaptors">[[range.adaptors]]</a>
2
+
3
+ This subclause defines *range adaptors*, which are utilities that
4
+ transform a `range` into a `view` with custom behaviors. These adaptors
5
+ can be chained to create pipelines of range transformations that
6
+ evaluate lazily as the resulting view is iterated.
7
+
8
+ Range adaptors are declared in namespace `std::ranges::views`.
9
+
10
+ The bitwise operator is overloaded for the purpose of creating adaptor
11
+ chain pipelines. The adaptors also support function call syntax with
12
+ equivalent semantics.
13
+
14
+ [*Example 1*:
15
+
16
+ ``` cpp
17
+ vector<int> ints{0,1,2,3,4,5};
18
+ auto even = [](int i){ return 0 == i % 2; };
19
+ auto square = [](int i) { return i * i; };
20
+ for (int i : ints | views::filter(even) | views::transform(square)) {
21
+ cout << i << ' '; // prints: 0 4 16
22
+ }
23
+ assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
24
+ ```
25
+
26
+ — *end example*]
27
+
28
+ ### Range adaptor objects <a id="range.adaptor.object">[[range.adaptor.object]]</a>
29
+
30
+ A *range adaptor closure object* is a unary function object that accepts
31
+ a `viewable_range` argument and returns a `view`. For a range adaptor
32
+ closure object `C` and an expression `R` such that `decltype((R))`
33
+ models `viewable_range`, the following expressions are equivalent and
34
+ yield a `view`:
35
+
36
+ ``` cpp
37
+ C(R)
38
+ R | C
39
+ ```
40
+
41
+ Given an additional range adaptor closure object `D`, the expression
42
+ `C | D` is well-formed and produces another range adaptor closure object
43
+ such that the following two expressions are equivalent:
44
+
45
+ ``` cpp
46
+ R | C | D
47
+ R | (C | D)
48
+ ```
49
+
50
+ A *range adaptor object* is a customization point object
51
+ [[customization.point.object]] that accepts a `viewable_range` as its
52
+ first argument and returns a `view`.
53
+
54
+ If a range adaptor object accepts only one argument, then it is a range
55
+ adaptor closure object.
56
+
57
+ If a range adaptor object accepts more than one argument, then the
58
+ following expressions are equivalent:
59
+
60
+ ``` cpp
61
+ adaptor(range, args...)
62
+ adaptor(args...)(range)
63
+ range | adaptor(args...)
64
+ ```
65
+
66
+ In this case, `adaptor(args...)` is a range adaptor closure object.
67
+
68
+ ### Semiregular wrapper <a id="range.semi.wrap">[[range.semi.wrap]]</a>
69
+
70
+ Many types in this subclause are specified in terms of an
71
+ exposition-only class template *`semiregular-box`*. `semiregular-box<T>`
72
+ behaves exactly like `optional<T>` with the following differences:
73
+
74
+ - `semiregular-box<T>` constrains its type parameter `T` with
75
+ `copy_constructible<T> && is_object_v<T>`.
76
+ - If `T` models `default_initializable`, the default constructor of
77
+ `semiregular-box<T>` is equivalent to:
78
+ ``` cpp
79
+ constexpr semiregular-box() noexcept(is_nothrow_default_constructible_v<T>)
80
+ : semiregular-box{in_place}
81
+ { }
82
+ ```
83
+ - If `assignable_from<T&, const T&>` is not modeled, the copy assignment
84
+ operator is equivalent to:
85
+ ``` cpp
86
+ semiregular-box& operator=(const semiregular-box& that)
87
+ noexcept(is_nothrow_copy_constructible_v<T>)
88
+ {
89
+ if (that) emplace(*that);
90
+ else reset();
91
+ return *this;
92
+ }
93
+ ```
94
+ - If `assignable_from<T&, T>` is not modeled, the move assignment
95
+ operator is equivalent to:
96
+ ``` cpp
97
+ semiregular-box& operator=(semiregular-box&& that)
98
+ noexcept(is_nothrow_move_constructible_v<T>)
99
+ {
100
+ if (that) emplace(std::move(*that));
101
+ else reset();
102
+ return *this;
103
+ }
104
+ ```
105
+
106
+ ### All view <a id="range.all">[[range.all]]</a>
107
+
108
+ `views::all` returns a `view` that includes all elements of its `range`
109
+ argument.
110
+
111
+ The name `views::all` denotes a range adaptor object
112
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
113
+ `views::all(E)` is expression-equivalent to:
114
+
115
+ - `decay-copy(E)` if the decayed type of `E` models `view`.
116
+ - Otherwise, `ref_view{E}` if that expression is well-formed.
117
+ - Otherwise, `subrange{E}`.
118
+
119
+ #### Class template `ref_view` <a id="range.ref.view">[[range.ref.view]]</a>
120
+
121
+ `ref_view` is a `view` of the elements of some other `range`.
122
+
123
+ ``` cpp
124
+ namespace std::ranges {
125
+ template<range R>
126
+ requires is_object_v<R>
127
+ class ref_view : public view_interface<ref_view<R>> {
128
+ private:
129
+ R* r_ = nullptr; // exposition only
130
+ public:
131
+ constexpr ref_view() noexcept = default;
132
+
133
+ template<not-same-as<ref_view> T>
134
+ requires see below
135
+ constexpr ref_view(T&& t);
136
+
137
+ constexpr R& base() const { return *r_; }
138
+
139
+ constexpr iterator_t<R> begin() const { return ranges::begin(*r_); }
140
+ constexpr sentinel_t<R> end() const { return ranges::end(*r_); }
141
+
142
+ constexpr bool empty() const
143
+ requires requires { ranges::empty(*r_); }
144
+ { return ranges::empty(*r_); }
145
+
146
+ constexpr auto size() const requires sized_range<R>
147
+ { return ranges::size(*r_); }
148
+
149
+ constexpr auto data() const requires contiguous_range<R>
150
+ { return ranges::data(*r_); }
151
+ };
152
+ template<class R>
153
+ ref_view(R&) -> ref_view<R>;
154
+ }
155
+ ```
156
+
157
+ ``` cpp
158
+ template<not-same-as<ref_view> T>
159
+ requires see below
160
+ constexpr ref_view(T&& t);
161
+ ```
162
+
163
+ *Remarks:* Let *`FUN`* denote the exposition-only functions
164
+
165
+ ``` cpp
166
+ void FUN(R&);
167
+ void FUN(R&&) = delete;
168
+ ```
169
+
170
+ The expression in the *requires-clause* is equivalent to
171
+
172
+ ``` cpp
173
+ convertible_to<T, R&> && requires { FUN(declval<T>()); }
174
+ ```
175
+
176
+ *Effects:* Initializes *r\_* with
177
+ `addressof(static_cast<R&>(std::forward<T>(t)))`.
178
+
179
+ ### Filter view <a id="range.filter">[[range.filter]]</a>
180
+
181
+ #### Overview <a id="range.filter.overview">[[range.filter.overview]]</a>
182
+
183
+ `filter_view` presents a `view` of the elements of an underlying
184
+ sequence that satisfy a predicate.
185
+
186
+ The name `views::filter` denotes a range adaptor object
187
+ [[range.adaptor.object]]. Given subexpressions `E` and `P`, the
188
+ expression `views::filter(E, P)` is expression-equivalent to
189
+ `filter_view{E, P}`.
190
+
191
+ [*Example 1*:
192
+
193
+ ``` cpp
194
+ vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
195
+ filter_view evens{is, [](int i) { return 0 == i % 2; }};
196
+ for (int i : evens)
197
+ cout << i << ' '; // prints: 0 2 4 6
198
+ ```
199
+
200
+ — *end example*]
201
+
202
+ #### Class template `filter_view` <a id="range.filter.view">[[range.filter.view]]</a>
203
+
204
+ ``` cpp
205
+ namespace std::ranges {
206
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
207
+ requires view<V> && is_object_v<Pred>
208
+ class filter_view : public view_interface<filter_view<V, Pred>> {
209
+ private:
210
+ V base_ = V(); // exposition only
211
+ semiregular-box<Pred> pred_; // exposition only
212
+
213
+ // [range.filter.iterator], class filter_view::iterator
214
+ class iterator; // exposition only
215
+ // [range.filter.sentinel], class filter_view::sentinel
216
+ class sentinel; // exposition only
217
+
218
+ public:
219
+ filter_view() = default;
220
+ constexpr filter_view(V base, Pred pred);
221
+
222
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
223
+ constexpr V base() && { return std::move(base_); }
224
+
225
+ constexpr const Pred& pred() const;
226
+
227
+ constexpr iterator begin();
228
+ constexpr auto end() {
229
+ if constexpr (common_range<V>)
230
+ return iterator{*this, ranges::end(base_)};
231
+ else
232
+ return sentinel{*this};
233
+ }
234
+ };
235
+
236
+ template<class R, class Pred>
237
+ filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
238
+ }
239
+ ```
240
+
241
+ ``` cpp
242
+ constexpr filter_view(V base, Pred pred);
243
+ ```
244
+
245
+ *Effects:* Initializes *base\_* with `std::move(base)` and initializes
246
+ *pred\_* with `std::move(pred)`.
247
+
248
+ ``` cpp
249
+ constexpr const Pred& pred() const;
250
+ ```
251
+
252
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
253
+
254
+ ``` cpp
255
+ constexpr iterator begin();
256
+ ```
257
+
258
+ *Preconditions:* `pred_.has_value()`.
259
+
260
+ *Returns:* `{*this, ranges::find_if(`*`base_`*`, ref(*`*`pred_`*`))}`.
261
+
262
+ *Remarks:* In order to provide the amortized constant time complexity
263
+ required by the `range` concept when `filter_view` models
264
+ `forward_range`, this function caches the result within the
265
+ `filter_view` for use on subsequent calls.
266
+
267
+ #### Class `filter_view::iterator` <a id="range.filter.iterator">[[range.filter.iterator]]</a>
268
+
269
+ ``` cpp
270
+ namespace std::ranges {
271
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
272
+ requires view<V> && is_object_v<Pred>
273
+ class filter_view<V, Pred>::iterator {
274
+ private:
275
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only
276
+ filter_view* parent_ = nullptr; // exposition only
277
+ public:
278
+ using iterator_concept = see below;
279
+ using iterator_category = see below;
280
+ using value_type = range_value_t<V>;
281
+ using difference_type = range_difference_t<V>;
282
+
283
+ iterator() = default;
284
+ constexpr iterator(filter_view& parent, iterator_t<V> current);
285
+
286
+ constexpr iterator_t<V> base() const &
287
+ requires copyable<iterator_t<V>>;
288
+ constexpr iterator_t<V> base() &&;
289
+ constexpr range_reference_t<V> operator*() const;
290
+ constexpr iterator_t<V> operator->() const
291
+ requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
292
+
293
+ constexpr iterator& operator++();
294
+ constexpr void operator++(int);
295
+ constexpr iterator operator++(int) requires forward_range<V>;
296
+
297
+ constexpr iterator& operator--() requires bidirectional_range<V>;
298
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
299
+
300
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
301
+ requires equality_comparable<iterator_t<V>>;
302
+
303
+ friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
304
+ noexcept(noexcept(ranges::iter_move(i.current_)));
305
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
306
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
307
+ requires indirectly_swappable<iterator_t<V>>;
308
+ };
309
+ }
310
+ ```
311
+
312
+ Modification of the element a `filter_view::iterator` denotes is
313
+ permitted, but results in undefined behavior if the resulting value does
314
+ not satisfy the filter predicate.
315
+
316
+ `iterator::iterator_concept` is defined as follows:
317
+
318
+ - If `V` models `bidirectional_range`, then `iterator_concept` denotes
319
+ `bidirectional_iterator_tag`.
320
+ - Otherwise, if `V` models `forward_range`, then `iterator_concept`
321
+ denotes `forward_iterator_tag`.
322
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
323
+
324
+ `iterator::iterator_category` is defined as follows:
325
+
326
+ - Let `C` denote the type
327
+ `iterator_traits<iterator_t<V>>::iterator_category`.
328
+ - If `C` models `derived_from<bidirectional_iterator_tag>`, then
329
+ `iterator_category` denotes `bidirectional_iterator_tag`.
330
+ - Otherwise, if `C` models `derived_from<forward_iterator_tag>`, then
331
+ `iterator_category` denotes `forward_iterator_tag`.
332
+ - Otherwise, `iterator_category` denotes `C`.
333
+
334
+ ``` cpp
335
+ constexpr iterator(filter_view& parent, iterator_t<V> current);
336
+ ```
337
+
338
+ *Effects:* Initializes *current\_* with `std::move(current)` and
339
+ *parent\_* with `addressof(parent)`.
340
+
341
+ ``` cpp
342
+ constexpr iterator_t<V> base() const &
343
+ requires copyable<iterator_t<V>>;
344
+ ```
345
+
346
+ *Effects:* Equivalent to: `return `*`current_`*`;`
347
+
348
+ ``` cpp
349
+ constexpr iterator_t<V> base() &&;
350
+ ```
351
+
352
+ *Effects:* Equivalent to: `return std::move(current_);`
353
+
354
+ ``` cpp
355
+ constexpr range_reference_t<V> operator*() const;
356
+ ```
357
+
358
+ *Effects:* Equivalent to: `return *`*`current_`*`;`
359
+
360
+ ``` cpp
361
+ constexpr iterator_t<V> operator->() const
362
+ requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
363
+ ```
364
+
365
+ *Effects:* Equivalent to: `return `*`current_`*`;`
366
+
367
+ ``` cpp
368
+ constexpr iterator& operator++();
369
+ ```
370
+
371
+ *Effects:* Equivalent to:
372
+
373
+ ``` cpp
374
+ current_ = ranges::find_if(std::move(++current_), ranges::end(parent_->base_),
375
+ ref(*parent_->pred_));
376
+ return *this;
377
+ ```
378
+
379
+ ``` cpp
380
+ constexpr void operator++(int);
381
+ ```
382
+
383
+ *Effects:* Equivalent to `++*this`.
384
+
385
+ ``` cpp
386
+ constexpr iterator operator++(int) requires forward_range<V>;
387
+ ```
388
+
389
+ *Effects:* Equivalent to:
390
+
391
+ ``` cpp
392
+ auto tmp = *this;
393
+ ++*this;
394
+ return tmp;
395
+ ```
396
+
397
+ ``` cpp
398
+ constexpr iterator& operator--() requires bidirectional_range<V>;
399
+ ```
400
+
401
+ *Effects:* Equivalent to:
402
+
403
+ ``` cpp
404
+ do
405
+ --current_;
406
+ while (!invoke(*parent_->pred_, *current_));
407
+ return *this;
408
+ ```
409
+
410
+ ``` cpp
411
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
412
+ ```
413
+
414
+ *Effects:* Equivalent to:
415
+
416
+ ``` cpp
417
+ auto tmp = *this;
418
+ --*this;
419
+ return tmp;
420
+ ```
421
+
422
+ ``` cpp
423
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
424
+ requires equality_comparable<iterator_t<V>>;
425
+ ```
426
+
427
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
428
+
429
+ ``` cpp
430
+ friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
431
+ noexcept(noexcept(ranges::iter_move(i.current_)));
432
+ ```
433
+
434
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
435
+
436
+ ``` cpp
437
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
438
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
439
+ requires indirectly_swappable<iterator_t<V>>;
440
+ ```
441
+
442
+ *Effects:* Equivalent to
443
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
444
+
445
+ #### Class `filter_view::sentinel` <a id="range.filter.sentinel">[[range.filter.sentinel]]</a>
446
+
447
+ ``` cpp
448
+ namespace std::ranges {
449
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
450
+ requires view<V> && is_object_v<Pred>
451
+ class filter_view<V, Pred>::sentinel {
452
+ private:
453
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
454
+ public:
455
+ sentinel() = default;
456
+ constexpr explicit sentinel(filter_view& parent);
457
+
458
+ constexpr sentinel_t<V> base() const;
459
+
460
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
461
+ };
462
+ }
463
+ ```
464
+
465
+ ``` cpp
466
+ constexpr explicit sentinel(filter_view& parent);
467
+ ```
468
+
469
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
470
+
471
+ ``` cpp
472
+ constexpr sentinel_t<V> base() const;
473
+ ```
474
+
475
+ *Effects:* Equivalent to: `return `*`end_`*`;`
476
+
477
+ ``` cpp
478
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
479
+ ```
480
+
481
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
482
+
483
+ ### Transform view <a id="range.transform">[[range.transform]]</a>
484
+
485
+ #### Overview <a id="range.transform.overview">[[range.transform.overview]]</a>
486
+
487
+ `transform_view` presents a `view` of an underlying sequence after
488
+ applying a transformation function to each element.
489
+
490
+ The name `views::transform` denotes a range adaptor object
491
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
492
+ expression `views::transform(E, F)` is expression-equivalent to
493
+ `transform_view{E, F}`.
494
+
495
+ [*Example 1*:
496
+
497
+ ``` cpp
498
+ vector<int> is{ 0, 1, 2, 3, 4 };
499
+ transform_view squares{is, [](int i) { return i * i; }};
500
+ for (int i : squares)
501
+ cout << i << ' '; // prints: 0 1 4 9 16
502
+ ```
503
+
504
+ — *end example*]
505
+
506
+ #### Class template `transform_view` <a id="range.transform.view">[[range.transform.view]]</a>
507
+
508
+ ``` cpp
509
+ namespace std::ranges {
510
+ template<input_range V, copy_constructible F>
511
+ requires view<V> && is_object_v<F> &&
512
+ regular_invocable<F&, range_reference_t<V>> &&
513
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
514
+ class transform_view : public view_interface<transform_view<V, F>> {
515
+ private:
516
+ // [range.transform.iterator], class template transform_view::iterator
517
+ template<bool> struct iterator; // exposition only
518
+ // [range.transform.sentinel], class template transform_view::sentinel
519
+ template<bool> struct sentinel; // exposition only
520
+
521
+ V base_ = V(); // exposition only
522
+ semiregular-box<F> fun_; // exposition only
523
+
524
+ public:
525
+ transform_view() = default;
526
+ constexpr transform_view(V base, F fun);
527
+
528
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
529
+ constexpr V base() && { return std::move(base_); }
530
+
531
+ constexpr iterator<false> begin();
532
+ constexpr iterator<true> begin() const
533
+ requires range<const V> &&
534
+ regular_invocable<const F&, range_reference_t<const V>>;
535
+
536
+ constexpr sentinel<false> end();
537
+ constexpr iterator<false> end() requires common_range<V>;
538
+ constexpr sentinel<true> end() const
539
+ requires range<const V> &&
540
+ regular_invocable<const F&, range_reference_t<const V>>;
541
+ constexpr iterator<true> end() const
542
+ requires common_range<const V> &&
543
+ regular_invocable<const F&, range_reference_t<const V>>;
544
+
545
+ constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
546
+ constexpr auto size() const requires sized_range<const V>
547
+ { return ranges::size(base_); }
548
+ };
549
+
550
+ template<class R, class F>
551
+ transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
552
+ }
553
+ ```
554
+
555
+ ``` cpp
556
+ constexpr transform_view(V base, F fun);
557
+ ```
558
+
559
+ *Effects:* Initializes *base\_* with `std::move(base)` and *fun\_* with
560
+ `std::move(fun)`.
561
+
562
+ ``` cpp
563
+ constexpr iterator<false> begin();
564
+ ```
565
+
566
+ *Effects:* Equivalent to:
567
+
568
+ ``` cpp
569
+ return iterator<false>{*this, ranges::begin(base_)};
570
+ ```
571
+
572
+ ``` cpp
573
+ constexpr iterator<true> begin() const
574
+ requires range<const V> &&
575
+ regular_invocable<const F&, range_reference_t<const V>>;
576
+ ```
577
+
578
+ *Effects:* Equivalent to:
579
+
580
+ ``` cpp
581
+ return iterator<true>{*this, ranges::begin(base_)};
582
+ ```
583
+
584
+ ``` cpp
585
+ constexpr sentinel<false> end();
586
+ ```
587
+
588
+ *Effects:* Equivalent to:
589
+
590
+ ``` cpp
591
+ return sentinel<false>{ranges::end(base_)};
592
+ ```
593
+
594
+ ``` cpp
595
+ constexpr iterator<false> end() requires common_range<V>;
596
+ ```
597
+
598
+ *Effects:* Equivalent to:
599
+
600
+ ``` cpp
601
+ return iterator<false>{*this, ranges::end(base_)};
602
+ ```
603
+
604
+ ``` cpp
605
+ constexpr sentinel<true> end() const
606
+ requires range<const V> &&
607
+ regular_invocable<const F&, range_reference_t<const V>>;
608
+ ```
609
+
610
+ *Effects:* Equivalent to:
611
+
612
+ ``` cpp
613
+ return sentinel<true>{ranges::end(base_)};
614
+ ```
615
+
616
+ ``` cpp
617
+ constexpr iterator<true> end() const
618
+ requires common_range<const V> &&
619
+ regular_invocable<const F&, range_reference_t<const V>>;
620
+ ```
621
+
622
+ *Effects:* Equivalent to:
623
+
624
+ ``` cpp
625
+ return iterator<true>{*this, ranges::end(base_)};
626
+ ```
627
+
628
+ #### Class template `transform_view::iterator` <a id="range.transform.iterator">[[range.transform.iterator]]</a>
629
+
630
+ ``` cpp
631
+ namespace std::ranges {
632
+ template<input_range V, copy_constructible F>
633
+ requires view<V> && is_object_v<F> &&
634
+ regular_invocable<F&, range_reference_t<V>> &&
635
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
636
+ template<bool Const>
637
+ class transform_view<V, F>::iterator {
638
+ private:
639
+ using Parent = // exposition only
640
+ conditional_t<Const, const transform_view, transform_view>;
641
+ using Base = // exposition only
642
+ conditional_t<Const, const V, V>;
643
+ iterator_t<Base> current_ = // exposition only
644
+ iterator_t<Base>();
645
+ Parent* parent_ = nullptr; // exposition only
646
+ public:
647
+ using iterator_concept = see below;
648
+ using iterator_category = see below;
649
+ using value_type =
650
+ remove_cvref_t<invoke_result_t<F&, range_reference_t<Base>>>;
651
+ using difference_type = range_difference_t<Base>;
652
+
653
+ iterator() = default;
654
+ constexpr iterator(Parent& parent, iterator_t<Base> current);
655
+ constexpr iterator(iterator<!Const> i)
656
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
657
+
658
+ constexpr iterator_t<Base> base() const &
659
+ requires copyable<iterator_t<Base>>;
660
+ constexpr iterator_t<Base> base() &&;
661
+ constexpr decltype(auto) operator*() const
662
+ { return invoke(*parent_->fun_, *current_); }
663
+
664
+ constexpr iterator& operator++();
665
+ constexpr void operator++(int);
666
+ constexpr iterator operator++(int) requires forward_range<Base>;
667
+
668
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
669
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
670
+
671
+ constexpr iterator& operator+=(difference_type n)
672
+ requires random_access_range<Base>;
673
+ constexpr iterator& operator-=(difference_type n)
674
+ requires random_access_range<Base>;
675
+ constexpr decltype(auto) operator[](difference_type n) const
676
+ requires random_access_range<Base>
677
+ { return invoke(*parent_->fun_, current_[n]); }
678
+
679
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
680
+ requires equality_comparable<iterator_t<Base>>;
681
+
682
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
683
+ requires random_access_range<Base>;
684
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
685
+ requires random_access_range<Base>;
686
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
687
+ requires random_access_range<Base>;
688
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
689
+ requires random_access_range<Base>;
690
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
691
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
692
+
693
+ friend constexpr iterator operator+(iterator i, difference_type n)
694
+ requires random_access_range<Base>;
695
+ friend constexpr iterator operator+(difference_type n, iterator i)
696
+ requires random_access_range<Base>;
697
+
698
+ friend constexpr iterator operator-(iterator i, difference_type n)
699
+ requires random_access_range<Base>;
700
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
701
+ requires random_access_range<Base>;
702
+
703
+ friend constexpr decltype(auto) iter_move(const iterator& i)
704
+ noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
705
+ {
706
+ if constexpr (is_lvalue_reference_v<decltype(*i)>)
707
+ return std::move(*i);
708
+ else
709
+ return *i;
710
+ }
711
+
712
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
713
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
714
+ requires indirectly_swappable<iterator_t<Base>>;
715
+ };
716
+ }
717
+ ```
718
+
719
+ `iterator::iterator_concept` is defined as follows:
720
+
721
+ - If `V` models `random_access_range`, then `iterator_concept` denotes
722
+ `random_access_iterator_tag`.
723
+ - Otherwise, if `V` models `bidirectional_range`, then
724
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
725
+ - Otherwise, if `V` models `forward_range`, then `iterator_concept`
726
+ denotes `forward_iterator_tag`.
727
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
728
+
729
+ `iterator::iterator_category` is defined as follows: Let `C` denote the
730
+ type `iterator_traits<iterator_t<Base>>::iterator_category`.
731
+
732
+ - If
733
+ `is_lvalue_reference_v<invoke_result_t<F&, range_reference_t<Base>>>`
734
+ is `true`, then
735
+ - if `C` models `derived_from<contiguous_iterator_tag>`,
736
+ `iterator_category` denotes `random_access_iterator_tag`;
737
+ - otherwise, `iterator_category` denotes `C`.
738
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
739
+
740
+ ``` cpp
741
+ constexpr iterator(Parent& parent, iterator_t<Base> current);
742
+ ```
743
+
744
+ *Effects:* Initializes *current\_* with `std::move(current)` and
745
+ *parent\_* with `addressof(parent)`.
746
+
747
+ ``` cpp
748
+ constexpr iterator(iterator<!Const> i)
749
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
750
+ ```
751
+
752
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
753
+ and *parent\_* with `i.`*`parent_`*.
754
+
755
+ ``` cpp
756
+ constexpr iterator_t<Base> base() const &
757
+ requires copyable<iterator_t<Base>>;
758
+ ```
759
+
760
+ *Effects:* Equivalent to: `return `*`current_`*`;`
761
+
762
+ ``` cpp
763
+ constexpr iterator_t<Base> base() &&;
764
+ ```
765
+
766
+ *Effects:* Equivalent to: `return std::move(current_);`
767
+
768
+ ``` cpp
769
+ constexpr iterator& operator++();
770
+ ```
771
+
772
+ *Effects:* Equivalent to:
773
+
774
+ ``` cpp
775
+ ++current_;
776
+ return *this;
777
+ ```
778
+
779
+ ``` cpp
780
+ constexpr void operator++(int);
781
+ ```
782
+
783
+ *Effects:* Equivalent to `++current_`.
784
+
785
+ ``` cpp
786
+ constexpr iterator operator++(int) requires forward_range<Base>;
787
+ ```
788
+
789
+ *Effects:* Equivalent to:
790
+
791
+ ``` cpp
792
+ auto tmp = *this;
793
+ ++*this;
794
+ return tmp;
795
+ ```
796
+
797
+ ``` cpp
798
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
799
+ ```
800
+
801
+ *Effects:* Equivalent to:
802
+
803
+ ``` cpp
804
+ --current_;
805
+ return *this;
806
+ ```
807
+
808
+ ``` cpp
809
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
810
+ ```
811
+
812
+ *Effects:* Equivalent to:
813
+
814
+ ``` cpp
815
+ auto tmp = *this;
816
+ --*this;
817
+ return tmp;
818
+ ```
819
+
820
+ ``` cpp
821
+ constexpr iterator& operator+=(difference_type n)
822
+ requires random_access_range<Base>;
823
+ ```
824
+
825
+ *Effects:* Equivalent to:
826
+
827
+ ``` cpp
828
+ current_ += n;
829
+ return *this;
830
+ ```
831
+
832
+ ``` cpp
833
+ constexpr iterator& operator-=(difference_type n)
834
+ requires random_access_range<Base>;
835
+ ```
836
+
837
+ *Effects:* Equivalent to:
838
+
839
+ ``` cpp
840
+ current_ -= n;
841
+ return *this;
842
+ ```
843
+
844
+ ``` cpp
845
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
846
+ requires equality_comparable<iterator_t<Base>>;
847
+ ```
848
+
849
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
850
+
851
+ ``` cpp
852
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
853
+ requires random_access_range<Base>;
854
+ ```
855
+
856
+ *Effects:* Equivalent to: `return x.`*`current_`*` < y.`*`current_`*`;`
857
+
858
+ ``` cpp
859
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
860
+ requires random_access_range<Base>;
861
+ ```
862
+
863
+ *Effects:* Equivalent to: `return y < x;`
864
+
865
+ ``` cpp
866
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
867
+ requires random_access_range<Base>;
868
+ ```
869
+
870
+ *Effects:* Equivalent to: `return !(y < x);`
871
+
872
+ ``` cpp
873
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
874
+ requires random_access_range<Base>;
875
+ ```
876
+
877
+ *Effects:* Equivalent to: `return !(x < y);`
878
+
879
+ ``` cpp
880
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
881
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
882
+ ```
883
+
884
+ *Effects:* Equivalent to:
885
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
886
+
887
+ ``` cpp
888
+ friend constexpr iterator operator+(iterator i, difference_type n)
889
+ requires random_access_range<Base>;
890
+ friend constexpr iterator operator+(difference_type n, iterator i)
891
+ requires random_access_range<Base>;
892
+ ```
893
+
894
+ *Effects:* Equivalent to:
895
+ `return iterator{*i.`*`parent_`*`, i.`*`current_`*` + n};`
896
+
897
+ ``` cpp
898
+ friend constexpr iterator operator-(iterator i, difference_type n)
899
+ requires random_access_range<Base>;
900
+ ```
901
+
902
+ *Effects:* Equivalent to:
903
+ `return iterator{*i.`*`parent_`*`, i.`*`current_`*` - n};`
904
+
905
+ ``` cpp
906
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
907
+ requires random_access_range<Base>;
908
+ ```
909
+
910
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
911
+
912
+ ``` cpp
913
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
914
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
915
+ requires indirectly_swappable<iterator_t<Base>>;
916
+ ```
917
+
918
+ *Effects:* Equivalent to
919
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
920
+
921
+ #### Class template `transform_view::sentinel` <a id="range.transform.sentinel">[[range.transform.sentinel]]</a>
922
+
923
+ ``` cpp
924
+ namespace std::ranges {
925
+ template<input_range V, copy_constructible F>
926
+ requires view<V> && is_object_v<F> &&
927
+ regular_invocable<F&, range_reference_t<V>> &&
928
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
929
+ template<bool Const>
930
+ class transform_view<V, F>::sentinel {
931
+ private:
932
+ using Parent = // exposition only
933
+ conditional_t<Const, const transform_view, transform_view>;
934
+ using Base = conditional_t<Const, const V, V>; // exposition only
935
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
936
+ public:
937
+ sentinel() = default;
938
+ constexpr explicit sentinel(sentinel_t<Base> end);
939
+ constexpr sentinel(sentinel<!Const> i)
940
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
941
+
942
+ constexpr sentinel_t<Base> base() const;
943
+
944
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
945
+
946
+ friend constexpr range_difference_t<Base>
947
+ operator-(const iterator<Const>& x, const sentinel& y)
948
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
949
+ friend constexpr range_difference_t<Base>
950
+ operator-(const sentinel& y, const iterator<Const>& x)
951
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
952
+ };
953
+ }
954
+ ```
955
+
956
+ ``` cpp
957
+ constexpr explicit sentinel(sentinel_t<Base> end);
958
+ ```
959
+
960
+ *Effects:* Initializes *end\_* with `end`.
961
+
962
+ ``` cpp
963
+ constexpr sentinel(sentinel<!Const> i)
964
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
965
+ ```
966
+
967
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
968
+
969
+ ``` cpp
970
+ constexpr sentinel_t<Base> base() const;
971
+ ```
972
+
973
+ *Effects:* Equivalent to: `return `*`end_`*`;`
974
+
975
+ ``` cpp
976
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
977
+ ```
978
+
979
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
980
+
981
+ ``` cpp
982
+ friend constexpr range_difference_t<Base>
983
+ operator-(const iterator<Const>& x, const sentinel& y)
984
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
985
+ ```
986
+
987
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
988
+
989
+ ``` cpp
990
+ friend constexpr range_difference_t<Base>
991
+ operator-(const sentinel& y, const iterator<Const>& x)
992
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
993
+ ```
994
+
995
+ *Effects:* Equivalent to: `return y.`*`end_`*` - x.`*`current_`*`;`
996
+
997
+ ### Take view <a id="range.take">[[range.take]]</a>
998
+
999
+ #### Overview <a id="range.take.overview">[[range.take.overview]]</a>
1000
+
1001
+ `take_view` produces a `view` of the first N elements from another
1002
+ `view`, or all the elements if the adapted `view` contains fewer than N.
1003
+
1004
+ The name `views::take` denotes a range adaptor object
1005
+ [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
1006
+ `remove_cvref_t<decltype((E))>`, and let `D` be
1007
+ `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
1008
+ `convertible_to<D>`, `views::take(E, F)` is ill-formed. Otherwise, the
1009
+ expression `views::take(E, F)` is expression-equivalent to:
1010
+
1011
+ - If `T` is a specialization of `ranges::empty_view`
1012
+ [[range.empty.view]], then `((void) F, decay-copy(E))`.
1013
+ - Otherwise, if `T` models `random_access_range` and `sized_range` and
1014
+ is
1015
+ - a specialization of `span` [[views.span]] where
1016
+ `T::extent == dynamic_extent`,
1017
+ - a specialization of `basic_string_view` [[string.view]],
1018
+ - a specialization of `ranges::iota_view` [[range.iota.view]], or
1019
+ - a specialization of `ranges::subrange` [[range.subrange]],
1020
+
1021
+ then
1022
+ `T{ranges::begin(E), ranges::begin(E) + min<D>(ranges::size(E), F)}`,
1023
+ except that `E` is evaluated only once.
1024
+ - Otherwise, `ranges::take_view{E, F}`.
1025
+
1026
+ [*Example 1*:
1027
+
1028
+ ``` cpp
1029
+ vector<int> is{0,1,2,3,4,5,6,7,8,9};
1030
+ take_view few{is, 5};
1031
+ for (int i : few)
1032
+ cout << i << ' '; // prints: 0 1 2 3 4
1033
+ ```
1034
+
1035
+ — *end example*]
1036
+
1037
+ #### Class template `take_view` <a id="range.take.view">[[range.take.view]]</a>
1038
+
1039
+ ``` cpp
1040
+ namespace std::ranges {
1041
+ template<view V>
1042
+ class take_view : public view_interface<take_view<V>> {
1043
+ private:
1044
+ V base_ = V(); // exposition only
1045
+ range_difference_t<V> count_ = 0; // exposition only
1046
+ // [range.take.sentinel], class template take_view::sentinel
1047
+ template<bool> struct sentinel; // exposition only
1048
+ public:
1049
+ take_view() = default;
1050
+ constexpr take_view(V base, range_difference_t<V> count);
1051
+
1052
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
1053
+ constexpr V base() && { return std::move(base_); }
1054
+
1055
+ constexpr auto begin() requires (!simple-view<V>) {
1056
+ if constexpr (sized_range<V>) {
1057
+ if constexpr (random_access_range<V>)
1058
+ return ranges::begin(base_);
1059
+ else {
1060
+ auto sz = size();
1061
+ return counted_iterator{ranges::begin(base_), sz};
1062
+ }
1063
+ } else
1064
+ return counted_iterator{ranges::begin(base_), count_};
1065
+ }
1066
+
1067
+ constexpr auto begin() const requires range<const V> {
1068
+ if constexpr (sized_range<const V>) {
1069
+ if constexpr (random_access_range<const V>)
1070
+ return ranges::begin(base_);
1071
+ else {
1072
+ auto sz = size();
1073
+ return counted_iterator{ranges::begin(base_), sz};
1074
+ }
1075
+ } else
1076
+ return counted_iterator{ranges::begin(base_), count_};
1077
+ }
1078
+
1079
+ constexpr auto end() requires (!simple-view<V>) {
1080
+ if constexpr (sized_range<V>) {
1081
+ if constexpr (random_access_range<V>)
1082
+ return ranges::begin(base_) + size();
1083
+ else
1084
+ return default_sentinel;
1085
+ } else
1086
+ return sentinel<false>{ranges::end(base_)};
1087
+ }
1088
+
1089
+ constexpr auto end() const requires range<const V> {
1090
+ if constexpr (sized_range<const V>) {
1091
+ if constexpr (random_access_range<const V>)
1092
+ return ranges::begin(base_) + size();
1093
+ else
1094
+ return default_sentinel;
1095
+ } else
1096
+ return sentinel<true>{ranges::end(base_)};
1097
+ }
1098
+
1099
+ constexpr auto size() requires sized_range<V> {
1100
+ auto n = ranges::size(base_);
1101
+ return ranges::min(n, static_cast<decltype(n)>(count_));
1102
+ }
1103
+
1104
+ constexpr auto size() const requires sized_range<const V> {
1105
+ auto n = ranges::size(base_);
1106
+ return ranges::min(n, static_cast<decltype(n)>(count_));
1107
+ }
1108
+ };
1109
+
1110
+ template<range R>
1111
+ take_view(R&&, range_difference_t<R>)
1112
+ -> take_view<views::all_t<R>>;
1113
+ }
1114
+ ```
1115
+
1116
+ ``` cpp
1117
+ constexpr take_view(V base, range_difference_t<V> count);
1118
+ ```
1119
+
1120
+ *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
1121
+ with `count`.
1122
+
1123
+ #### Class template `take_view::sentinel` <a id="range.take.sentinel">[[range.take.sentinel]]</a>
1124
+
1125
+ ``` cpp
1126
+ namespace std::ranges {
1127
+ template<view V>
1128
+ template<bool Const>
1129
+ class take_view<V>::sentinel {
1130
+ private:
1131
+ using Base = conditional_t<Const, const V, V>; // exposition only
1132
+ using CI = counted_iterator<iterator_t<Base>>; // exposition only
1133
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1134
+ public:
1135
+ sentinel() = default;
1136
+ constexpr explicit sentinel(sentinel_t<Base> end);
1137
+ constexpr sentinel(sentinel<!Const> s)
1138
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1139
+
1140
+ constexpr sentinel_t<Base> base() const;
1141
+
1142
+ friend constexpr bool operator==(const CI& y, const sentinel& x);
1143
+ };
1144
+ }
1145
+ ```
1146
+
1147
+ ``` cpp
1148
+ constexpr explicit sentinel(sentinel_t<Base> end);
1149
+ ```
1150
+
1151
+ *Effects:* Initializes *end\_* with `end`.
1152
+
1153
+ ``` cpp
1154
+ constexpr sentinel(sentinel<!Const> s)
1155
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1156
+ ```
1157
+
1158
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
1159
+
1160
+ ``` cpp
1161
+ constexpr sentinel_t<Base> base() const;
1162
+ ```
1163
+
1164
+ *Effects:* Equivalent to: `return `*`end_`*`;`
1165
+
1166
+ ``` cpp
1167
+ friend constexpr bool operator==(const CI& y, const sentinel& x);
1168
+ ```
1169
+
1170
+ *Effects:* Equivalent to:
1171
+ `return y.count() == 0 || y.base() == x.`*`end_`*`;`
1172
+
1173
+ ### Take while view <a id="range.take.while">[[range.take.while]]</a>
1174
+
1175
+ #### Overview <a id="range.take.while.overview">[[range.take.while.overview]]</a>
1176
+
1177
+ Given a unary predicate `pred` and a `view` `r`, `take_while_view`
1178
+ produces a `view` of the range \[`begin(r)`,
1179
+ `ranges::find_if_not(r, pred)`).
1180
+
1181
+ The name `views::take_while` denotes a range adaptor object
1182
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1183
+ expression `views::take_while(E, F)` is expression-equivalent to
1184
+ `take_while_view{E, F}`.
1185
+
1186
+ [*Example 1*:
1187
+
1188
+ ``` cpp
1189
+ auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
1190
+ auto small = [](const auto x) noexcept { return x < 5; };
1191
+ auto small_ints = istream_view<int>(input) | views::take_while(small);
1192
+ for (const auto i : small_ints) {
1193
+ cout << i << ' '; // prints 0 1 2 3 4
1194
+ }
1195
+ auto i = 0;
1196
+ input >> i;
1197
+ cout << i; // prints 6
1198
+ ```
1199
+
1200
+ — *end example*]
1201
+
1202
+ #### Class template `take_while_view` <a id="range.take.while.view">[[range.take.while.view]]</a>
1203
+
1204
+ ``` cpp
1205
+ namespace std::ranges {
1206
+ template<view V, class Pred>
1207
+ requires input_range<V> && is_object_v<Pred> &&
1208
+ indirect_unary_predicate<const Pred, iterator_t<V>>
1209
+ class take_while_view : public view_interface<take_while_view<V, Pred>> {
1210
+ // [range.take.while.sentinel], class template take_while_view::sentinel
1211
+ template<bool> class sentinel; // exposition only
1212
+
1213
+ V base_ = V(); // exposition only
1214
+ semiregular-box<Pred> pred_; // exposition only
1215
+
1216
+ public:
1217
+ take_while_view() = default;
1218
+ constexpr take_while_view(V base, Pred pred);
1219
+
1220
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
1221
+ constexpr V base() && { return std::move(base_); }
1222
+
1223
+ constexpr const Pred& pred() const;
1224
+
1225
+ constexpr auto begin() requires (!simple-view<V>)
1226
+ { return ranges::begin(base_); }
1227
+
1228
+ constexpr auto begin() const requires range<const V>
1229
+ { return ranges::begin(base_); }
1230
+
1231
+ constexpr auto end() requires (!simple-view<V>)
1232
+ { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
1233
+
1234
+ constexpr auto end() const requires range<const V>
1235
+ { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
1236
+ };
1237
+
1238
+ template<class R, class Pred>
1239
+ take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
1240
+ }
1241
+ ```
1242
+
1243
+ ``` cpp
1244
+ constexpr take_while_view(V base, Pred pred);
1245
+ ```
1246
+
1247
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
1248
+ `std::move(pred)`.
1249
+
1250
+ ``` cpp
1251
+ constexpr const Pred& pred() const;
1252
+ ```
1253
+
1254
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
1255
+
1256
+ #### Class template `take_while_view::sentinel` <a id="range.take.while.sentinel">[[range.take.while.sentinel]]</a>
1257
+
1258
+ ``` cpp
1259
+ namespace std::ranges {
1260
+ template<view V, class Pred>
1261
+ requires input_range<V> && is_object_v<Pred> &&
1262
+ indirect_unary_predicate<const Pred, iterator_t<V>>
1263
+ template<bool Const>
1264
+ class take_while_view<V, Pred>::sentinel { // exposition only
1265
+ using Base = conditional_t<Const, const V, V>; // exposition only
1266
+
1267
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1268
+ const Pred* pred_ = nullptr; // exposition only
1269
+ public:
1270
+ sentinel() = default;
1271
+ constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
1272
+ constexpr sentinel(sentinel<!Const> s)
1273
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1274
+
1275
+ constexpr sentinel_t<Base> base() const { return end_; }
1276
+
1277
+ friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
1278
+ };
1279
+ }
1280
+ ```
1281
+
1282
+ ``` cpp
1283
+ constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
1284
+ ```
1285
+
1286
+ *Effects:* Initializes *end\_* with `end` and *pred\_* with `pred`.
1287
+
1288
+ ``` cpp
1289
+ constexpr sentinel(sentinel<!Const> s)
1290
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1291
+ ```
1292
+
1293
+ *Effects:* Initializes *end\_* with `s.`*`end_`* and *pred\_* with
1294
+ `s.`*`pred_`*.
1295
+
1296
+ ``` cpp
1297
+ friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
1298
+ ```
1299
+
1300
+ *Effects:* Equivalent to:
1301
+ `return y.`*`end_`*` == x || !invoke(*y.`*`pred_`*`, *x);`
1302
+
1303
+ ### Drop view <a id="range.drop">[[range.drop]]</a>
1304
+
1305
+ #### Overview <a id="range.drop.overview">[[range.drop.overview]]</a>
1306
+
1307
+ `drop_view` produces a `view` excluding the first N elements from
1308
+ another `view`, or an empty range if the adapted `view` contains fewer
1309
+ than N elements.
1310
+
1311
+ The name `views::drop` denotes a range adaptor object
1312
+ [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
1313
+ `remove_cvref_t<decltype((E))>`, and let `D` be
1314
+ `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
1315
+ `convertible_to<D>`, `views::drop(E, F)` is ill-formed. Otherwise, the
1316
+ expression `views::drop(E, F)` is expression-equivalent to:
1317
+
1318
+ - If `T` is a specialization of `ranges::empty_view`
1319
+ [[range.empty.view]], then `((void) F, decay-copy(E))`.
1320
+ - Otherwise, if `T` models `random_access_range` and `sized_range` and
1321
+ is
1322
+ - a specialization of `span` [[views.span]] where
1323
+ `T::extent == dynamic_extent`,
1324
+ - a specialization of `basic_string_view` [[string.view]],
1325
+ - a specialization of `ranges::iota_view` [[range.iota.view]], or
1326
+ - a specialization of `ranges::subrange` [[range.subrange]],
1327
+
1328
+ then
1329
+ `T{ranges::begin(E) + min<D>(ranges::size(E), F), ranges::end(E)}`,
1330
+ except that `E` is evaluated only once.
1331
+ - Otherwise, `ranges::drop_view{E, F}`.
1332
+
1333
+ [*Example 1*:
1334
+
1335
+ ``` cpp
1336
+ auto ints = views::iota(0) | views::take(10);
1337
+ auto latter_half = drop_view{ints, 5};
1338
+ for (auto i : latter_half) {
1339
+ cout << i << ' '; // prints 5 6 7 8 9
1340
+ }
1341
+ ```
1342
+
1343
+ — *end example*]
1344
+
1345
+ #### Class template `drop_view` <a id="range.drop.view">[[range.drop.view]]</a>
1346
+
1347
+ ``` cpp
1348
+ namespace std::ranges {
1349
+ template<view V>
1350
+ class drop_view : public view_interface<drop_view<V>> {
1351
+ public:
1352
+ drop_view() = default;
1353
+ constexpr drop_view(V base, range_difference_t<V> count);
1354
+
1355
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
1356
+ constexpr V base() && { return std::move(base_); }
1357
+
1358
+ constexpr auto begin()
1359
+ requires (!(simple-view<V> && random_access_range<V>));
1360
+ constexpr auto begin() const
1361
+ requires random_access_range<const V>;
1362
+
1363
+ constexpr auto end()
1364
+ requires (!simple-view<V>)
1365
+ { return ranges::end(base_); }
1366
+
1367
+ constexpr auto end() const
1368
+ requires range<const V>
1369
+ { return ranges::end(base_); }
1370
+
1371
+ constexpr auto size()
1372
+ requires sized_range<V>
1373
+ {
1374
+ const auto s = ranges::size(base_);
1375
+ const auto c = static_cast<decltype(s)>(count_);
1376
+ return s < c ? 0 : s - c;
1377
+ }
1378
+
1379
+ constexpr auto size() const
1380
+ requires sized_range<const V>
1381
+ {
1382
+ const auto s = ranges::size(base_);
1383
+ const auto c = static_cast<decltype(s)>(count_);
1384
+ return s < c ? 0 : s - c;
1385
+ }
1386
+ private:
1387
+ V base_ = V(); // exposition only
1388
+ range_difference_t<V> count_ = 0; // exposition only
1389
+ };
1390
+
1391
+ template<class R>
1392
+ drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
1393
+ }
1394
+ ```
1395
+
1396
+ ``` cpp
1397
+ constexpr drop_view(V base, range_difference_t<V> count);
1398
+ ```
1399
+
1400
+ *Preconditions:* `count >= 0` is `true`.
1401
+
1402
+ *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
1403
+ with `count`.
1404
+
1405
+ ``` cpp
1406
+ constexpr auto begin()
1407
+ requires (!(simple-view<V> && random_access_range<V>));
1408
+ constexpr auto begin() const
1409
+ requires random_access_range<const V>;
1410
+ ```
1411
+
1412
+ *Returns:*
1413
+ `ranges::next(ranges::begin(base_), count_, ranges::end(base_))`.
1414
+
1415
+ *Remarks:* In order to provide the amortized constant-time complexity
1416
+ required by the `range` concept when `drop_view` models `forward_range`,
1417
+ the first overload caches the result within the `drop_view` for use on
1418
+ subsequent calls.
1419
+
1420
+ [*Note 1*: Without this, applying a `reverse_view` over a `drop_view`
1421
+ would have quadratic iteration complexity. — *end note*]
1422
+
1423
+ ### Drop while view <a id="range.drop.while">[[range.drop.while]]</a>
1424
+
1425
+ #### Overview <a id="range.drop.while.overview">[[range.drop.while.overview]]</a>
1426
+
1427
+ Given a unary predicate `pred` and a `view` `r`, `drop_while_view`
1428
+ produces a `view` of the range \[`ranges::find_if_not(r, pred)`,
1429
+ `ranges::end(r)`).
1430
+
1431
+ The name `views::drop_while` denotes a range adaptor object
1432
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1433
+ expression `views::drop_while(E, F)` is expression-equivalent to
1434
+ `drop_while_view{E, F}`.
1435
+
1436
+ [*Example 1*:
1437
+
1438
+ ``` cpp
1439
+ constexpr auto source = " \t \t \t hello there";
1440
+ auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
1441
+ auto skip_ws = drop_while_view{source, is_invisible};
1442
+ for (auto c : skip_ws) {
1443
+ cout << c; // prints hello there with no leading space
1444
+ }
1445
+ ```
1446
+
1447
+ — *end example*]
1448
+
1449
+ #### Class template `drop_while_view` <a id="range.drop.while.view">[[range.drop.while.view]]</a>
1450
+
1451
+ ``` cpp
1452
+ namespace std::ranges {
1453
+ template<view V, class Pred>
1454
+ requires input_range<V> && is_object_v<Pred> &&
1455
+ indirect_unary_predicate<const Pred, iterator_t<V>>
1456
+ class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
1457
+ public:
1458
+ drop_while_view() = default;
1459
+ constexpr drop_while_view(V base, Pred pred);
1460
+
1461
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
1462
+ constexpr V base() && { return std::move(base_); }
1463
+
1464
+ constexpr const Pred& pred() const;
1465
+
1466
+ constexpr auto begin();
1467
+
1468
+ constexpr auto end()
1469
+ { return ranges::end(base_); }
1470
+
1471
+ private:
1472
+ V base_ = V(); // exposition only
1473
+ semiregular-box<Pred> pred_; // exposition only
1474
+ };
1475
+
1476
+ template<class R, class Pred>
1477
+ drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
1478
+ }
1479
+ ```
1480
+
1481
+ ``` cpp
1482
+ constexpr drop_while_view(V base, Pred pred);
1483
+ ```
1484
+
1485
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
1486
+ `std::move(pred)`.
1487
+
1488
+ ``` cpp
1489
+ constexpr const Pred& pred() const;
1490
+ ```
1491
+
1492
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
1493
+
1494
+ ``` cpp
1495
+ constexpr auto begin();
1496
+ ```
1497
+
1498
+ *Returns:* `ranges::find_if_not(base_, cref(*pred_))`.
1499
+
1500
+ *Remarks:* In order to provide the amortized constant-time complexity
1501
+ required by the `range` concept when `drop_while_view` models
1502
+ `forward_range`, the first call caches the result within the
1503
+ `drop_while_view` for use on subsequent calls.
1504
+
1505
+ [*Note 1*: Without this, applying a `reverse_view` over a
1506
+ `drop_while_view` would have quadratic iteration
1507
+ complexity. — *end note*]
1508
+
1509
+ ### Join view <a id="range.join">[[range.join]]</a>
1510
+
1511
+ #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
1512
+
1513
+ `join_view` flattens a `view` of ranges into a `view`.
1514
+
1515
+ The name `views::join` denotes a range adaptor object
1516
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
1517
+ `views::join(E)` is expression-equivalent to `join_view{E}`.
1518
+
1519
+ [*Example 1*:
1520
+
1521
+ ``` cpp
1522
+ vector<string> ss{"hello", " ", "world", "!"};
1523
+ join_view greeting{ss};
1524
+ for (char ch : greeting)
1525
+ cout << ch; // prints: hello world!
1526
+ ```
1527
+
1528
+ — *end example*]
1529
+
1530
+ #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
1531
+
1532
+ ``` cpp
1533
+ namespace std::ranges {
1534
+ template<input_range V>
1535
+ requires view<V> && input_range<range_reference_t<V>> &&
1536
+ (is_reference_v<range_reference_t<V>> ||
1537
+ view<range_value_t<V>>)
1538
+ class join_view : public view_interface<join_view<V>> {
1539
+ private:
1540
+ using InnerRng = // exposition only
1541
+ range_reference_t<V>;
1542
+ // [range.join.iterator], class template join_view::iterator
1543
+ template<bool Const>
1544
+ struct iterator; // exposition only
1545
+ // [range.join.sentinel], class template join_view::sentinel
1546
+ template<bool Const>
1547
+ struct sentinel; // exposition only
1548
+
1549
+ V base_ = V(); // exposition only
1550
+ views::all_t<InnerRng> inner_ = // exposition only, present only when !is_reference_v<InnerRng>
1551
+ views::all_t<InnerRng>();
1552
+ public:
1553
+ join_view() = default;
1554
+ constexpr explicit join_view(V base);
1555
+
1556
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
1557
+ constexpr V base() && { return std::move(base_); }
1558
+
1559
+ constexpr auto begin() {
1560
+ constexpr bool use_const = simple-view<V> &&
1561
+ is_reference_v<range_reference_t<V>>;
1562
+ return iterator<use_const>{*this, ranges::begin(base_)};
1563
+ }
1564
+
1565
+ constexpr auto begin() const
1566
+ requires input_range<const V> &&
1567
+ is_reference_v<range_reference_t<const V>> {
1568
+ return iterator<true>{*this, ranges::begin(base_)};
1569
+ }
1570
+
1571
+ constexpr auto end() {
1572
+ if constexpr (forward_range<V> &&
1573
+ is_reference_v<InnerRng> && forward_range<InnerRng> &&
1574
+ common_range<V> && common_range<InnerRng>)
1575
+ return iterator<simple-view<V>>{*this, ranges::end(base_)};
1576
+ else
1577
+ return sentinel<simple-view<V>>{*this};
1578
+ }
1579
+
1580
+ constexpr auto end() const
1581
+ requires input_range<const V> &&
1582
+ is_reference_v<range_reference_t<const V>> {
1583
+ if constexpr (forward_range<const V> &&
1584
+ is_reference_v<range_reference_t<const V>> &&
1585
+ forward_range<range_reference_t<const V>> &&
1586
+ common_range<const V> &&
1587
+ common_range<range_reference_t<const V>>)
1588
+ return iterator<true>{*this, ranges::end(base_)};
1589
+ else
1590
+ return sentinel<true>{*this};
1591
+ }
1592
+ };
1593
+
1594
+ template<class R>
1595
+ explicit join_view(R&&) -> join_view<views::all_t<R>>;
1596
+ }
1597
+ ```
1598
+
1599
+ ``` cpp
1600
+ constexpr explicit join_view(V base);
1601
+ ```
1602
+
1603
+ *Effects:* Initializes *base\_* with `std::move(base)`.
1604
+
1605
+ #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
1606
+
1607
+ ``` cpp
1608
+ namespace std::ranges {
1609
+ template<input_range V>
1610
+ requires view<V> && input_range<range_reference_t<V>> &&
1611
+ (is_reference_v<range_reference_t<V>> ||
1612
+ view<range_value_t<V>>)
1613
+ template<bool Const>
1614
+ struct join_view<V>::iterator {
1615
+ private:
1616
+ using Parent = // exposition only
1617
+ conditional_t<Const, const join_view, join_view>;
1618
+ using Base = conditional_t<Const, const V, V>; // exposition only
1619
+
1620
+ static constexpr bool ref-is-glvalue = // exposition only
1621
+ is_reference_v<range_reference_t<Base>>;
1622
+
1623
+ iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only
1624
+ iterator_t<range_reference_t<Base>> inner_ = // exposition only
1625
+ iterator_t<range_reference_t<Base>>();
1626
+ Parent* parent_ = nullptr; // exposition only
1627
+
1628
+ constexpr void satisfy(); // exposition only
1629
+ public:
1630
+ using iterator_concept = see below;
1631
+ using iterator_category = see below;
1632
+ using value_type = range_value_t<range_reference_t<Base>>;
1633
+ using difference_type = see below;
1634
+
1635
+ iterator() = default;
1636
+ constexpr iterator(Parent& parent, iterator_t<Base> outer);
1637
+ constexpr iterator(iterator<!Const> i)
1638
+ requires Const &&
1639
+ convertible_to<iterator_t<V>, iterator_t<Base>> &&
1640
+ convertible_to<iterator_t<InnerRng>,
1641
+ iterator_t<range_reference_t<Base>>>;
1642
+
1643
+ constexpr decltype(auto) operator*() const { return *inner_; }
1644
+
1645
+ constexpr iterator_t<Base> operator->() const
1646
+ requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
1647
+
1648
+ constexpr iterator& operator++();
1649
+ constexpr void operator++(int);
1650
+ constexpr iterator operator++(int)
1651
+ requires ref-is-glvalue && forward_range<Base> &&
1652
+ forward_range<range_reference_t<Base>>;
1653
+
1654
+ constexpr iterator& operator--()
1655
+ requires ref-is-glvalue && bidirectional_range<Base> &&
1656
+ bidirectional_range<range_reference_t<Base>> &&
1657
+ common_range<range_reference_t<Base>>;
1658
+
1659
+ constexpr iterator operator--(int)
1660
+ requires ref-is-glvalue && bidirectional_range<Base> &&
1661
+ bidirectional_range<range_reference_t<Base>> &&
1662
+ common_range<range_reference_t<Base>>;
1663
+
1664
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
1665
+ requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
1666
+ equality_comparable<iterator_t<range_reference_t<Base>>>;
1667
+
1668
+ friend constexpr decltype(auto) iter_move(const iterator& i)
1669
+ noexcept(noexcept(ranges::iter_move(i.inner_))) {
1670
+ return ranges::iter_move(i.inner_);
1671
+ }
1672
+
1673
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
1674
+ noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
1675
+ };
1676
+ }
1677
+ ```
1678
+
1679
+ `iterator::iterator_concept` is defined as follows:
1680
+
1681
+ - If *`ref-is-glvalue`* is `true` and *`Base`* and
1682
+ `range_reference_t<Base>` each model `bidirectional_range`, then
1683
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
1684
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
1685
+ `range_reference_t<Base>` each model , then `iterator_concept` denotes
1686
+ `forward_iterator_tag`.
1687
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
1688
+
1689
+ `iterator::iterator_category` is defined as follows:
1690
+
1691
+ - Let *OUTERC* denote
1692
+ `iterator_traits<iterator_t<Base>>::iterator_category`, and let
1693
+ *INNERC* denote
1694
+ `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
1695
+ - If *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC* each model
1696
+ `derived_from<bidirectional_iterator_tag>`, `iterator_category`
1697
+ denotes `bidirectional_iterator_tag`.
1698
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC*
1699
+ each model `derived_from<forward_iterator_tag>`, `iterator_category`
1700
+ denotes `forward_iterator_tag`.
1701
+ - Otherwise, if *OUTERC* and *INNERC* each model
1702
+ `derived_from<input_iterator_tag>`, `iterator_category` denotes
1703
+ `input_iterator_tag`.
1704
+ - Otherwise, `iterator_category` denotes `output_iterator_tag`.
1705
+
1706
+ `iterator::difference_type` denotes the type:
1707
+
1708
+ ``` cpp
1709
+ common_type_t<
1710
+ range_difference_t<Base>,
1711
+ range_difference_t<range_reference_t<Base>>>
1712
+ ```
1713
+
1714
+ `join_view` iterators use the *`satisfy`* function to skip over empty
1715
+ inner ranges.
1716
+
1717
+ ``` cpp
1718
+ constexpr void satisfy(); // exposition only
1719
+ ```
1720
+
1721
+ *Effects:* Equivalent to:
1722
+
1723
+ ``` cpp
1724
+ auto update_inner = [this](range_reference_t<Base> x) -> auto& {
1725
+ if constexpr (ref-is-glvalue) // x is a reference
1726
+ return x;
1727
+ else
1728
+ return (parent_->inner_ = views::all(std::move(x)));
1729
+ };
1730
+
1731
+ for (; outer_ != ranges::end(parent_->base_); ++outer_) {
1732
+ auto& inner = update_inner(*outer_);
1733
+ inner_ = ranges::begin(inner);
1734
+ if (inner_ != ranges::end(inner))
1735
+ return;
1736
+ }
1737
+ if constexpr (ref-is-glvalue)
1738
+ inner_ = iterator_t<range_reference_t<Base>>();
1739
+ ```
1740
+
1741
+ ``` cpp
1742
+ constexpr iterator(Parent& parent, iterator_t<Base> outer);
1743
+ ```
1744
+
1745
+ *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
1746
+ with `addressof(parent)`; then calls *`satisfy`*`()`.
1747
+
1748
+ ``` cpp
1749
+ constexpr iterator(iterator<!Const> i)
1750
+ requires Const &&
1751
+ convertible_to<iterator_t<V>, iterator_t<Base>> &&
1752
+ convertible_to<iterator_t<InnerRng>,
1753
+ iterator_t<range_reference_t<Base>>>;
1754
+ ```
1755
+
1756
+ *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
1757
+ *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
1758
+ `i.`*`parent_`*.
1759
+
1760
+ ``` cpp
1761
+ constexpr iterator_t<Base> operator->() const
1762
+ requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
1763
+ ```
1764
+
1765
+ *Effects:* Equivalent to `return `*`inner_`*`;`
1766
+
1767
+ ``` cpp
1768
+ constexpr iterator& operator++();
1769
+ ```
1770
+
1771
+ Let *`inner-range`* be:
1772
+
1773
+ - If *ref-is-glvalue* is `true`, `*`*`outer_`*.
1774
+ - Otherwise, *`parent_`*`->`*`inner_`*.
1775
+
1776
+ *Effects:* Equivalent to:
1777
+
1778
+ ``` cpp
1779
+ auto&& inner_rng = inner-range;
1780
+ if (++inner_ == ranges::end(inner_rng)) {
1781
+ ++outer_;
1782
+ satisfy();
1783
+ }
1784
+ return *this;
1785
+ ```
1786
+
1787
+ ``` cpp
1788
+ constexpr void operator++(int);
1789
+ ```
1790
+
1791
+ *Effects:* Equivalent to: `++*this`.
1792
+
1793
+ ``` cpp
1794
+ constexpr iterator operator++(int)
1795
+ requires ref-is-glvalue && forward_range<Base> &&
1796
+ forward_range<range_reference_t<Base>>;
1797
+ ```
1798
+
1799
+ *Effects:* Equivalent to:
1800
+
1801
+ ``` cpp
1802
+ auto tmp = *this;
1803
+ ++*this;
1804
+ return tmp;
1805
+ ```
1806
+
1807
+ ``` cpp
1808
+ constexpr iterator& operator--()
1809
+ requires ref-is-glvalue && bidirectional_range<Base> &&
1810
+ bidirectional_range<range_reference_t<Base>> &&
1811
+ common_range<range_reference_t<Base>>;
1812
+ ```
1813
+
1814
+ *Effects:* Equivalent to:
1815
+
1816
+ ``` cpp
1817
+ if (outer_ == ranges::end(parent_->base_))
1818
+ inner_ = ranges::end(*--outer_);
1819
+ while (inner_ == ranges::begin(*outer_))
1820
+ inner_ = ranges::end(*--outer_);
1821
+ --inner_;
1822
+ return *this;
1823
+ ```
1824
+
1825
+ ``` cpp
1826
+ constexpr iterator operator--(int)
1827
+ requires ref-is-glvalue && bidirectional_range<Base> &&
1828
+ bidirectional_range<range_reference_t<Base>> &&
1829
+ common_range<range_reference_t<Base>>;
1830
+ ```
1831
+
1832
+ *Effects:* Equivalent to:
1833
+
1834
+ ``` cpp
1835
+ auto tmp = *this;
1836
+ --*this;
1837
+ return tmp;
1838
+ ```
1839
+
1840
+ ``` cpp
1841
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
1842
+ requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
1843
+ equality_comparable<iterator_t<range_reference_t<Base>>>;
1844
+ ```
1845
+
1846
+ *Effects:* Equivalent to:
1847
+ `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
1848
+
1849
+ ``` cpp
1850
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
1851
+ noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
1852
+ ```
1853
+
1854
+ *Effects:* Equivalent to:
1855
+ `return ranges::iter_swap(x.`*`inner_`*`, y.`*`inner_`*`);`
1856
+
1857
+ #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
1858
+
1859
+ ``` cpp
1860
+ namespace std::ranges {
1861
+ template<input_range V>
1862
+ requires view<V> && input_range<range_reference_t<V>> &&
1863
+ (is_reference_v<range_reference_t<V>> ||
1864
+ view<range_value_t<V>>)
1865
+ template<bool Const>
1866
+ struct join_view<V>::sentinel {
1867
+ private:
1868
+ using Parent = // exposition only
1869
+ conditional_t<Const, const join_view, join_view>;
1870
+ using Base = conditional_t<Const, const V, V>; // exposition only
1871
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1872
+ public:
1873
+ sentinel() = default;
1874
+
1875
+ constexpr explicit sentinel(Parent& parent);
1876
+ constexpr sentinel(sentinel<!Const> s)
1877
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1878
+
1879
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
1880
+ };
1881
+ }
1882
+ ```
1883
+
1884
+ ``` cpp
1885
+ constexpr explicit sentinel(Parent& parent);
1886
+ ```
1887
+
1888
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
1889
+
1890
+ ``` cpp
1891
+ constexpr sentinel(sentinel<!Const> s)
1892
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1893
+ ```
1894
+
1895
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
1896
+
1897
+ ``` cpp
1898
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
1899
+ ```
1900
+
1901
+ *Effects:* Equivalent to: `return x.`*`outer_`*` == y.`*`end_`*`;`
1902
+
1903
+ ### Split view <a id="range.split">[[range.split]]</a>
1904
+
1905
+ #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
1906
+
1907
+ `split_view` takes a `view` and a delimiter, and splits the `view` into
1908
+ subranges on the delimiter. The delimiter can be a single element or a
1909
+ `view` of elements.
1910
+
1911
+ The name `views::split` denotes a range adaptor object
1912
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1913
+ expression `views::split(E, F)` is expression-equivalent to
1914
+ `split_view{E, F}`.
1915
+
1916
+ [*Example 1*:
1917
+
1918
+ ``` cpp
1919
+ string str{"the quick brown fox"};
1920
+ split_view sentence{str, ' '};
1921
+ for (auto word : sentence) {
1922
+ for (char ch : word)
1923
+ cout << ch;
1924
+ cout << '*';
1925
+ }
1926
+ // The above prints: the*quick*brown*fox*
1927
+ ```
1928
+
1929
+ — *end example*]
1930
+
1931
+ #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
1932
+
1933
+ ``` cpp
1934
+ namespace std::ranges {
1935
+ template<auto> struct require-constant; // exposition only
1936
+
1937
+ template<class R>
1938
+ concept tiny-range = // exposition only
1939
+ sized_range<R> &&
1940
+ requires { typename require-constant<remove_reference_t<R>::size()>; } &&
1941
+ (remove_reference_t<R>::size() <= 1);
1942
+
1943
+ template<input_range V, forward_range Pattern>
1944
+ requires view<V> && view<Pattern> &&
1945
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
1946
+ (forward_range<V> || tiny-range<Pattern>)
1947
+ class split_view : public view_interface<split_view<V, Pattern>> {
1948
+ private:
1949
+ V base_ = V(); // exposition only
1950
+ Pattern pattern_ = Pattern(); // exposition only
1951
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only, present only if !forward_range<V>
1952
+ // [range.split.outer], class template split_view::outer-iterator
1953
+ template<bool> struct outer-iterator; // exposition only
1954
+ // [range.split.inner], class template split_view::inner-iterator
1955
+ template<bool> struct inner-iterator; // exposition only
1956
+ public:
1957
+ split_view() = default;
1958
+ constexpr split_view(V base, Pattern pattern);
1959
+
1960
+ template<input_range R>
1961
+ requires constructible_from<V, views::all_t<R>> &&
1962
+ constructible_from<Pattern, single_view<range_value_t<R>>>
1963
+ constexpr split_view(R&& r, range_value_t<R> e);
1964
+
1965
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
1966
+ constexpr V base() && { return std::move(base_); }
1967
+
1968
+ constexpr auto begin() {
1969
+ if constexpr (forward_range<V>)
1970
+ return outer-iterator<simple-view<V>>{*this, ranges::begin(base_)};
1971
+ else {
1972
+ current_ = ranges::begin(base_);
1973
+ return outer-iterator<false>{*this};
1974
+ }
1975
+ }
1976
+
1977
+ constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
1978
+ return outer-iterator<true>{*this, ranges::begin(base_)};
1979
+ }
1980
+
1981
+ constexpr auto end() requires forward_range<V> && common_range<V> {
1982
+ return outer-iterator<simple-view<V>>{*this, ranges::end(base_)};
1983
+ }
1984
+
1985
+ constexpr auto end() const {
1986
+ if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
1987
+ return outer-iterator<true>{*this, ranges::end(base_)};
1988
+ else
1989
+ return default_sentinel;
1990
+ }
1991
+ };
1992
+
1993
+ template<class R, class P>
1994
+ split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
1995
+
1996
+ template<input_range R>
1997
+ split_view(R&&, range_value_t<R>)
1998
+ -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
1999
+ }
2000
+ ```
2001
+
2002
+ ``` cpp
2003
+ constexpr split_view(V base, Pattern pattern);
2004
+ ```
2005
+
2006
+ *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
2007
+ with `std::move(pattern)`.
2008
+
2009
+ ``` cpp
2010
+ template<input_range R>
2011
+ requires constructible_from<V, views::all_t<R>> &&
2012
+ constructible_from<Pattern, single_view<range_value_t<R>>>
2013
+ constexpr split_view(R&& r, range_value_t<R> e);
2014
+ ```
2015
+
2016
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
2017
+ and *pattern\_* with `single_view{std::move(e)}`.
2018
+
2019
+ #### Class template `split_view::outer-iterator` <a id="range.split.outer">[[range.split.outer]]</a>
2020
+
2021
+ ``` cpp
2022
+ namespace std::ranges {
2023
+ template<input_range V, forward_range Pattern>
2024
+ requires view<V> && view<Pattern> &&
2025
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2026
+ (forward_range<V> || tiny-range<Pattern>)
2027
+ template<bool Const>
2028
+ struct split_view<V, Pattern>::outer-iterator {
2029
+ private:
2030
+ using Parent = // exposition only
2031
+ conditional_t<Const, const split_view, split_view>;
2032
+ using Base = // exposition only
2033
+ conditional_t<Const, const V, V>;
2034
+ Parent* parent_ = nullptr; // exposition only
2035
+ iterator_t<Base> current_ = // exposition only, present only if V models forward_range
2036
+ iterator_t<Base>();
2037
+
2038
+ public:
2039
+ using iterator_concept =
2040
+ conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
2041
+ using iterator_category = input_iterator_tag;
2042
+ // [range.split.outer.value], class split_view::outer-iterator::value_type
2043
+ struct value_type;
2044
+ using difference_type = range_difference_t<Base>;
2045
+
2046
+ outer-iterator() = default;
2047
+ constexpr explicit outer-iterator(Parent& parent)
2048
+ requires (!forward_range<Base>);
2049
+ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
2050
+ requires forward_range<Base>;
2051
+ constexpr outer-iterator(outer-iterator<!Const> i)
2052
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2053
+
2054
+ constexpr value_type operator*() const;
2055
+
2056
+ constexpr outer-iterator& operator++();
2057
+ constexpr decltype(auto) operator++(int) {
2058
+ if constexpr (forward_range<Base>) {
2059
+ auto tmp = *this;
2060
+ ++*this;
2061
+ return tmp;
2062
+ } else
2063
+ ++*this;
2064
+ }
2065
+
2066
+ friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
2067
+ requires forward_range<Base>;
2068
+
2069
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
2070
+ };
2071
+ }
2072
+ ```
2073
+
2074
+ Many of the following specifications refer to the notional member
2075
+ *current* of *`outer-iterator`*. *current* is equivalent to *`current_`*
2076
+ if `V` models `forward_range`, and `parent_->current_` otherwise.
2077
+
2078
+ ``` cpp
2079
+ constexpr explicit outer-iterator(Parent& parent)
2080
+ requires (!forward_range<Base>);
2081
+ ```
2082
+
2083
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
2084
+
2085
+ ``` cpp
2086
+ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
2087
+ requires forward_range<Base>;
2088
+ ```
2089
+
2090
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and
2091
+ *current\_* with `std::move(current)`.
2092
+
2093
+ ``` cpp
2094
+ constexpr outer-iterator(outer-iterator<!Const> i)
2095
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2096
+ ```
2097
+
2098
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *current\_*
2099
+ with `std::move(i.`*`current_`*`)`.
2100
+
2101
+ ``` cpp
2102
+ constexpr value_type operator*() const;
2103
+ ```
2104
+
2105
+ *Effects:* Equivalent to: `return value_type{*this};`
2106
+
2107
+ ``` cpp
2108
+ constexpr outer-iterator& operator++();
2109
+ ```
2110
+
2111
+ *Effects:* Equivalent to:
2112
+
2113
+ ``` cpp
2114
+ const auto end = ranges::end(parent_->base_);
2115
+ if (current == end) return *this;
2116
+ const auto [pbegin, pend] = subrange{parent_->pattern_};
2117
+ if (pbegin == pend) ++current;
2118
+ else {
2119
+ do {
2120
+ auto [b, p] = ranges::mismatch(std::move(current), end, pbegin, pend);
2121
+ current = std::move(b);
2122
+ if (p == pend) {
2123
+ break; // The pattern matched; skip it
2124
+ }
2125
+ } while (++current != end);
2126
+ }
2127
+ return *this;
2128
+ ```
2129
+
2130
+ ``` cpp
2131
+ friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
2132
+ requires forward_range<Base>;
2133
+ ```
2134
+
2135
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
2136
+
2137
+ ``` cpp
2138
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
2139
+ ```
2140
+
2141
+ *Effects:* Equivalent to:
2142
+ `return x.`*`current`*` == ranges::end(x.`*`parent_`*`->`*`base_`*`);`
2143
+
2144
+ #### Class `split_view::outer-iterator::value_type` <a id="range.split.outer.value">[[range.split.outer.value]]</a>
2145
+
2146
+ ``` cpp
2147
+ namespace std::ranges {
2148
+ template<input_range V, forward_range Pattern>
2149
+ requires view<V> && view<Pattern> &&
2150
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2151
+ (forward_range<V> || tiny-range<Pattern>)
2152
+ template<bool Const>
2153
+ struct split_view<V, Pattern>::outer-iterator<Const>::value_type
2154
+ : view_interface<value_type> {
2155
+ private:
2156
+ outer-iterator i_ = outer-iterator(); // exposition only
2157
+ public:
2158
+ value_type() = default;
2159
+ constexpr explicit value_type(outer-iterator i);
2160
+
2161
+ constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
2162
+ constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
2163
+ constexpr default_sentinel_t end() const;
2164
+ };
2165
+ }
2166
+ ```
2167
+
2168
+ ``` cpp
2169
+ constexpr explicit value_type(outer-iterator i);
2170
+ ```
2171
+
2172
+ *Effects:* Initializes *i\_* with `std::move(i)`.
2173
+
2174
+ ``` cpp
2175
+ constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
2176
+ ```
2177
+
2178
+ *Effects:* Equivalent to:
2179
+ `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
2180
+
2181
+ ``` cpp
2182
+ constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
2183
+ ```
2184
+
2185
+ *Effects:* Equivalent to:
2186
+ `return `*`inner-iterator`*`<Const>{std::move(`*`i_`*`)};`
2187
+
2188
+ ``` cpp
2189
+ constexpr default_sentinel_t end() const;
2190
+ ```
2191
+
2192
+ *Effects:* Equivalent to: `return default_sentinel;`
2193
+
2194
+ #### Class template `split_view::inner-iterator` <a id="range.split.inner">[[range.split.inner]]</a>
2195
+
2196
+ ``` cpp
2197
+ namespace std::ranges {
2198
+ template<input_range V, forward_range Pattern>
2199
+ requires view<V> && view<Pattern> &&
2200
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2201
+ (forward_range<V> || tiny-range<Pattern>)
2202
+ template<bool Const>
2203
+ struct split_view<V, Pattern>::inner-iterator {
2204
+ private:
2205
+ using Base = conditional_t<Const, const V, V>; // exposition only
2206
+ outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
2207
+ bool incremented_ = false; // exposition only
2208
+ public:
2209
+ using iterator_concept = typename outer-iterator<Const>::iterator_concept;
2210
+ using iterator_category = see below;
2211
+ using value_type = range_value_t<Base>;
2212
+ using difference_type = range_difference_t<Base>;
2213
+
2214
+ inner-iterator() = default;
2215
+ constexpr explicit inner-iterator(outer-iterator<Const> i);
2216
+
2217
+ constexpr decltype(auto) operator*() const { return *i_.current; }
2218
+
2219
+ constexpr inner-iterator& operator++();
2220
+ constexpr decltype(auto) operator++(int) {
2221
+ if constexpr (forward_range<V>) {
2222
+ auto tmp = *this;
2223
+ ++*this;
2224
+ return tmp;
2225
+ } else
2226
+ ++*this;
2227
+ }
2228
+
2229
+ friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y)
2230
+ requires forward_range<Base>;
2231
+
2232
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
2233
+
2234
+ friend constexpr decltype(auto) iter_move(const inner-iterator& i)
2235
+ noexcept(noexcept(ranges::iter_move(i.i_.current))) {
2236
+ return ranges::iter_move(i.i_.current);
2237
+ }
2238
+
2239
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
2240
+ noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
2241
+ requires indirectly_swappable<iterator_t<Base>>;
2242
+ };
2243
+ }
2244
+ ```
2245
+
2246
+ The *typedef-name* `iterator_category` denotes:
2247
+
2248
+ - `forward_iterator_tag` if
2249
+ `iterator_traits<iterator_t<Base>>::iterator_category` models
2250
+ `derived_from<forward_iterator_tag>`;
2251
+ - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
2252
+
2253
+ ``` cpp
2254
+ constexpr explicit inner-iterator(outer-iterator<Const> i);
2255
+ ```
2256
+
2257
+ *Effects:* Initializes *i\_* with `std::move(i)`.
2258
+
2259
+ ``` cpp
2260
+ constexpr inner-iterator& operator++();
2261
+ ```
2262
+
2263
+ *Effects:* Equivalent to:
2264
+
2265
+ ``` cpp
2266
+ incremented_ = true;
2267
+ if constexpr (!forward_range<Base>) {
2268
+ if constexpr (Pattern::size() == 0) {
2269
+ return *this;
2270
+ }
2271
+ }
2272
+ ++i_.current;
2273
+ return *this;
2274
+ ```
2275
+
2276
+ ``` cpp
2277
+ friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y)
2278
+ requires forward_range<Base>;
2279
+ ```
2280
+
2281
+ *Effects:* Equivalent to:
2282
+ `return x.`*`i_`*`.`*`current`*` == y.`*`i_`*`.`*`current`*`;`
2283
+
2284
+ ``` cpp
2285
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
2286
+ ```
2287
+
2288
+ *Effects:* Equivalent to:
2289
+
2290
+ ``` cpp
2291
+ auto [pcur, pend] = subrange{x.i_.parent_->pattern_};
2292
+ auto end = ranges::end(x.i_.parent_->base_);
2293
+ if constexpr (tiny-range<Pattern>) {
2294
+ const auto & cur = x.i_.current;
2295
+ if (cur == end) return true;
2296
+ if (pcur == pend) return x.incremented_;
2297
+ return *cur == *pcur;
2298
+ } else {
2299
+ auto cur = x.i_.current;
2300
+ if (cur == end) return true;
2301
+ if (pcur == pend) return x.incremented_;
2302
+ do {
2303
+ if (*cur != *pcur) return false;
2304
+ if (++pcur == pend) return true;
2305
+ } while (++cur != end);
2306
+ return false;
2307
+ }
2308
+ ```
2309
+
2310
+ ``` cpp
2311
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
2312
+ noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
2313
+ requires indirectly_swappable<iterator_t<Base>>;
2314
+ ```
2315
+
2316
+ *Effects:* Equivalent to
2317
+ `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
2318
+
2319
+ ### Counted view <a id="range.counted">[[range.counted]]</a>
2320
+
2321
+ A counted view presents a `view` of the elements of the counted range
2322
+ [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
2323
+ non-negative integer `n`.
2324
+
2325
+ The name `views::counted` denotes a customization point object
2326
+ [[customization.point.object]]. Let `E` and `F` be expressions, let `T`
2327
+ be `decay_t<decltype((E))>`, and let `D` be `iter_difference_t<T>`. If
2328
+ `decltype((F))` does not model `convertible_to<D>`,
2329
+ `views::counted(E, F)` is ill-formed.
2330
+
2331
+ [*Note 1*: This case can result in substitution failure when
2332
+ `views::counted(E, F)` appears in the immediate context of a template
2333
+ instantiation. — *end note*]
2334
+
2335
+ Otherwise, `views::counted(E, F)` is expression-equivalent to:
2336
+
2337
+ - If `T` models `contiguous_iterator`, then
2338
+ `span{to_address(E), static_cast<D>(F)}`.
2339
+ - Otherwise, if `T` models `random_access_iterator`, then
2340
+ `subrange{E, E + static_cast<D>(F)}`, except that `E` is evaluated
2341
+ only once.
2342
+ - Otherwise, `subrange{counted_iterator{E, F}, default_sentinel}`.
2343
+
2344
+ ### Common view <a id="range.common">[[range.common]]</a>
2345
+
2346
+ #### Overview <a id="range.common.overview">[[range.common.overview]]</a>
2347
+
2348
+ `common_view` takes a `view` which has different types for its iterator
2349
+ and sentinel and turns it into a `view` of the same elements with an
2350
+ iterator and sentinel of the same type.
2351
+
2352
+ [*Note 1*: `common_view` is useful for calling legacy algorithms that
2353
+ expect a range’s iterator and sentinel types to be the
2354
+ same. — *end note*]
2355
+
2356
+ The name `views::common` denotes a range adaptor object
2357
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
2358
+ `views::common(E)` is expression-equivalent to:
2359
+
2360
+ - `views::all(E)`, if `decltype((E))` models `common_range` and
2361
+ `views::all(E)` is a well-formed expression.
2362
+ - Otherwise, `common_view{E}`.
2363
+
2364
+ [*Example 1*:
2365
+
2366
+ ``` cpp
2367
+ // Legacy algorithm:
2368
+ template<class ForwardIterator>
2369
+ size_t count(ForwardIterator first, ForwardIterator last);
2370
+
2371
+ template<forward_range R>
2372
+ void my_algo(R&& r) {
2373
+ auto&& common = common_view{r};
2374
+ auto cnt = count(common.begin(), common.end());
2375
+ // ...
2376
+ }
2377
+ ```
2378
+
2379
+ — *end example*]
2380
+
2381
+ #### Class template `common_view` <a id="range.common.view">[[range.common.view]]</a>
2382
+
2383
+ ``` cpp
2384
+ namespace std::ranges {
2385
+ template<view V>
2386
+ requires (!common_range<V> && copyable<iterator_t<V>>)
2387
+ class common_view : public view_interface<common_view<V>> {
2388
+ private:
2389
+ V base_ = V(); // exposition only
2390
+ public:
2391
+ common_view() = default;
2392
+
2393
+ constexpr explicit common_view(V r);
2394
+
2395
+ template<viewable_range R>
2396
+ requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
2397
+ constexpr explicit common_view(R&& r);
2398
+
2399
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
2400
+ constexpr V base() && { return std::move(base_); }
2401
+
2402
+ constexpr auto begin() {
2403
+ if constexpr (random_access_range<V> && sized_range<V>)
2404
+ return ranges::begin(base_);
2405
+ else
2406
+ return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
2407
+ }
2408
+
2409
+ constexpr auto begin() const requires range<const V> {
2410
+ if constexpr (random_access_range<const V> && sized_range<const V>)
2411
+ return ranges::begin(base_);
2412
+ else
2413
+ return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
2414
+ }
2415
+
2416
+ constexpr auto end() {
2417
+ if constexpr (random_access_range<V> && sized_range<V>)
2418
+ return ranges::begin(base_) + ranges::size(base_);
2419
+ else
2420
+ return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
2421
+ }
2422
+
2423
+ constexpr auto end() const requires range<const V> {
2424
+ if constexpr (random_access_range<const V> && sized_range<const V>)
2425
+ return ranges::begin(base_) + ranges::size(base_);
2426
+ else
2427
+ return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
2428
+ }
2429
+
2430
+ constexpr auto size() requires sized_range<V> {
2431
+ return ranges::size(base_);
2432
+ }
2433
+ constexpr auto size() const requires sized_range<const V> {
2434
+ return ranges::size(base_);
2435
+ }
2436
+ };
2437
+
2438
+ template<class R>
2439
+ common_view(R&&) -> common_view<views::all_t<R>>;
2440
+ }
2441
+ ```
2442
+
2443
+ ``` cpp
2444
+ constexpr explicit common_view(V base);
2445
+ ```
2446
+
2447
+ *Effects:* Initializes *base\_* with `std::move(base)`.
2448
+
2449
+ ``` cpp
2450
+ template<viewable_range R>
2451
+ requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
2452
+ constexpr explicit common_view(R&& r);
2453
+ ```
2454
+
2455
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`.
2456
+
2457
+ ### Reverse view <a id="range.reverse">[[range.reverse]]</a>
2458
+
2459
+ #### Overview <a id="range.reverse.overview">[[range.reverse.overview]]</a>
2460
+
2461
+ `reverse_view` takes a bidirectional `view` and produces another `view`
2462
+ that iterates the same elements in reverse order.
2463
+
2464
+ The name `views::reverse` denotes a range adaptor object
2465
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
2466
+ `views::reverse(E)` is expression-equivalent to:
2467
+
2468
+ - If the type of `E` is a (possibly cv-qualified) specialization of
2469
+ `reverse_view`, equivalent to `E.base()`.
2470
+ - Otherwise, if the type of `E` is cv-qualified
2471
+ ``` cpp
2472
+ subrange<reverse_iterator<I>, reverse_iterator<I>, K>
2473
+ ```
2474
+
2475
+ for some iterator type `I` and value `K` of type `subrange_kind`,
2476
+ - if `K` is `subrange_kind::sized`, equivalent to:
2477
+ ``` cpp
2478
+ subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
2479
+ ```
2480
+ - otherwise, equivalent to:
2481
+ ``` cpp
2482
+ subrange<I, I, K>(E.end().base(), E.begin().base())
2483
+ ```
2484
+
2485
+ However, in either case `E` is evaluated only once.
2486
+ - Otherwise, equivalent to `reverse_view{E}`.
2487
+
2488
+ [*Example 1*:
2489
+
2490
+ ``` cpp
2491
+ vector<int> is {0,1,2,3,4};
2492
+ reverse_view rv {is};
2493
+ for (int i : rv)
2494
+ cout << i << ' '; // prints: 4 3 2 1 0
2495
+ ```
2496
+
2497
+ — *end example*]
2498
+
2499
+ #### Class template `reverse_view` <a id="range.reverse.view">[[range.reverse.view]]</a>
2500
+
2501
+ ``` cpp
2502
+ namespace std::ranges {
2503
+ template<view V>
2504
+ requires bidirectional_range<V>
2505
+ class reverse_view : public view_interface<reverse_view<V>> {
2506
+ private:
2507
+ V base_ = V(); // exposition only
2508
+ public:
2509
+ reverse_view() = default;
2510
+
2511
+ constexpr explicit reverse_view(V r);
2512
+
2513
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
2514
+ constexpr V base() && { return std::move(base_); }
2515
+
2516
+ constexpr reverse_iterator<iterator_t<V>> begin();
2517
+ constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
2518
+ constexpr auto begin() const requires common_range<const V>;
2519
+
2520
+ constexpr reverse_iterator<iterator_t<V>> end();
2521
+ constexpr auto end() const requires common_range<const V>;
2522
+
2523
+ constexpr auto size() requires sized_range<V> {
2524
+ return ranges::size(base_);
2525
+ }
2526
+ constexpr auto size() const requires sized_range<const V> {
2527
+ return ranges::size(base_);
2528
+ }
2529
+ };
2530
+
2531
+ template<class R>
2532
+ reverse_view(R&&) -> reverse_view<views::all_t<R>>;
2533
+ }
2534
+ ```
2535
+
2536
+ ``` cpp
2537
+ constexpr explicit reverse_view(V base);
2538
+ ```
2539
+
2540
+ *Effects:* Initializes *base\_* with `std::move(base)`.
2541
+
2542
+ ``` cpp
2543
+ constexpr reverse_iterator<iterator_t<V>> begin();
2544
+ ```
2545
+
2546
+ *Returns:*
2547
+
2548
+ ``` cpp
2549
+ make_reverse_iterator(ranges::next(ranges::begin(base_), ranges::end(base_)))
2550
+ ```
2551
+
2552
+ *Remarks:* In order to provide the amortized constant time complexity
2553
+ required by the `range` concept, this function caches the result within
2554
+ the `reverse_view` for use on subsequent calls.
2555
+
2556
+ ``` cpp
2557
+ constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
2558
+ constexpr auto begin() const requires common_range<const V>;
2559
+ ```
2560
+
2561
+ *Effects:* Equivalent to:
2562
+ `return make_reverse_iterator(ranges::end(base_));`
2563
+
2564
+ ``` cpp
2565
+ constexpr reverse_iterator<iterator_t<V>> end();
2566
+ constexpr auto end() const requires common_range<const V>;
2567
+ ```
2568
+
2569
+ *Effects:* Equivalent to:
2570
+ `return make_reverse_iterator(ranges::begin(base_));`
2571
+
2572
+ ### Elements view <a id="range.elements">[[range.elements]]</a>
2573
+
2574
+ #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
2575
+
2576
+ `elements_view` takes a `view` of tuple-like values and a `size_t`, and
2577
+ produces a `view` with a value-type of the Nᵗʰ element of the adapted
2578
+ `view`’s value-type.
2579
+
2580
+ The name `views::elements<N>` denotes a range adaptor object
2581
+ [[range.adaptor.object]]. Given a subexpression `E` and constant
2582
+ expression `N`, the expression `views::elements<N>(E)` is
2583
+ expression-equivalent to
2584
+ `elements_view<views::all_t<decltype((E))>, N>{E}`.
2585
+
2586
+ [*Example 1*:
2587
+
2588
+ ``` cpp
2589
+ auto historical_figures = map{
2590
+ {"Lovelace"sv, 1815},
2591
+ {"Turing"sv, 1912},
2592
+ {"Babbage"sv, 1791},
2593
+ {"Hamilton"sv, 1936}
2594
+ };
2595
+
2596
+ auto names = historical_figures | views::elements<0>;
2597
+ for (auto&& name : names) {
2598
+ cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
2599
+ }
2600
+
2601
+ auto birth_years = historical_figures | views::elements<1>;
2602
+ for (auto&& born : birth_years) {
2603
+ cout << born << ' '; // prints 1791 1936 1815 1912
2604
+ }
2605
+ ```
2606
+
2607
+ — *end example*]
2608
+
2609
+ `keys_view` is an alias for `elements_view<views::all_t<R>, 0>`, and is
2610
+ useful for extracting keys from associative containers.
2611
+
2612
+ [*Example 2*:
2613
+
2614
+ ``` cpp
2615
+ auto names = keys_view{historical_figures};
2616
+ for (auto&& name : names) {
2617
+ cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
2618
+ }
2619
+ ```
2620
+
2621
+ — *end example*]
2622
+
2623
+ `values_view` is an alias for `elements_view<views::all_t<R>, 1>`, and
2624
+ is useful for extracting values from associative containers.
2625
+
2626
+ [*Example 3*:
2627
+
2628
+ ``` cpp
2629
+ auto is_even = [](const auto x) { return x % 2 == 0; };
2630
+ cout << ranges::count_if(values_view{historical_figures}, is_even); // prints 2
2631
+ ```
2632
+
2633
+ — *end example*]
2634
+
2635
+ #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
2636
+
2637
+ ``` cpp
2638
+ namespace std::ranges {
2639
+ template<class T, size_t N>
2640
+ concept has-tuple-element = // exposition only
2641
+ requires(T t) {
2642
+ typename tuple_size<T>::type;
2643
+ requires N < tuple_size_v<T>;
2644
+ typename tuple_element_t<N, T>;
2645
+ { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
2646
+ };
2647
+
2648
+
2649
+ template<input_range V, size_t N>
2650
+ requires view<V> && has-tuple-element<range_value_t<V>, N> &&
2651
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
2652
+ class elements_view : public view_interface<elements_view<V, N>> {
2653
+ public:
2654
+ elements_view() = default;
2655
+ constexpr explicit elements_view(V base);
2656
+
2657
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
2658
+ constexpr V base() && { return std::move(base_); }
2659
+
2660
+ constexpr auto begin() requires (!simple-view<V>)
2661
+ { return iterator<false>(ranges::begin(base_)); }
2662
+
2663
+ constexpr auto begin() const requires simple-view<V>
2664
+ { return iterator<true>(ranges::begin(base_)); }
2665
+
2666
+ constexpr auto end()
2667
+ { return sentinel<false>{ranges::end(base_)}; }
2668
+
2669
+ constexpr auto end() requires common_range<V>
2670
+ { return iterator<false>{ranges::end(base_)}; }
2671
+
2672
+ constexpr auto end() const requires range<const V>
2673
+ { return sentinel<true>{ranges::end(base_)}; }
2674
+
2675
+ constexpr auto end() const requires common_range<const V>
2676
+ { return iterator<true>{ranges::end(base_)}; }
2677
+
2678
+ constexpr auto size() requires sized_range<V>
2679
+ { return ranges::size(base_); }
2680
+
2681
+ constexpr auto size() const requires sized_range<const V>
2682
+ { return ranges::size(base_); }
2683
+
2684
+ private:
2685
+ // [range.elements.iterator], class template elements_view::iterator
2686
+ template<bool> struct iterator; // exposition only
2687
+ // [range.elements.sentinel], class template elements_view::sentinel
2688
+ template<bool> struct sentinel; // exposition only
2689
+ V base_ = V(); // exposition only
2690
+ };
2691
+ }
2692
+ ```
2693
+
2694
+ ``` cpp
2695
+ constexpr explicit elements_view(V base);
2696
+ ```
2697
+
2698
+ *Effects:* Initializes *base\_* with `std::move(base)`.
2699
+
2700
+ #### Class template `elements_view::iterator` <a id="range.elements.iterator">[[range.elements.iterator]]</a>
2701
+
2702
+ ``` cpp
2703
+ namespace std::ranges {
2704
+ template<input_range V, size_t N>
2705
+ requires view<V> && has-tuple-element<range_value_t<V>, N> &&
2706
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
2707
+ template<bool Const>
2708
+ class elements_view<V, N>::iterator { // exposition only
2709
+ using Base = conditional_t<Const, const V, V>; // exposition only
2710
+
2711
+ iterator_t<Base> current_ = iterator_t<Base>();
2712
+ public:
2713
+ using iterator_category = typename iterator_traits<iterator_t<Base>>::iterator_category;
2714
+ using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
2715
+ using difference_type = range_difference_t<Base>;
2716
+
2717
+ iterator() = default;
2718
+ constexpr explicit iterator(iterator_t<Base> current);
2719
+ constexpr iterator(iterator<!Const> i)
2720
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2721
+
2722
+ constexpr iterator_t<Base> base() const&
2723
+ requires copyable<iterator_t<Base>>;
2724
+ constexpr iterator_t<Base> base() &&;
2725
+
2726
+ constexpr decltype(auto) operator*() const
2727
+ { return get<N>(*current_); }
2728
+
2729
+ constexpr iterator& operator++();
2730
+ constexpr void operator++(int) requires (!forward_range<Base>);
2731
+ constexpr iterator operator++(int) requires forward_range<Base>;
2732
+
2733
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
2734
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
2735
+
2736
+ constexpr iterator& operator+=(difference_type x)
2737
+ requires random_access_range<Base>;
2738
+ constexpr iterator& operator-=(difference_type x)
2739
+ requires random_access_range<Base>;
2740
+
2741
+ constexpr decltype(auto) operator[](difference_type n) const
2742
+ requires random_access_range<Base>
2743
+ { return get<N>(*(current_ + n)); }
2744
+
2745
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2746
+ requires equality_comparable<iterator_t<Base>>;
2747
+
2748
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
2749
+ requires random_access_range<Base>;
2750
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
2751
+ requires random_access_range<Base>;
2752
+ friend constexpr bool operator<=(const iterator& y, const iterator& y)
2753
+ requires random_access_range<Base>;
2754
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
2755
+ requires random_access_range<Base>;
2756
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
2757
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
2758
+
2759
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
2760
+ requires random_access_range<Base>;
2761
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
2762
+ requires random_access_range<Base>;
2763
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
2764
+ requires random_access_range<Base>;
2765
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
2766
+ requires random_access_range<Base>;
2767
+ };
2768
+ }
2769
+ ```
2770
+
2771
+ ``` cpp
2772
+ constexpr explicit iterator(iterator_t<Base> current);
2773
+ ```
2774
+
2775
+ *Effects:* Initializes *current\_* with `std::move(current)`.
2776
+
2777
+ ``` cpp
2778
+ constexpr iterator(iterator<!Const> i)
2779
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2780
+ ```
2781
+
2782
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
2783
+
2784
+ ``` cpp
2785
+ constexpr iterator_t<Base> base() const&
2786
+ requires copyable<iterator_t<Base>>;
2787
+ ```
2788
+
2789
+ *Effects:* Equivalent to: `return `*`current_`*`;`
2790
+
2791
+ ``` cpp
2792
+ constexpr iterator_t<Base> base() &&;
2793
+ ```
2794
+
2795
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
2796
+
2797
+ ``` cpp
2798
+ constexpr iterator& operator++();
2799
+ ```
2800
+
2801
+ *Effects:* Equivalent to:
2802
+
2803
+ ``` cpp
2804
+ ++current_;
2805
+ return *this;
2806
+ ```
2807
+
2808
+ ``` cpp
2809
+ constexpr void operator++(int) requires (!forward_range<Base>);
2810
+ ```
2811
+
2812
+ *Effects:* Equivalent to: `++`*`current_`*.
2813
+
2814
+ ``` cpp
2815
+ constexpr iterator operator++(int) requires forward_range<Base>;
2816
+ ```
2817
+
2818
+ *Effects:* Equivalent to:
2819
+
2820
+ ``` cpp
2821
+ auto temp = *this;
2822
+ ++current_;
2823
+ return temp;
2824
+ ```
2825
+
2826
+ ``` cpp
2827
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
2828
+ ```
2829
+
2830
+ *Effects:* Equivalent to:
2831
+
2832
+ ``` cpp
2833
+ --current_;
2834
+ return *this;
2835
+ ```
2836
+
2837
+ ``` cpp
2838
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
2839
+ ```
2840
+
2841
+ *Effects:* Equivalent to:
2842
+
2843
+ ``` cpp
2844
+ auto temp = *this;
2845
+ --current_;
2846
+ return temp;
2847
+ ```
2848
+
2849
+ ``` cpp
2850
+ constexpr iterator& operator+=(difference_type n);
2851
+ requires random_access_range<Base>;
2852
+ ```
2853
+
2854
+ *Effects:* Equivalent to:
2855
+
2856
+ ``` cpp
2857
+ current_ += n;
2858
+ return *this;
2859
+ ```
2860
+
2861
+ ``` cpp
2862
+ constexpr iterator& operator-=(difference_type n)
2863
+ requires random_access_range<Base>;
2864
+ ```
2865
+
2866
+ *Effects:* Equivalent to:
2867
+
2868
+ ``` cpp
2869
+ current_ -= n;
2870
+ return *this;
2871
+ ```
2872
+
2873
+ ``` cpp
2874
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2875
+ requires equality_comparable<Base>;
2876
+ ```
2877
+
2878
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
2879
+
2880
+ ``` cpp
2881
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
2882
+ requires random_access_range<Base>;
2883
+ ```
2884
+
2885
+ *Effects:* Equivalent to: `return x.`*`current_`*` < y.`*`current_`*`;`
2886
+
2887
+ ``` cpp
2888
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
2889
+ requires random_access_range<Base>;
2890
+ ```
2891
+
2892
+ *Effects:* Equivalent to: `return y < x;`
2893
+
2894
+ ``` cpp
2895
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
2896
+ requires random_access_range<Base>;
2897
+ ```
2898
+
2899
+ *Effects:* Equivalent to: `return !(y < x);`
2900
+
2901
+ ``` cpp
2902
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
2903
+ requires random_access_range<Base>;
2904
+ ```
2905
+
2906
+ *Effects:* Equivalent to: `return !(x < y);`
2907
+
2908
+ ``` cpp
2909
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
2910
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
2911
+ ```
2912
+
2913
+ *Effects:* Equivalent to:
2914
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
2915
+
2916
+ ``` cpp
2917
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
2918
+ requires random_access_range<Base>;
2919
+ ```
2920
+
2921
+ *Effects:* Equivalent to: `return iterator{x} += y;`
2922
+
2923
+ ``` cpp
2924
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
2925
+ requires random_access_range<Base>;
2926
+ ```
2927
+
2928
+ *Effects:* Equivalent to: `return y + x;`
2929
+
2930
+ ``` cpp
2931
+ constexpr iterator operator-(const iterator& x, difference_type y)
2932
+ requires random_access_range<Base>;
2933
+ ```
2934
+
2935
+ *Effects:* Equivalent to: `return iterator{x} -= y;`
2936
+
2937
+ ``` cpp
2938
+ constexpr difference_type operator-(const iterator& x, const iterator& y)
2939
+ requires random_access_range<Base>;
2940
+ ```
2941
+
2942
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
2943
+
2944
+ #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
2945
+
2946
+ ``` cpp
2947
+ namespace std::ranges {
2948
+ template<input_range V, size_t N>
2949
+ requires view<V> && has-tuple-element<range_value_t<V>, N> &&
2950
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
2951
+ template<bool Const>
2952
+ class elements_view<V, N>::sentinel { // exposition only
2953
+ private:
2954
+ using Base = conditional_t<Const, const V, V>; // exposition only
2955
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
2956
+ public:
2957
+ sentinel() = default;
2958
+ constexpr explicit sentinel(sentinel_t<Base> end);
2959
+ constexpr sentinel(sentinel<!Const> other)
2960
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
2961
+
2962
+ constexpr sentinel_t<Base> base() const;
2963
+
2964
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
2965
+
2966
+ friend constexpr range_difference_t<Base>
2967
+ operator-(const iterator<Const>& x, const sentinel& y)
2968
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
2969
+
2970
+ friend constexpr range_difference_t<Base>
2971
+ operator-(const sentinel& x, const iterator<Const>& y)
2972
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
2973
+ };
2974
+ }
2975
+ ```
2976
+
2977
+ ``` cpp
2978
+ constexpr explicit sentinel(sentinel_t<Base> end);
2979
+ ```
2980
+
2981
+ *Effects:* Initializes *end\_* with `end`.
2982
+
2983
+ ``` cpp
2984
+ constexpr sentinel(sentinel<!Const> other)
2985
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
2986
+ ```
2987
+
2988
+ *Effects:* Initializes *end\_* with `std::move(other.`*`end_`*`)`.
2989
+
2990
+ ``` cpp
2991
+ constexpr sentinel_t<Base> base() const;
2992
+ ```
2993
+
2994
+ *Effects:* Equivalent to: `return `*`end_`*`;`
2995
+
2996
+ ``` cpp
2997
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
2998
+ ```
2999
+
3000
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
3001
+
3002
+ ``` cpp
3003
+ friend constexpr range_difference_t<Base>
3004
+ operator-(const iterator<Const>& x, const sentinel& y)
3005
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3006
+ ```
3007
+
3008
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
3009
+
3010
+ ``` cpp
3011
+ friend constexpr range_difference_t<Base>
3012
+ operator-(const sentinel& x, const iterator<Const>& y)
3013
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3014
+ ```
3015
+
3016
+ *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
3017
+
3018
+ <!-- Link reference definitions -->
3019
+ [basic.compound]: basic.md#basic.compound
3020
+ [concepts.equality]: concepts.md#concepts.equality
3021
+ [containers]: containers.md#containers
3022
+ [conv.rval]: expr.md#conv.rval
3023
+ [customization.point.object]: library.md#customization.point.object
3024
+ [dcl.array]: dcl.md#dcl.array
3025
+ [expr.const]: expr.md#expr.const
3026
+ [iterator.concept.bidir]: iterators.md#iterator.concept.bidir
3027
+ [iterator.concept.iterator]: iterators.md#iterator.concept.iterator
3028
+ [iterator.concept.output]: iterators.md#iterator.concept.output
3029
+ [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
3030
+ [iterator.concept.sizedsentinel]: iterators.md#iterator.concept.sizedsentinel
3031
+ [iterator.concept.winc]: iterators.md#iterator.concept.winc
3032
+ [iterator.requirements.general]: iterators.md#iterator.requirements.general
3033
+ [namespace.std]: library.md#namespace.std
3034
+ [range.access]: #range.access
3035
+ [range.access.begin]: #range.access.begin
3036
+ [range.access.cbegin]: #range.access.cbegin
3037
+ [range.access.cend]: #range.access.cend
3038
+ [range.access.crbegin]: #range.access.crbegin
3039
+ [range.access.crend]: #range.access.crend
3040
+ [range.access.end]: #range.access.end
3041
+ [range.access.rbegin]: #range.access.rbegin
3042
+ [range.access.rend]: #range.access.rend
3043
+ [range.adaptor.object]: #range.adaptor.object
3044
+ [range.adaptors]: #range.adaptors
3045
+ [range.all]: #range.all
3046
+ [range.common]: #range.common
3047
+ [range.common.overview]: #range.common.overview
3048
+ [range.common.view]: #range.common.view
3049
+ [range.counted]: #range.counted
3050
+ [range.dangling]: #range.dangling
3051
+ [range.drop]: #range.drop
3052
+ [range.drop.overview]: #range.drop.overview
3053
+ [range.drop.view]: #range.drop.view
3054
+ [range.drop.while]: #range.drop.while
3055
+ [range.drop.while.overview]: #range.drop.while.overview
3056
+ [range.drop.while.view]: #range.drop.while.view
3057
+ [range.elements]: #range.elements
3058
+ [range.elements.iterator]: #range.elements.iterator
3059
+ [range.elements.overview]: #range.elements.overview
3060
+ [range.elements.sentinel]: #range.elements.sentinel
3061
+ [range.elements.view]: #range.elements.view
3062
+ [range.empty]: #range.empty
3063
+ [range.empty.overview]: #range.empty.overview
3064
+ [range.empty.view]: #range.empty.view
3065
+ [range.factories]: #range.factories
3066
+ [range.filter]: #range.filter
3067
+ [range.filter.iterator]: #range.filter.iterator
3068
+ [range.filter.overview]: #range.filter.overview
3069
+ [range.filter.sentinel]: #range.filter.sentinel
3070
+ [range.filter.view]: #range.filter.view
3071
+ [range.iota]: #range.iota
3072
+ [range.iota.iterator]: #range.iota.iterator
3073
+ [range.iota.overview]: #range.iota.overview
3074
+ [range.iota.sentinel]: #range.iota.sentinel
3075
+ [range.iota.view]: #range.iota.view
3076
+ [range.istream]: #range.istream
3077
+ [range.istream.iterator]: #range.istream.iterator
3078
+ [range.istream.overview]: #range.istream.overview
3079
+ [range.istream.view]: #range.istream.view
3080
+ [range.join]: #range.join
3081
+ [range.join.iterator]: #range.join.iterator
3082
+ [range.join.overview]: #range.join.overview
3083
+ [range.join.sentinel]: #range.join.sentinel
3084
+ [range.join.view]: #range.join.view
3085
+ [range.prim.cdata]: #range.prim.cdata
3086
+ [range.prim.data]: #range.prim.data
3087
+ [range.prim.empty]: #range.prim.empty
3088
+ [range.prim.size]: #range.prim.size
3089
+ [range.prim.ssize]: #range.prim.ssize
3090
+ [range.range]: #range.range
3091
+ [range.ref.view]: #range.ref.view
3092
+ [range.refinements]: #range.refinements
3093
+ [range.req]: #range.req
3094
+ [range.req.general]: #range.req.general
3095
+ [range.reverse]: #range.reverse
3096
+ [range.reverse.overview]: #range.reverse.overview
3097
+ [range.reverse.view]: #range.reverse.view
3098
+ [range.semi.wrap]: #range.semi.wrap
3099
+ [range.single]: #range.single
3100
+ [range.single.overview]: #range.single.overview
3101
+ [range.single.view]: #range.single.view
3102
+ [range.sized]: #range.sized
3103
+ [range.split]: #range.split
3104
+ [range.split.inner]: #range.split.inner
3105
+ [range.split.outer]: #range.split.outer
3106
+ [range.split.outer.value]: #range.split.outer.value
3107
+ [range.split.overview]: #range.split.overview
3108
+ [range.split.view]: #range.split.view
3109
+ [range.subrange]: #range.subrange
3110
+ [range.subrange.access]: #range.subrange.access
3111
+ [range.subrange.ctor]: #range.subrange.ctor
3112
+ [range.summary]: #range.summary
3113
+ [range.take]: #range.take
3114
+ [range.take.overview]: #range.take.overview
3115
+ [range.take.sentinel]: #range.take.sentinel
3116
+ [range.take.view]: #range.take.view
3117
+ [range.take.while]: #range.take.while
3118
+ [range.take.while.overview]: #range.take.while.overview
3119
+ [range.take.while.sentinel]: #range.take.while.sentinel
3120
+ [range.take.while.view]: #range.take.while.view
3121
+ [range.transform]: #range.transform
3122
+ [range.transform.iterator]: #range.transform.iterator
3123
+ [range.transform.overview]: #range.transform.overview
3124
+ [range.transform.sentinel]: #range.transform.sentinel
3125
+ [range.transform.view]: #range.transform.view
3126
+ [range.utility]: #range.utility
3127
+ [range.utility.helpers]: #range.utility.helpers
3128
+ [range.view]: #range.view
3129
+ [ranges]: #ranges
3130
+ [ranges.general]: #ranges.general
3131
+ [ranges.syn]: #ranges.syn
3132
+ [string.view]: strings.md#string.view
3133
+ [view.interface]: #view.interface
3134
+ [view.interface.members]: #view.interface.members
3135
+ [views.span]: containers.md#views.span