From Jason Turner

[mdspan.layout]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpfgbub1f9/{from.md → to.md} +871 -0
tmp/tmpfgbub1f9/{from.md → to.md} RENAMED
@@ -0,0 +1,871 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Layout mapping <a id="mdspan.layout">[[mdspan.layout]]</a>
2
+
3
+ ##### General <a id="mdspan.layout.general">[[mdspan.layout.general]]</a>
4
+
5
+ In subclauses [[mdspan.layout.reqmts]] and
6
+ [[mdspan.layout.policy.reqmts]]:
7
+
8
+ - `M` denotes a layout mapping class.
9
+ - `m` denotes a (possibly const) value of type `M`.
10
+ - `i` and `j` are packs of (possibly const) integers that are
11
+ multidimensional indices in `m.extents()` [[mdspan.overview]].
12
+ \[*Note 1*: The type of each element of the packs can be a different
13
+ integer type. — *end note*]
14
+ - `r` is a (possibly const) rank index of `typename M::extents_type`.
15
+ - `dᵣ` is a pack of (possibly const) integers for which
16
+ `sizeof...(dᵣ) == M::extents_type::rank()` is `true`, the rᵗʰ element
17
+ is equal to 1, and all other elements are equal to 0.
18
+
19
+ In subclauses [[mdspan.layout.reqmts]] through [[mdspan.layout.stride]],
20
+ let *`is-mapping-of`* be the exposition-only variable template defined
21
+ as follows:
22
+
23
+ ``` cpp
24
+ template<class Layout, class Mapping>
25
+ constexpr bool is-mapping-of = // exposition only
26
+ is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
27
+ ```
28
+
29
+ ##### Requirements <a id="mdspan.layout.reqmts">[[mdspan.layout.reqmts]]</a>
30
+
31
+ A type `M` meets the *layout mapping* requirements if
32
+
33
+ - `M` models `copyable` and `equality_comparable`,
34
+ - `is_nothrow_move_constructible_v<M>` is `true`,
35
+ - `is_nothrow_move_assignable_v<M>` is `true`,
36
+ - `is_nothrow_swappable_v<M>` is `true`, and
37
+ - the following types and expressions are well-formed and have the
38
+ specified semantics.
39
+
40
+ ``` cpp
41
+ typename M::extents_type
42
+ ```
43
+
44
+ *Result:* A type that is a specialization of `extents`.
45
+
46
+ ``` cpp
47
+ typename M::index_type
48
+ ```
49
+
50
+ *Result:* `typename M::extents_type::index_type`.
51
+
52
+ ``` cpp
53
+ typename M::rank_type
54
+ ```
55
+
56
+ *Result:* `typename M::extents_type::rank_type`.
57
+
58
+ ``` cpp
59
+ typename M::layout_type
60
+ ```
61
+
62
+ *Result:* A type `MP` that meets the layout mapping policy
63
+ requirements [[mdspan.layout.policy.reqmts]] and for which
64
+ *`is-mapping-of`*`<MP, M>` is `true`.
65
+
66
+ ``` cpp
67
+ m.extents()
68
+ ```
69
+
70
+ *Result:* `const typename M::extents_type&`
71
+
72
+ ``` cpp
73
+ m(i...)
74
+ ```
75
+
76
+ *Result:* `typename M::index_type`
77
+
78
+ *Returns:* A nonnegative integer less than
79
+ `numeric_limits<typename M::index_type>::max()` and less than or equal
80
+ to `numeric_limits<size_t>::max()`.
81
+
82
+ ``` cpp
83
+ m(i...) == m(static_cast<typename M::index_type>(i)...)
84
+ ```
85
+
86
+ *Result:* `bool`
87
+
88
+ *Returns:* `true`
89
+
90
+ ``` cpp
91
+ m.required_span_size()
92
+ ```
93
+
94
+ *Result:* `typename M::index_type`
95
+
96
+ *Returns:* If the size of the multidimensional index space `m.extents()`
97
+ is 0, then `0`, else `1` plus the maximum value of `m(i...)` for all
98
+ `i`.
99
+
100
+ ``` cpp
101
+ m.is_unique()
102
+ ```
103
+
104
+ *Result:* `bool`
105
+
106
+ *Returns:* `true` only if for every `i` and `j` where `(i != j || ...)`
107
+ is `true`, `m(i...) != m(j...)` is `true`.
108
+
109
+ [*Note 1*: A mapping can return `false` even if the condition is met.
110
+ For certain layouts, it is possibly not feasible to determine
111
+ efficiently whether the layout is unique. — *end note*]
112
+
113
+ ``` cpp
114
+ m.is_exhaustive()
115
+ ```
116
+
117
+ *Result:* `bool`
118
+
119
+ *Returns:* `true` only if for all k in the range
120
+ [0, `m.required_span_size()`) there exists an `i` such that `m(i...)`
121
+ equals k.
122
+
123
+ [*Note 2*: A mapping can return `false` even if the condition is met.
124
+ For certain layouts, it is possibly not feasible to determine
125
+ efficiently whether the layout is exhaustive. — *end note*]
126
+
127
+ ``` cpp
128
+ m.is_strided()
129
+ ```
130
+
131
+ *Result:* `bool`
132
+
133
+ *Returns:* `true` only if for every rank index r of `m.extents()` there
134
+ exists an integer sᵣ such that, for all `i` where (`i`+dᵣ) is a
135
+ multidimensional index in `m.extents()` [[mdspan.overview]],
136
+ `m((i + `dᵣ`)...) - m(i...)` equals sᵣ.
137
+
138
+ [*Note 3*: This implies that for a strided layout
139
+ m(i₀, …, iₖ) = m(0, …, 0) + i₀ × s₀ + … + iₖ × sₖ. — *end note*]
140
+
141
+ [*Note 4*: A mapping can return `false` even if the condition is met.
142
+ For certain layouts, it is possibly not feasible to determine
143
+ efficiently whether the layout is strided. — *end note*]
144
+
145
+ ``` cpp
146
+ m.stride(r)
147
+ ```
148
+
149
+ *Preconditions:* `m.is_strided()` is `true`.
150
+
151
+ *Result:* `typename M::index_type`
152
+
153
+ *Returns:* sᵣ as defined in `m.is_strided()` above.
154
+
155
+ ``` cpp
156
+ M::is_always_unique()
157
+ ```
158
+
159
+ *Result:* A constant expression [[expr.const]] of type `bool`.
160
+
161
+ *Returns:* `true` only if `m.is_unique()` is `true` for all possible
162
+ objects `m` of type `M`.
163
+
164
+ [*Note 5*: A mapping can return `false` even if the above condition is
165
+ met. For certain layout mappings, it is possibly not feasible to
166
+ determine whether every instance is unique. — *end note*]
167
+
168
+ ``` cpp
169
+ M::is_always_exhaustive()
170
+ ```
171
+
172
+ *Result:* A constant expression [[expr.const]] of type `bool`.
173
+
174
+ *Returns:* `true` only if `m.is_exhaustive()` is `true` for all possible
175
+ objects `m` of type `M`.
176
+
177
+ [*Note 6*: A mapping can return `false` even if the above condition is
178
+ met. For certain layout mappings, it is possibly not feasible to
179
+ determine whether every instance is exhaustive. — *end note*]
180
+
181
+ ``` cpp
182
+ M::is_always_strided()
183
+ ```
184
+
185
+ *Result:* A constant expression [[expr.const]] of type `bool`.
186
+
187
+ *Returns:* `true` only if `m.is_strided()` is `true` for all possible
188
+ objects `m` of type `M`.
189
+
190
+ [*Note 7*: A mapping can return `false` even if the above condition is
191
+ met. For certain layout mappings, it is possibly not feasible to
192
+ determine whether every instance is strided. — *end note*]
193
+
194
+ ##### Layout mapping policy requirements <a id="mdspan.layout.policy.reqmts">[[mdspan.layout.policy.reqmts]]</a>
195
+
196
+ A type `MP` meets the *layout mapping policy* requirements if for a type
197
+ `E` that is a specialization of `extents`, `MP::mapping<E>` is valid and
198
+ denotes a type `X` that meets the layout mapping requirements
199
+ [[mdspan.layout.reqmts]], and for which the *qualified-id*
200
+ `X::layout_type` is valid and denotes the type `MP` and the
201
+ *qualified-id* `X::extents_type` denotes `E`.
202
+
203
+ ##### Layout mapping policies <a id="mdspan.layout.policy.overview">[[mdspan.layout.policy.overview]]</a>
204
+
205
+ ``` cpp
206
+ namespace std {
207
+ struct layout_left {
208
+ template<class Extents>
209
+ class mapping;
210
+ };
211
+ struct layout_right {
212
+ template<class Extents>
213
+ class mapping;
214
+ };
215
+ struct layout_stride {
216
+ template<class Extents>
217
+ class mapping;
218
+ };
219
+ }
220
+ ```
221
+
222
+ Each of `layout_left`, `layout_right`, and `layout_stride` meets the
223
+ layout mapping policy requirements and is a trivial type.
224
+
225
+ ##### Class template `layout_left::mapping` <a id="mdspan.layout.left">[[mdspan.layout.left]]</a>
226
+
227
+ ###### Overview <a id="mdspan.layout.left.overview">[[mdspan.layout.left.overview]]</a>
228
+
229
+ `layout_left` provides a layout mapping where the leftmost extent has
230
+ stride 1, and strides increase left-to-right as the product of extents.
231
+
232
+ ``` cpp
233
+ namespace std {
234
+ template<class Extents>
235
+ class layout_left::mapping {
236
+ public:
237
+ using extents_type = Extents;
238
+ using index_type = typename extents_type::index_type;
239
+ using size_type = typename extents_type::size_type;
240
+ using rank_type = typename extents_type::rank_type;
241
+ using layout_type = layout_left;
242
+
243
+ // [mdspan.layout.left.cons], constructors
244
+ constexpr mapping() noexcept = default;
245
+ constexpr mapping(const mapping&) noexcept = default;
246
+ constexpr mapping(const extents_type&) noexcept;
247
+ template<class OtherExtents>
248
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
249
+ mapping(const mapping<OtherExtents>&) noexcept;
250
+ template<class OtherExtents>
251
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
252
+ mapping(const layout_right::mapping<OtherExtents>&) noexcept;
253
+ template<class OtherExtents>
254
+ constexpr explicit(extents_type::rank() > 0)
255
+ mapping(const layout_stride::mapping<OtherExtents>&);
256
+
257
+ constexpr mapping& operator=(const mapping&) noexcept = default;
258
+
259
+ // [mdspan.layout.left.obs], observers
260
+ constexpr const extents_type& extents() const noexcept { return extents_; }
261
+
262
+ constexpr index_type required_span_size() const noexcept;
263
+
264
+ template<class... Indices>
265
+ constexpr index_type operator()(Indices...) const noexcept;
266
+
267
+ static constexpr bool is_always_unique() noexcept { return true; }
268
+ static constexpr bool is_always_exhaustive() noexcept { return true; }
269
+ static constexpr bool is_always_strided() noexcept { return true; }
270
+
271
+ static constexpr bool is_unique() noexcept { return true; }
272
+ static constexpr bool is_exhaustive() noexcept { return true; }
273
+ static constexpr bool is_strided() noexcept { return true; }
274
+
275
+ constexpr index_type stride(rank_type) const noexcept;
276
+
277
+ template<class OtherExtents>
278
+ friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
279
+
280
+ private:
281
+ extents_type extents_{}; // exposition only
282
+ };
283
+ }
284
+ ```
285
+
286
+ If `Extents` is not a specialization of `extents`, then the program is
287
+ ill-formed.
288
+
289
+ `layout_left::mapping<E>` is a trivially copyable type that models
290
+ `regular` for each `E`.
291
+
292
+ *Mandates:* If `Extents::rank_dynamic() == 0` is `true`, then the size
293
+ of the multidimensional index space `Extents()` is representable as a
294
+ value of type `typename Extents::index_type`.
295
+
296
+ ###### Constructors <a id="mdspan.layout.left.cons">[[mdspan.layout.left.cons]]</a>
297
+
298
+ ``` cpp
299
+ constexpr mapping(const extents_type& e) noexcept;
300
+ ```
301
+
302
+ *Preconditions:* The size of the multidimensional index space `e` is
303
+ representable as a value of type `index_type` [[basic.fundamental]].
304
+
305
+ *Effects:* Direct-non-list-initializes *extents\_* with `e`.
306
+
307
+ ``` cpp
308
+ template<class OtherExtents>
309
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
310
+ mapping(const mapping<OtherExtents>& other) noexcept;
311
+ ```
312
+
313
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
314
+ `true`.
315
+
316
+ *Preconditions:* `other.required_span_size()` is representable as a
317
+ value of type `index_type` [[basic.fundamental]].
318
+
319
+ *Effects:* Direct-non-list-initializes *extents\_* with
320
+ `other.extents()`.
321
+
322
+ ``` cpp
323
+ template<class OtherExents>
324
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
325
+ mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
326
+ ```
327
+
328
+ *Constraints:*
329
+
330
+ - `extents_type::rank() <= 1` is `true`, and
331
+ - `is_constructible_v<extents_type, OtherExtents>` is `true`.
332
+
333
+ *Preconditions:* `other.required_span_size()` is representable as a
334
+ value of type `index_type` [[basic.fundamental]].
335
+
336
+ *Effects:* Direct-non-list-initializes *extents\_* with
337
+ `other.extents()`.
338
+
339
+ ``` cpp
340
+ template<class OtherExtents>
341
+ constexpr explicit(extents_type::rank() > 0)
342
+ mapping(const layout_stride::mapping<OtherExtents>& other);
343
+ ```
344
+
345
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
346
+ `true`.
347
+
348
+ *Preconditions:*
349
+
350
+ - If `extents_type::rank() > 0` is `true`, then for all r in the range
351
+ [0, `extents_type::rank()`), `other.stride(`r`)` equals
352
+ `other.extents().`*`fwd-prod-of-extents`*`(`r`)`, and
353
+ - `other.required_span_size()` is representable as a value of type
354
+ `index_type` [[basic.fundamental]].
355
+
356
+ *Effects:* Direct-non-list-initializes *extents\_* with
357
+ `other.extents()`.
358
+
359
+ ###### Observers <a id="mdspan.layout.left.obs">[[mdspan.layout.left.obs]]</a>
360
+
361
+ ``` cpp
362
+ constexpr index_type required_span_size() const noexcept;
363
+ ```
364
+
365
+ *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
366
+
367
+ ``` cpp
368
+ template<class... Indices>
369
+ constexpr index_type operator()(Indices... i) const noexcept;
370
+ ```
371
+
372
+ *Constraints:*
373
+
374
+ - `sizeof...(Indices) == extents_type::rank()` is `true`,
375
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`, and
376
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
377
+
378
+ *Preconditions:* `extents_type::`*`index-cast`*`(i)` is a
379
+ multidimensional index in *extents\_*[[mdspan.overview]].
380
+
381
+ *Effects:* Let `P` be a parameter pack such that
382
+
383
+ ``` cpp
384
+ is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
385
+ ```
386
+
387
+ is `true`. Equivalent to:
388
+
389
+ ``` cpp
390
+ return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
391
+ ```
392
+
393
+ ``` cpp
394
+ constexpr index_type stride(rank_type i) const;
395
+ ```
396
+
397
+ *Constraints:* `extents_type::rank() > 0` is `true`.
398
+
399
+ *Preconditions:* `i < extents_type::rank()` is `true`.
400
+
401
+ *Returns:* `extents().`*`fwd-prod-of-extents`*`(i)`.
402
+
403
+ ``` cpp
404
+ template<class OtherExtents>
405
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
406
+ ```
407
+
408
+ *Constraints:* `extents_type::rank() == OtherExtents::rank()` is `true`.
409
+
410
+ *Effects:* Equivalent to: `return x.extents() == y.extents();`
411
+
412
+ ##### Class template `layout_right::mapping` <a id="mdspan.layout.right">[[mdspan.layout.right]]</a>
413
+
414
+ ###### Overview <a id="mdspan.layout.right.overview">[[mdspan.layout.right.overview]]</a>
415
+
416
+ `layout_right` provides a layout mapping where the rightmost extent is
417
+ stride 1, and strides increase right-to-left as the product of extents.
418
+
419
+ ``` cpp
420
+ namespace std {
421
+ template<class Extents>
422
+ class layout_right::mapping {
423
+ public:
424
+ using extents_type = Extents;
425
+ using index_type = typename extents_type::index_type;
426
+ using size_type = typename extents_type::size_type;
427
+ using rank_type = typename extents_type::rank_type;
428
+ using layout_type = layout_right;
429
+
430
+ // [mdspan.layout.right.cons], constructors
431
+ constexpr mapping() noexcept = default;
432
+ constexpr mapping(const mapping&) noexcept = default;
433
+ constexpr mapping(const extents_type&) noexcept;
434
+ template<class OtherExtents>
435
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
436
+ mapping(const mapping<OtherExtents>&) noexcept;
437
+ template<class OtherExtents>
438
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
439
+ mapping(const layout_left::mapping<OtherExtents>&) noexcept;
440
+ template<class OtherExtents>
441
+ constexpr explicit(extents_type::rank() > 0)
442
+ mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
443
+
444
+ constexpr mapping& operator=(const mapping&) noexcept = default;
445
+
446
+ // [mdspan.layout.right.obs], observers
447
+ constexpr const extents_type& extents() const noexcept { return extents_; }
448
+
449
+ constexpr index_type required_span_size() const noexcept;
450
+
451
+ template<class... Indices>
452
+ constexpr index_type operator()(Indices...) const noexcept;
453
+
454
+ static constexpr bool is_always_unique() noexcept { return true; }
455
+ static constexpr bool is_always_exhaustive() noexcept { return true; }
456
+ static constexpr bool is_always_strided() noexcept { return true; }
457
+
458
+ static constexpr bool is_unique() noexcept { return true; }
459
+ static constexpr bool is_exhaustive() noexcept { return true; }
460
+ static constexpr bool is_strided() noexcept { return true; }
461
+
462
+ constexpr index_type stride(rank_type) const noexcept;
463
+
464
+ template<class OtherExtents>
465
+ friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
466
+
467
+ private:
468
+ extents_type extents_{}; // exposition only
469
+ };
470
+ }
471
+ ```
472
+
473
+ If `Extents` is not a specialization of `extents`, then the program is
474
+ ill-formed.
475
+
476
+ `layout_right::mapping<E>` is a trivially copyable type that models
477
+ `regular` for each `E`.
478
+
479
+ *Mandates:* If `Extents::rank_dynamic() == 0` is `true`, then the size
480
+ of the multidimensional index space `Extents()` is representable as a
481
+ value of type `typename Extents::index_type`.
482
+
483
+ ###### Constructors <a id="mdspan.layout.right.cons">[[mdspan.layout.right.cons]]</a>
484
+
485
+ ``` cpp
486
+ constexpr mapping(const extents_type& e) noexcept;
487
+ ```
488
+
489
+ *Preconditions:* The size of the multidimensional index space `e` is
490
+ representable as a value of type `index_type` [[basic.fundamental]].
491
+
492
+ *Effects:* Direct-non-list-initializes *extents\_* with `e`.
493
+
494
+ ``` cpp
495
+ template<class OtherExtents>
496
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
497
+ mapping(const mapping<OtherExtents>& other) noexcept;
498
+ ```
499
+
500
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
501
+ `true`.
502
+
503
+ *Preconditions:* `other.required_span_size()` is representable as a
504
+ value of type `index_type` [[basic.fundamental]].
505
+
506
+ *Effects:* Direct-non-list-initializes *extents\_* with
507
+ `other.extents()`.
508
+
509
+ ``` cpp
510
+ template<class OtherExtents>
511
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
512
+ mapping(const layout_left::mapping<OtherExtents>& other) noexcept;
513
+ ```
514
+
515
+ *Constraints:*
516
+
517
+ - `extents_type::rank() <= 1` is `true`, and
518
+ - `is_constructible_v<extents_type, OtherExtents>` is `true`.
519
+
520
+ *Preconditions:* `other.required_span_size()` is representable as a
521
+ value of type `index_type` [[basic.fundamental]].
522
+
523
+ *Effects:* Direct-non-list-initializes *extents\_* with
524
+ `other.extents()`.
525
+
526
+ ``` cpp
527
+ template<class OtherExtents>
528
+ constexpr explicit(extents_type::rank() > 0)
529
+ mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
530
+ ```
531
+
532
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
533
+ `true`.
534
+
535
+ *Preconditions:*
536
+
537
+ - If `extents_type::rank() > 0` is `true`, then for all r in the range
538
+ [0, `extents_type::rank()`), `other.stride(`r`)` equals
539
+ `other.extents().`*`rev-prod-of-extents`*`(`r`)`.
540
+ - `other.required_span_size()` is representable as a value of type
541
+ `index_type` [[basic.fundamental]].
542
+
543
+ *Effects:* Direct-non-list-initializes *extents\_* with
544
+ `other.extents()`.
545
+
546
+ ###### Observers <a id="mdspan.layout.right.obs">[[mdspan.layout.right.obs]]</a>
547
+
548
+ ``` cpp
549
+ index_type required_span_size() const noexcept;
550
+ ```
551
+
552
+ *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
553
+
554
+ ``` cpp
555
+ template<class... Indices>
556
+ constexpr index_type operator()(Indices... i) const noexcept;
557
+ ```
558
+
559
+ *Constraints:*
560
+
561
+ - `sizeof...(Indices) == extents_type::rank()` is `true`,
562
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`, and
563
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
564
+
565
+ *Preconditions:* `extents_type::`*`index-cast`*`(i)` is a
566
+ multidimensional index in *extents\_*[[mdspan.overview]].
567
+
568
+ *Effects:* Let `P` be a parameter pack such that
569
+
570
+ ``` cpp
571
+ is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
572
+ ```
573
+
574
+ is `true`. Equivalent to:
575
+
576
+ ``` cpp
577
+ return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
578
+ ```
579
+
580
+ ``` cpp
581
+ constexpr index_type stride(rank_type i) const noexcept;
582
+ ```
583
+
584
+ *Constraints:* `extents_type::rank() > 0` is `true`.
585
+
586
+ *Preconditions:* `i < extents_type::rank()` is `true`.
587
+
588
+ *Returns:* `extents().`*`rev-prod-of-extents`*`(i)`.
589
+
590
+ ``` cpp
591
+ template<class OtherExtents>
592
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
593
+ ```
594
+
595
+ *Constraints:* `extents_type::rank() == OtherExtents::rank()` is `true`.
596
+
597
+ *Effects:* Equivalent to: `return x.extents() == y.extents();`
598
+
599
+ ##### Class template `layout_stride::mapping` <a id="mdspan.layout.stride">[[mdspan.layout.stride]]</a>
600
+
601
+ ###### Overview <a id="mdspan.layout.stride.overview">[[mdspan.layout.stride.overview]]</a>
602
+
603
+ `layout_stride` provides a layout mapping where the strides are
604
+ user-defined.
605
+
606
+ ``` cpp
607
+ namespace std {
608
+ template<class Extents>
609
+ class layout_stride::mapping {
610
+ public:
611
+ using extents_type = Extents;
612
+ using index_type = typename extents_type::index_type;
613
+ using size_type = typename extents_type::size_type;
614
+ using rank_type = typename extents_type::rank_type;
615
+ using layout_type = layout_stride;
616
+
617
+ private:
618
+ static constexpr rank_type rank_ = extents_type::rank(); // exposition only
619
+
620
+ public:
621
+ // [mdspan.layout.stride.cons], constructors
622
+ constexpr mapping() noexcept;
623
+ constexpr mapping(const mapping&) noexcept = default;
624
+ template<class OtherIndexType>
625
+ constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept;
626
+ template<class OtherIndexType>
627
+ constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept;
628
+
629
+ template<class StridedLayoutMapping>
630
+ constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;
631
+
632
+ constexpr mapping& operator=(const mapping&) noexcept = default;
633
+
634
+ // [mdspan.layout.stride.obs], observers
635
+ constexpr const extents_type& extents() const noexcept { return extents_; }
636
+ constexpr array<index_type, rank_> strides() const noexcept { return strides_; }
637
+
638
+ constexpr index_type required_span_size() const noexcept;
639
+
640
+ template<class... Indices>
641
+ constexpr index_type operator()(Indices...) const noexcept;
642
+
643
+ static constexpr bool is_always_unique() noexcept { return true; }
644
+ static constexpr bool is_always_exhaustive() noexcept { return false; }
645
+ static constexpr bool is_always_strided() noexcept { return true; }
646
+
647
+ static constexpr bool is_unique() noexcept { return true; }
648
+ constexpr bool is_exhaustive() const noexcept;
649
+ static constexpr bool is_strided() noexcept { return true; }
650
+
651
+ constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
652
+
653
+ template<class OtherMapping>
654
+ friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
655
+
656
+ private:
657
+ extents_type extents_{}; // exposition only
658
+ array<index_type, rank_> strides_{}; // exposition only
659
+ };
660
+ }
661
+ ```
662
+
663
+ If `Extents` is not a specialization of `extents`, then the program is
664
+ ill-formed.
665
+
666
+ `layout_stride::mapping<E>` is a trivially copyable type that models
667
+ `regular` for each `E`.
668
+
669
+ *Mandates:* If `Extents::rank_dynamic() == 0` is `true`, then the size
670
+ of the multidimensional index space `Extents()` is representable as a
671
+ value of type `typename Extents::index_type`.
672
+
673
+ ###### Exposition-only helpers <a id="mdspan.layout.stride.expo">[[mdspan.layout.stride.expo]]</a>
674
+
675
+ Let `REQUIRED-SPAN-SIZE(e, strides)` be:
676
+
677
+ - `1`, if `e.rank() == 0` is `true`,
678
+ - otherwise `0`, if the size of the multidimensional index space `e` is
679
+ 0,
680
+ - otherwise `1` plus the sum of products of `(e.extent(r) - 1)` and
681
+ `strides[r]` for all r in the range [0, `e.rank()`).
682
+
683
+ Let `OFFSET(m)` be:
684
+
685
+ - `m()`, if `e.rank() == 0` is `true`,
686
+ - otherwise `0`, if the size of the multidimensional index space `e` is
687
+ 0,
688
+ - otherwise `m(z...)` for a pack of integers `z` that is a
689
+ multidimensional index in `m.extents()` and each element of `z` equals
690
+ 0.
691
+
692
+ Let *`is-extents`* be the exposition-only variable template defined as
693
+ follows:
694
+
695
+ ``` cpp
696
+ template<class T>
697
+ constexpr bool is-extents = false; // exposition only
698
+ template<class IndexType, size_t... Args>
699
+ constexpr bool is-extents<extents<IndexType, Args...>> = true; // exposition only
700
+ ```
701
+
702
+ Let `layout-mapping-alike` be the exposition-only concept defined as
703
+ follows:
704
+
705
+ ``` cpp
706
+ template<class M>
707
+ concept layout-mapping-alike = requires { // exposition only
708
+ requires is-extents<typename M::extents_type>;
709
+ { M::is_always_strided() } -> same_as<bool>;
710
+ { M::is_always_exhaustive() } -> same_as<bool>;
711
+ { M::is_always_unique() } -> same_as<bool>;
712
+ bool_constant<M::is_always_strided()>::value;
713
+ bool_constant<M::is_always_exhaustive()>::value;
714
+ bool_constant<M::is_always_unique()>::value;
715
+ };
716
+ ```
717
+
718
+ [*Note 2*: This concept checks that the functions
719
+ `M::is_always_strided()`, `M::is_always_exhaustive()`, and
720
+ `M::is_always_unique()` exist, are constant expressions, and have a
721
+ return type of `bool`. — *end note*]
722
+
723
+ ###### Constructors <a id="mdspan.layout.stride.cons">[[mdspan.layout.stride.cons]]</a>
724
+
725
+ ``` cpp
726
+ constexpr mapping() noexcept;
727
+ ```
728
+
729
+ *Preconditions:*
730
+ `layout_right::mapping<extents_type>().required_span_size()` is
731
+ representable as a value of type `index_type` [[basic.fundamental]].
732
+
733
+ *Effects:* Direct-non-list-initializes *extents\_* with
734
+ `extents_type()`, and for all d in the range \[`0`, *`rank_`*),
735
+ direct-non-list-initializes *`strides_`*`[`d`]` with
736
+ `layout_right::mapping<extents_type>().stride(`d`)`.
737
+
738
+ ``` cpp
739
+ template<class OtherIndexType>
740
+ constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
741
+ template<class OtherIndexType>
742
+ constexpr mapping(const extents_type& e, const array<OtherIndexType, rank_>& s) noexcept;
743
+ ```
744
+
745
+ *Constraints:*
746
+
747
+ - `is_convertible_v<const OtherIndexType&, index_type>` is `true`, and
748
+ - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
749
+ `true`.
750
+
751
+ *Preconditions:*
752
+
753
+ - `s[`i`] > 0` is `true` for all i in the range [0, rank_).
754
+ - *`REQUIRED-SPAN-SIZE`*`(e, s)` is representable as a value of type
755
+ `index_type` [[basic.fundamental]].
756
+ - If *rank\_* is greater than 0, then there exists a permutation P of
757
+ the integers in the range [0, rank_), such that
758
+ `s[`pᵢ`] >= s[`pᵢ₋₁`] * e.extent(p`ᵢ₋₁`)` is `true` for all i in the
759
+ range [1, rank_), where pᵢ is the iᵗʰ element of P. \[*Note 3*: For
760
+ `layout_stride`, this condition is necessary and sufficient for
761
+ `is_unique()` to be `true`. — *end note*]
762
+
763
+ *Effects:* Direct-non-list-initializes *extents\_* with `e`, and for all
764
+ d in the range [0, rank_), direct-non-list-initializes `strides_[`d`]`
765
+ with `as_const(s[`d`])`.
766
+
767
+ ``` cpp
768
+ template<class StridedLayoutMapping>
769
+ constexpr explicit(see below)
770
+ mapping(const StridedLayoutMapping& other) noexcept;
771
+ ```
772
+
773
+ *Constraints:*
774
+
775
+ - `layout-mapping-alike<StridedLayoutMapping>` is satisfied.
776
+ - `is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type>`
777
+ is
778
+ `true`.
779
+ - `StridedLayoutMapping::is_always_unique()` is `true`.
780
+ - `StridedLayoutMapping::is_always_strided()` is `true`.
781
+
782
+ *Preconditions:*
783
+
784
+ - `StridedLayoutMapping` meets the layout mapping
785
+ requirements [[mdspan.layout.policy.reqmts]],
786
+ - `other.stride(`r`) > 0` is `true` for every rank index r of
787
+ `extents()`,
788
+ - `other.required_span_size()` is representable as a value of type
789
+ `index_type` [[basic.fundamental]], and
790
+ - *`OFFSET`*`(other) == 0` is `true`.
791
+
792
+ *Effects:* Direct-non-list-initializes *extents\_* with
793
+ `other.extents()`, and for all d in the range [0, rank_),
794
+ direct-non-list-initializes *`strides_`*`[`d`]` with
795
+ `other.stride(`d`)`.
796
+
797
+ Remarks: The expression inside `explicit` is equivalent to:
798
+
799
+ ``` cpp
800
+ !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
801
+ (is-mapping-of<layout_left, LayoutStrideMapping> ||
802
+ is-mapping-of<layout_right, LayoutStrideMapping> ||
803
+ is-mapping-of<layout_stride, LayoutStrideMapping>))
804
+ ```
805
+
806
+ ###### Observers <a id="mdspan.layout.stride.obs">[[mdspan.layout.stride.obs]]</a>
807
+
808
+ ``` cpp
809
+ constexpr index_type required_span_size() const noexcept;
810
+ ```
811
+
812
+ *Returns:* *`REQUIRED-SPAN-SIZE`*`(extents(), `*`strides_`*`)`.
813
+
814
+ ``` cpp
815
+ template<class... Indices>
816
+ constexpr index_type operator()(Indices... i) const noexcept;
817
+ ```
818
+
819
+ *Constraints:*
820
+
821
+ - `sizeof...(Indices) == `*`rank_`* is `true`,
822
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`, and
823
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
824
+
825
+ *Preconditions:* `extents_type::`*`index-cast`*`(i)` is a
826
+ multidimensional index in *extents\_*[[mdspan.overview]].
827
+
828
+ *Effects:* Let `P` be a parameter pack such that
829
+
830
+ ``` cpp
831
+ is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
832
+ ```
833
+
834
+ is `true`. Equivalent to:
835
+
836
+ ``` cpp
837
+ return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
838
+ ```
839
+
840
+ ``` cpp
841
+ constexpr bool is_exhaustive() const noexcept;
842
+ ```
843
+
844
+ *Returns:*
845
+
846
+ - `true` if *rank\_* is 0.
847
+ - Otherwise, `true` if there is a permutation P of the integers in the
848
+ range [0, rank_) such that `stride(`p₀`)` equals 1, and `stride(`pᵢ`)`
849
+ equals `stride(`pᵢ₋₁`) * extents().extent(`pᵢ₋₁`)` for i in the range
850
+ [1, rank_), where pᵢ is the iᵗʰ element of P.
851
+ - Otherwise, `false`.
852
+
853
+ ``` cpp
854
+ template<class OtherMapping>
855
+ friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;
856
+ ```
857
+
858
+ *Constraints:*
859
+
860
+ - `layout-mapping-alike<OtherMapping>` is satisfied.
861
+ - *`rank_`*` == OtherMapping::extents_type::rank()` is `true`.
862
+ - `OtherMapping::is_always_strided()` is `true`.
863
+
864
+ *Preconditions:* `OtherMapping` meets the layout mapping
865
+ requirements [[mdspan.layout.policy.reqmts]].
866
+
867
+ *Returns:* `true` if `x.extents() == y.extents()` is `true`,
868
+ *`OFFSET`*`(y) == 0` is `true`, and each of
869
+ `x.stride(`r`) == y.stride(`r`)` is `true` for r in the range
870
+ [0, `x.extents().rank()`). Otherwise, `false`.
871
+