From Jason Turner

[range.access]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpn4nzvla6/{from.md → to.md} +118 -128
tmp/tmpn4nzvla6/{from.md → to.md} RENAMED
@@ -1,12 +1,14 @@
1
  ## Range access <a id="range.access">[[range.access]]</a>
2
 
 
 
3
  In addition to being available via inclusion of the `<ranges>` header,
4
  the customization point objects in [[range.access]] are available when
5
  `<iterator>` is included.
6
 
7
- Within this subclause, the *reified object* of a subexpression `E`
8
  denotes
9
 
10
  - the same object as `E` if `E` is a glvalue, or
11
  - the result of applying the temporary materialization conversion
12
  [[conv.rval]] to `E` otherwise.
@@ -19,31 +21,23 @@ The name `ranges::begin` denotes a customization point object
19
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
20
  denotes the reified object for `E`. Then:
21
 
22
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
23
  `false`, `ranges::begin(E)` is ill-formed.
24
- - Otherwise, if `T` is an array type [[basic.compound]] and
25
  `remove_all_extents_t<T>` is an incomplete type, `ranges::begin(E)` is
26
  ill-formed with no diagnostic required.
27
  - Otherwise, if `T` is an array type, `ranges::begin(E)` is
28
  expression-equivalent to `t + 0`.
29
- - Otherwise, if `decay-copy(t.begin())` is a valid expression whose type
30
  models `input_or_output_iterator`, `ranges::begin(E)` is
31
- expression-equivalent to `decay-copy(t.begin())`.
32
- - Otherwise, if `T` is a class or enumeration type and
33
- `decay-copy(begin(t))` is a valid expression whose type models
34
- `input_or_output_iterator` with overload resolution performed in a
35
- context in which unqualified lookup for `begin` finds only the
36
- declarations
37
- ``` cpp
38
- void begin(auto&) = delete;
39
- void begin(const auto&) = delete;
40
- ```
41
-
42
- then `ranges::begin(E)` is expression-equivalent to
43
- `decay-copy(begin(t))` with overload resolution performed in the above
44
- context.
45
  - Otherwise, `ranges::begin(E)` is ill-formed.
46
 
47
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
48
  failure when `ranges::begin(E)` appears in the immediate context of a
49
  template instantiation. — *end note*]
@@ -59,32 +53,25 @@ The name `ranges::end` denotes a customization point object
59
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
60
  denotes the reified object for `E`. Then:
61
 
62
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
63
  `false`, `ranges::end(E)` is ill-formed.
64
- - Otherwise, if `T` is an array type [[basic.compound]] and
65
  `remove_all_extents_t<T>` is an incomplete type, `ranges::end(E)` is
66
  ill-formed with no diagnostic required.
67
  - Otherwise, if `T` is an array of unknown bound, `ranges::end(E)` is
68
  ill-formed.
69
  - Otherwise, if `T` is an array, `ranges::end(E)` is
70
  expression-equivalent to `t + extent_v<T>`.
71
- - Otherwise, if `decay-copy(t.end())` is a valid expression whose type
72
- models `sentinel_for<iterator_t<T>>` then `ranges::end(E)` is
73
- expression-equivalent to `decay-copy(t.end())`.
74
- - Otherwise, if `T` is a class or enumeration type and
75
- `decay-copy(end(t))` is a valid expression whose type models
76
- `sentinel_for<iterator_t<T>>` with overload resolution performed in a
77
- context in which unqualified lookup for `end` finds only the
78
- declarations
79
- ``` cpp
80
- void end(auto&) = delete;
81
- void end(const auto&) = delete;
82
- ```
83
-
84
- then `ranges::end(E)` is expression-equivalent to `decay-copy(end(t))`
85
- with overload resolution performed in the above context.
86
  - Otherwise, `ranges::end(E)` is ill-formed.
87
 
88
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
89
  failure when `ranges::end(E)` appears in the immediate context of a
90
  template instantiation. — *end note*]
@@ -94,31 +81,39 @@ template instantiation. — *end note*]
94
  `sentinel_for<S, I>`. — *end note*]
95
 
96
  ### `ranges::cbegin` <a id="range.access.cbegin">[[range.access.cbegin]]</a>
97
 
98
  The name `ranges::cbegin` denotes a customization point object
99
- [[customization.point.object]]. The expression `ranges::{}cbegin(E)` for
100
- a subexpression `E` of type `T` is expression-equivalent to:
101
 
102
- - `ranges::begin(static_cast<const T&>(E))` if `E` is an lvalue.
103
- - Otherwise, `ranges::begin(static_cast<const T&&>(E))`.
 
 
 
104
 
105
  [*Note 1*: Whenever `ranges::cbegin(E)` is a valid expression, its type
106
- models `input_or_output_iterator`. — *end note*]
 
107
 
108
  ### `ranges::cend` <a id="range.access.cend">[[range.access.cend]]</a>
109
 
110
  The name `ranges::cend` denotes a customization point object
111
- [[customization.point.object]]. The expression `ranges::cend(E)` for a
112
- subexpression `E` of type `T` is expression-equivalent to:
113
 
114
- - `ranges::end(static_cast<const T&>(E))` if `E` is an lvalue.
115
- - Otherwise, `ranges::end(static_cast<const T&&>(E))`.
 
 
 
116
 
117
  [*Note 1*: Whenever `ranges::cend(E)` is a valid expression, the types
118
- `S` and `I` of `ranges::cend(E)` and `ranges::cbegin(E)` model
119
- `sentinel_for<S, I>`. *end note*]
 
120
 
121
  ### `ranges::rbegin` <a id="range.access.rbegin">[[range.access.rbegin]]</a>
122
 
123
  The name `ranges::rbegin` denotes a customization point object
124
  [[customization.point.object]].
@@ -126,29 +121,21 @@ The name `ranges::rbegin` denotes a customization point object
126
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
127
  denotes the reified object for `E`. Then:
128
 
129
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
130
  `false`, `ranges::rbegin(E)` is ill-formed.
131
- - Otherwise, if `T` is an array type [[basic.compound]] and
132
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rbegin(E)`
133
  is ill-formed with no diagnostic required.
134
- - Otherwise, if `decay-copy(t.rbegin())` is a valid expression whose
135
- type models `input_or_output_iterator`, `ranges::rbegin(E)` is
136
- expression-equivalent to `decay-copy(t.rbegin())`.
137
- - Otherwise, if `T` is a class or enumeration type and
138
- `decay-copy(rbegin(t))` is a valid expression whose type models
139
- `input_or_output_iterator` with overload resolution performed in a
140
- context in which unqualified lookup for `rbegin` finds only the
141
- declarations
142
- ``` cpp
143
- void rbegin(auto&) = delete;
144
- void rbegin(const auto&) = delete;
145
- ```
146
-
147
- then `ranges::rbegin(E)` is expression-equivalent to
148
- `decay-copy(rbegin(t))` with overload resolution performed in the
149
- above context.
150
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
151
  expressions of the same type which models `bidirectional_iterator`
152
  [[iterator.concept.bidir]], `ranges::rbegin(E)` is
153
  expression-equivalent to `make_reverse_iterator(ranges::end(t))`.
154
  - Otherwise, `ranges::rbegin(E)` is ill-formed.
@@ -168,30 +155,22 @@ The name `ranges::rend` denotes a customization point object
168
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
169
  denotes the reified object for `E`. Then:
170
 
171
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
172
  `false`, `ranges::rend(E)` is ill-formed.
173
- - Otherwise, if `T` is an array type [[basic.compound]] and
174
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rend(E)` is
175
  ill-formed with no diagnostic required.
176
- - Otherwise, if `decay-copy(t.rend())` is a valid expression whose type
177
- models `sentinel_for<decltype(ranges::rbegin(E))>` then
178
- `ranges::rend(E)` is expression-equivalent to
179
- `decay-copy(t.rend({}))`.
180
- - Otherwise, if `T` is a class or enumeration type and
181
- `decay-copy(rend(t))` is a valid expression whose type models
182
- `sentinel_for<decltype(ranges::rbegin(E))>` with overload resolution
183
- performed in a context in which unqualified lookup for `rend` finds
184
- only the declarations
185
- ``` cpp
186
- void rend(auto&) = delete;
187
- void rend(const auto&) = delete;
188
- ```
189
-
190
- then `ranges::rend(E)` is expression-equivalent to
191
- `decay-copy(rend(t))` with overload resolution performed in the above
192
- context.
193
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
194
  expressions of the same type which models `bidirectional_iterator`
195
  [[iterator.concept.bidir]], then `ranges::rend(E)` is
196
  expression-equivalent to `make_reverse_iterator(ranges::begin(t))`.
197
  - Otherwise, `ranges::rend(E)` is ill-formed.
@@ -199,67 +178,69 @@ denotes the reified object for `E`. Then:
199
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
200
  failure when `ranges::rend(E)` appears in the immediate context of a
201
  template instantiation. — *end note*]
202
 
203
  [*Note 2*: Whenever `ranges::rend(E)` is a valid expression, the types
204
- `S` and `I` of `ranges::rend(E)` and `ranges::rbegin(E)` model
205
- `sentinel_for<S, I>`. — *end note*]
206
 
207
  ### `ranges::crbegin` <a id="range.access.crbegin">[[range.access.crbegin]]</a>
208
 
209
  The name `ranges::crbegin` denotes a customization point object
210
- [[customization.point.object]]. The expression `ranges::{}crbegin(E)`
211
- for a subexpression `E` of type `T` is expression-equivalent to:
212
 
213
- - `ranges::{}rbegin(static_cast<const T&>(E))` if `E` is an lvalue.
214
- - Otherwise, `ranges::rbegin(static_cast<const T&&>(E))`.
 
 
 
215
 
216
  [*Note 1*: Whenever `ranges::crbegin(E)` is a valid expression, its
217
- type models `input_or_output_iterator`. — *end note*]
 
218
 
219
  ### `ranges::crend` <a id="range.access.crend">[[range.access.crend]]</a>
220
 
221
  The name `ranges::crend` denotes a customization point object
222
- [[customization.point.object]]. The expression `ranges::{}crend(E)` for
223
- a subexpression `E` of type `T` is expression-equivalent to:
224
 
225
- - `ranges::rend(static_cast<const T&>(E))` if `E` is an lvalue.
226
- - Otherwise, `ranges::rend(static_cast<const T&&>(E))`.
 
 
 
227
 
228
  [*Note 1*: Whenever `ranges::crend(E)` is a valid expression, the types
229
- `S` and `I` of `ranges::crend(E)` and `ranges::crbegin(E)` model
230
- `sentinel_for<S, I>`. *end note*]
 
 
231
 
232
  ### `ranges::size` <a id="range.prim.size">[[range.prim.size]]</a>
233
 
234
  The name `ranges::size` denotes a customization point object
235
  [[customization.point.object]].
236
 
237
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
238
  denotes the reified object for `E`. Then:
239
 
240
- - If `T` is an array of unknown bound [[dcl.array]], `ranges::size(E)`
241
- is ill-formed.
242
  - Otherwise, if `T` is an array type, `ranges::size(E)` is
243
- expression-equivalent to `decay-copy(extent_v<T>)`.
244
  - Otherwise, if `disable_sized_range<remove_cv_t<T>>` [[range.sized]] is
245
- `false` and `decay-copy(t.size())` is a valid expression of
246
- integer-like type [[iterator.concept.winc]], `ranges::size(E)` is
247
- expression-equivalent to `decay-copy(t.size())`.
248
  - Otherwise, if `T` is a class or enumeration type,
249
- `disable_sized_range<remove_cv_t<T>>` is `false` and
250
- `decay-copy(size(t))` is a valid expression of integer-like type with
251
- overload resolution performed in a context in which unqualified lookup
252
- for `size` finds only the declarations
253
- ``` cpp
254
- void size(auto&) = delete;
255
- void size(const auto&) = delete;
256
- ```
257
-
258
- then `ranges::size(E)` is expression-equivalent to
259
- `decay-copy(size(t))` with overload resolution performed in the above
260
- context.
261
  - Otherwise, if `to-unsigned-like(ranges::end(t) - ranges::begin(t))`
262
  [[ranges.syn]] is a valid expression and the types `I` and `S` of
263
  `ranges::begin(t)` and `ranges::end(t)` (respectively) model both
264
  `sized_sentinel_for<S, I>` [[iterator.concept.sizedsentinel]] and
265
  `forward_iterator<I>`, then `ranges::size(E)` is expression-equivalent
@@ -274,26 +255,28 @@ template instantiation. — *end note*]
274
  is integer-like. — *end note*]
275
 
276
  ### `ranges::ssize` <a id="range.prim.ssize">[[range.prim.ssize]]</a>
277
 
278
  The name `ranges::ssize` denotes a customization point object
279
- [[customization.point.object]]. The expression `ranges::ssize({}E)` for
280
- a subexpression `E` of type `T` is expression-equivalent to:
281
 
282
- - If `range_difference_t<T>` has width less than `ptrdiff_t`,
283
- `static_cast<ptrdiff_t>(ranges::{}size(E))`.
284
- - Otherwise, `static_cast<range_difference_t<T>>(ranges::size(E))`.
 
 
 
285
 
286
  ### `ranges::empty` <a id="range.prim.empty">[[range.prim.empty]]</a>
287
 
288
  The name `ranges::empty` denotes a customization point object
289
  [[customization.point.object]].
290
 
291
- Given a subexpression `ranges::empty(E)` with type `T`, let `t` be an
292
- lvalue that denotes the reified object for `E`. Then:
293
 
294
- - If `T` is an array of unknown bound [[basic.compound]],
295
  `ranges::empty(E)` is ill-formed.
296
  - Otherwise, if `bool(t.empty())` is a valid expression,
297
  `ranges::empty(E)` is expression-equivalent to `bool(t.empty())`.
298
  - Otherwise, if `(ranges::size(t) == 0)` is a valid expression,
299
  `ranges::empty(E)` is expression-equivalent to
@@ -319,19 +302,19 @@ The name `ranges::data` denotes a customization point object
319
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
320
  denotes the reified object for `E`. Then:
321
 
322
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
323
  `false`, `ranges::data(E)` is ill-formed.
324
- - Otherwise, if `T` is an array type [[basic.compound]] and
325
  `remove_all_extents_t<T>` is an incomplete type, `ranges::data(E)` is
326
  ill-formed with no diagnostic required.
327
- - Otherwise, if `decay-copy(t.data())` is a valid expression of pointer
328
- to object type, `ranges::data(E)` is expression-equivalent to
329
- `decay-copy(t.data())`.
330
  - Otherwise, if `ranges::begin(t)` is a valid expression whose type
331
  models `contiguous_iterator`, `ranges::data(E)` is
332
- expression-equivalent to `to_address(ranges::begin(E))`.
333
  - Otherwise, `ranges::data(E)` is ill-formed.
334
 
335
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
336
  failure when `ranges::data(E)` appears in the immediate context of a
337
  template instantiation. — *end note*]
@@ -339,15 +322,22 @@ template instantiation. — *end note*]
339
  [*Note 2*: Whenever `ranges::data(E)` is a valid expression, it has
340
  pointer to object type. — *end note*]
341
 
342
  ### `ranges::cdata` <a id="range.prim.cdata">[[range.prim.cdata]]</a>
343
 
 
 
 
 
 
344
  The name `ranges::cdata` denotes a customization point object
345
- [[customization.point.object]]. The expression `ranges::{}cdata(E)` for
346
- a subexpression `E` of type `T` is expression-equivalent to:
347
 
348
- - `ranges::data(static_cast<const T&>(E))` if `E` is an lvalue.
349
- - Otherwise, `ranges::data(static_cast<const T&&>(E))`.
 
 
350
 
351
  [*Note 1*: Whenever `ranges::cdata(E)` is a valid expression, it has
352
- pointer to object type. — *end note*]
353
 
 
1
  ## Range access <a id="range.access">[[range.access]]</a>
2
 
3
+ ### General <a id="range.access.general">[[range.access.general]]</a>
4
+
5
  In addition to being available via inclusion of the `<ranges>` header,
6
  the customization point objects in [[range.access]] are available when
7
  `<iterator>` is included.
8
 
9
+ Within [[range.access]], the *reified object* of a subexpression `E`
10
  denotes
11
 
12
  - the same object as `E` if `E` is a glvalue, or
13
  - the result of applying the temporary materialization conversion
14
  [[conv.rval]] to `E` otherwise.
 
21
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
22
  denotes the reified object for `E`. Then:
23
 
24
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
25
  `false`, `ranges::begin(E)` is ill-formed.
26
+ - Otherwise, if `T` is an array type [[term.array.type]] and
27
  `remove_all_extents_t<T>` is an incomplete type, `ranges::begin(E)` is
28
  ill-formed with no diagnostic required.
29
  - Otherwise, if `T` is an array type, `ranges::begin(E)` is
30
  expression-equivalent to `t + 0`.
31
+ - Otherwise, if `auto(t.begin())` is a valid expression whose type
32
  models `input_or_output_iterator`, `ranges::begin(E)` is
33
+ expression-equivalent to `auto(t.begin())`.
34
+ - Otherwise, if `T` is a class or enumeration type and `auto(begin(t))`
35
+ is a valid expression whose type models `input_or_output_iterator`
36
+ where the meaning of `begin` is established as-if by performing
37
+ argument-dependent lookup only [[basic.lookup.argdep]], then
38
+ `ranges::begin(E)` is expression-equivalent to that expression.
 
 
 
 
 
 
 
 
39
  - Otherwise, `ranges::begin(E)` is ill-formed.
40
 
41
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
42
  failure when `ranges::begin(E)` appears in the immediate context of a
43
  template instantiation. — *end note*]
 
53
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
54
  denotes the reified object for `E`. Then:
55
 
56
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
57
  `false`, `ranges::end(E)` is ill-formed.
58
+ - Otherwise, if `T` is an array type [[term.array.type]] and
59
  `remove_all_extents_t<T>` is an incomplete type, `ranges::end(E)` is
60
  ill-formed with no diagnostic required.
61
  - Otherwise, if `T` is an array of unknown bound, `ranges::end(E)` is
62
  ill-formed.
63
  - Otherwise, if `T` is an array, `ranges::end(E)` is
64
  expression-equivalent to `t + extent_v<T>`.
65
+ - Otherwise, if `auto(t.end())` is a valid expression whose type models
66
+ `sentinel_for<iterator_t<T>>` then `ranges::end(E)` is
67
+ expression-equivalent to `auto(t.end())`.
68
+ - Otherwise, if `T` is a class or enumeration type and `auto(end(t))` is
69
+ a valid expression whose type models `sentinel_for<iterator_t<T>>`
70
+ where the meaning of `end` is established as-if by performing
71
+ argument-dependent lookup only [[basic.lookup.argdep]], then
72
+ `ranges::end(E)` is expression-equivalent to that expression.
 
 
 
 
 
 
 
73
  - Otherwise, `ranges::end(E)` is ill-formed.
74
 
75
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
76
  failure when `ranges::end(E)` appears in the immediate context of a
77
  template instantiation. — *end note*]
 
81
  `sentinel_for<S, I>`. — *end note*]
82
 
83
  ### `ranges::cbegin` <a id="range.access.cbegin">[[range.access.cbegin]]</a>
84
 
85
  The name `ranges::cbegin` denotes a customization point object
86
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
87
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
88
 
89
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
90
+ `false`, `ranges::cbegin(E)` is ill-formed.
91
+ - Otherwise, let `U` be `ranges::begin(possibly-const-range(t))`.
92
+ `ranges::cbegin(E)` is expression-equivalent to
93
+ `const_iterator<decltype(U)>(U)`.
94
 
95
  [*Note 1*: Whenever `ranges::cbegin(E)` is a valid expression, its type
96
+ models `input_or_output_iterator` and
97
+ `constant-iterator`. — *end note*]
98
 
99
  ### `ranges::cend` <a id="range.access.cend">[[range.access.cend]]</a>
100
 
101
  The name `ranges::cend` denotes a customization point object
102
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
103
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
104
 
105
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
106
+ `false`, `ranges::cend(E)` is ill-formed.
107
+ - Otherwise, let `U` be `ranges::end(possibly-const-range(t))`.
108
+ `ranges::cend(E)` is expression-equivalent to
109
+ `const_sentinel<decltype(U)>(U)`.
110
 
111
  [*Note 1*: Whenever `ranges::cend(E)` is a valid expression, the types
112
+ `S` and `I` of the expressions `ranges::cend(E)` and `ranges::cbegin(E)`
113
+ model `sentinel_for<S, I>`. If `S` models `input_iterator`, then `S`
114
+ also models *`constant-iterator`*. — *end note*]
115
 
116
  ### `ranges::rbegin` <a id="range.access.rbegin">[[range.access.rbegin]]</a>
117
 
118
  The name `ranges::rbegin` denotes a customization point object
119
  [[customization.point.object]].
 
121
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
122
  denotes the reified object for `E`. Then:
123
 
124
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
125
  `false`, `ranges::rbegin(E)` is ill-formed.
126
+ - Otherwise, if `T` is an array type [[term.array.type]] and
127
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rbegin(E)`
128
  is ill-formed with no diagnostic required.
129
+ - Otherwise, if `auto(t.rbegin())` is a valid expression whose type
130
+ models `input_or_output_iterator`, `ranges::rbegin(E)` is
131
+ expression-equivalent to `auto(t.rbegin())`.
132
+ - Otherwise, if `T` is a class or enumeration type and `auto(rbegin(t))`
133
+ is a valid expression whose type models `input_or_output_iterator`
134
+ where the meaning of `rbegin` is established as-if by performing
135
+ argument-dependent lookup only [[basic.lookup.argdep]], then
136
+ `ranges::rbegin(E)` is expression-equivalent to that expression.
 
 
 
 
 
 
 
 
137
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
138
  expressions of the same type which models `bidirectional_iterator`
139
  [[iterator.concept.bidir]], `ranges::rbegin(E)` is
140
  expression-equivalent to `make_reverse_iterator(ranges::end(t))`.
141
  - Otherwise, `ranges::rbegin(E)` is ill-formed.
 
155
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
156
  denotes the reified object for `E`. Then:
157
 
158
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
159
  `false`, `ranges::rend(E)` is ill-formed.
160
+ - Otherwise, if `T` is an array type [[term.array.type]] and
161
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rend(E)` is
162
  ill-formed with no diagnostic required.
163
+ - Otherwise, if `auto(t.rend())` is a valid expression whose type models
164
+ `sentinel_for<decltype({}ranges::rbegin(E))>` then `ranges::rend(E)`
165
+ is expression-equivalent to `auto(t.rend())`.
166
+ - Otherwise, if `T` is a class or enumeration type and `auto(rend(t))`
167
+ is a valid expression whose type models
168
+ `sentinel_for<decltype(ranges::rbegin(E))>` where the meaning of
169
+ `rend` is established as-if by performing argument-dependent lookup
170
+ only [[basic.lookup.argdep]], then `ranges::rend(E)` is
171
+ expression-equivalent to that expression.
 
 
 
 
 
 
 
 
172
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
173
  expressions of the same type which models `bidirectional_iterator`
174
  [[iterator.concept.bidir]], then `ranges::rend(E)` is
175
  expression-equivalent to `make_reverse_iterator(ranges::begin(t))`.
176
  - Otherwise, `ranges::rend(E)` is ill-formed.
 
178
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
179
  failure when `ranges::rend(E)` appears in the immediate context of a
180
  template instantiation. — *end note*]
181
 
182
  [*Note 2*: Whenever `ranges::rend(E)` is a valid expression, the types
183
+ `S` and `I` of the expressions `ranges::rend(E)` and `ranges::rbegin(E)`
184
+ model `sentinel_for<S, I>`. — *end note*]
185
 
186
  ### `ranges::crbegin` <a id="range.access.crbegin">[[range.access.crbegin]]</a>
187
 
188
  The name `ranges::crbegin` denotes a customization point object
189
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
190
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
191
 
192
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
193
+ `false`, `ranges::crbegin(E)` is ill-formed.
194
+ - Otherwise, let `U` be `ranges::rbegin(possibly-const-range(t))`.
195
+ `ranges::crbegin(E)` is expression-equivalent to
196
+ `const_iterator<decltype(U)>(U)`.
197
 
198
  [*Note 1*: Whenever `ranges::crbegin(E)` is a valid expression, its
199
+ type models `input_or_output_iterator` and
200
+ `constant-iterator`. — *end note*]
201
 
202
  ### `ranges::crend` <a id="range.access.crend">[[range.access.crend]]</a>
203
 
204
  The name `ranges::crend` denotes a customization point object
205
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
206
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
207
 
208
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
209
+ `false`, `ranges::crend(E)` is ill-formed.
210
+ - Otherwise, let `U` be `ranges::rend(possibly-const-range(t))`.
211
+ `ranges::crend(E)` is expression-equivalent to
212
+ `const_sentinel<decltype(U)>(U)`.
213
 
214
  [*Note 1*: Whenever `ranges::crend(E)` is a valid expression, the types
215
+ `S` and `I` of the expressions `ranges::crend(E)` and
216
+ `ranges::crbegin(E)` model `sentinel_for<S, I>`. If `S` models
217
+ `input_iterator`, then `S` also models
218
+ *`constant-iterator`*. — *end note*]
219
 
220
  ### `ranges::size` <a id="range.prim.size">[[range.prim.size]]</a>
221
 
222
  The name `ranges::size` denotes a customization point object
223
  [[customization.point.object]].
224
 
225
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
226
  denotes the reified object for `E`. Then:
227
 
228
+ - If `T` is an array of unknown bound [[term.array.type]],
229
+ `ranges::size(E)` is ill-formed.
230
  - Otherwise, if `T` is an array type, `ranges::size(E)` is
231
+ expression-equivalent to `auto(extent_v<T>)`.
232
  - Otherwise, if `disable_sized_range<remove_cv_t<T>>` [[range.sized]] is
233
+ `false` and `auto(t.size())` is a valid expression of integer-like
234
+ type [[iterator.concept.winc]], `ranges::size(E)` is
235
+ expression-equivalent to `auto({}t.size())`.
236
  - Otherwise, if `T` is a class or enumeration type,
237
+ `disable_sized_range<remove_cv_t<T>>` is `false` and `auto(size(t))`
238
+ is a valid expression of integer-like type where the meaning of `size`
239
+ is established as-if by performing argument-dependent lookup only
240
+ [[basic.lookup.argdep]], then `ranges::size(E)` is
241
+ expression-equivalent to that expression.
 
 
 
 
 
 
 
242
  - Otherwise, if `to-unsigned-like(ranges::end(t) - ranges::begin(t))`
243
  [[ranges.syn]] is a valid expression and the types `I` and `S` of
244
  `ranges::begin(t)` and `ranges::end(t)` (respectively) model both
245
  `sized_sentinel_for<S, I>` [[iterator.concept.sizedsentinel]] and
246
  `forward_iterator<I>`, then `ranges::size(E)` is expression-equivalent
 
255
  is integer-like. — *end note*]
256
 
257
  ### `ranges::ssize` <a id="range.prim.ssize">[[range.prim.ssize]]</a>
258
 
259
  The name `ranges::ssize` denotes a customization point object
260
+ [[customization.point.object]].
 
261
 
262
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
263
+ denotes the reified object for `E`. If `ranges::size(t)` is ill-formed,
264
+ `ranges::ssize(E)` is ill-formed. Otherwise let `D` be
265
+ `make-signed-like-t<decltype(ranges::{}size(t))>`, or `ptrdiff_t` if it
266
+ is wider than that type; `ranges::ssize(E)` is expression-equivalent to
267
+ `static_cast<D>(ranges::size(t))`.
268
 
269
  ### `ranges::empty` <a id="range.prim.empty">[[range.prim.empty]]</a>
270
 
271
  The name `ranges::empty` denotes a customization point object
272
  [[customization.point.object]].
273
 
274
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
275
+ denotes the reified object for `E`. Then:
276
 
277
+ - If `T` is an array of unknown bound [[term.array.type]],
278
  `ranges::empty(E)` is ill-formed.
279
  - Otherwise, if `bool(t.empty())` is a valid expression,
280
  `ranges::empty(E)` is expression-equivalent to `bool(t.empty())`.
281
  - Otherwise, if `(ranges::size(t) == 0)` is a valid expression,
282
  `ranges::empty(E)` is expression-equivalent to
 
302
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
303
  denotes the reified object for `E`. Then:
304
 
305
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
306
  `false`, `ranges::data(E)` is ill-formed.
307
+ - Otherwise, if `T` is an array type [[term.array.type]] and
308
  `remove_all_extents_t<T>` is an incomplete type, `ranges::data(E)` is
309
  ill-formed with no diagnostic required.
310
+ - Otherwise, if `auto(t.data())` is a valid expression of pointer to
311
+ object type, `ranges::data(E)` is expression-equivalent to
312
+ `auto(t.data())`.
313
  - Otherwise, if `ranges::begin(t)` is a valid expression whose type
314
  models `contiguous_iterator`, `ranges::data(E)` is
315
+ expression-equivalent to `to_address(ranges::begin(t))`.
316
  - Otherwise, `ranges::data(E)` is ill-formed.
317
 
318
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
319
  failure when `ranges::data(E)` appears in the immediate context of a
320
  template instantiation. — *end note*]
 
322
  [*Note 2*: Whenever `ranges::data(E)` is a valid expression, it has
323
  pointer to object type. — *end note*]
324
 
325
  ### `ranges::cdata` <a id="range.prim.cdata">[[range.prim.cdata]]</a>
326
 
327
+ ``` cpp
328
+ template<class T>
329
+ constexpr auto as-const-pointer(const T* p) { return p; } // exposition only
330
+ ```
331
+
332
  The name `ranges::cdata` denotes a customization point object
333
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
334
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
335
 
336
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
337
+ `false`, `ranges::cdata(E)` is ill-formed.
338
+ - Otherwise, `ranges::cdata(E)` is expression-equivalent to
339
+ `as-const-pointer(ranges::data(possibly-const-range(t)))`.
340
 
341
  [*Note 1*: Whenever `ranges::cdata(E)` is a valid expression, it has
342
+ pointer to constant object type. — *end note*]
343