From Jason Turner

[mdspan.layout]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpeybii2hx/{from.md → to.md} +1074 -28
tmp/tmpeybii2hx/{from.md → to.md} RENAMED
@@ -1,11 +1,10 @@
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]].
@@ -14,19 +13,44 @@ In subclauses [[mdspan.layout.reqmts]] and
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
 
@@ -150,20 +174,24 @@ m.stride(r)
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()
@@ -172,11 +200,11 @@ M::is_always_exhaustive()
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()
@@ -185,11 +213,11 @@ M::is_always_strided()
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
 
@@ -214,15 +242,27 @@ namespace std {
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
 
@@ -233,13 +273,13 @@ stride 1, and strides increase left-to-right as the product of extents.
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;
@@ -248,10 +288,14 @@ namespace std {
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;
@@ -277,10 +321,21 @@ namespace std {
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
@@ -318,11 +373,11 @@ 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:*
@@ -334,10 +389,44 @@ template<class OtherExents>
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
  ```
@@ -389,11 +478,11 @@ is `true`. Equivalent to:
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`.
@@ -420,13 +509,13 @@ stride 1, and strides increase right-to-left as the product of extents.
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;
@@ -435,10 +524,14 @@ namespace std {
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;
@@ -464,10 +557,21 @@ namespace std {
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
@@ -521,10 +625,46 @@ template<class OtherExtents>
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
  ```
@@ -544,11 +684,11 @@ template<class OtherExtents>
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
@@ -607,13 +747,13 @@ user-defined.
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
 
@@ -654,10 +794,21 @@ namespace std {
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
@@ -676,11 +827,15 @@ 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
@@ -748,11 +903,12 @@ template<class OtherIndexType>
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
@@ -780,11 +936,11 @@ template<class StridedLayoutMapping>
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`.
@@ -796,13 +952,15 @@ direct-non-list-initializes *`strides_`*`[`d`]` with
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
@@ -867,5 +1025,893 @@ requirements [[mdspan.layout.policy.reqmts]].
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 [[mdspan.layout.reqmts]] and [[mdspan.layout.policy.reqmts]]:
 
6
 
7
  - `M` denotes a layout mapping class.
8
  - `m` denotes a (possibly const) value of type `M`.
9
  - `i` and `j` are packs of (possibly const) integers that are
10
  multidimensional indices in `m.extents()` [[mdspan.overview]].
 
13
  - `r` is a (possibly const) rank index of `typename M::extents_type`.
14
  - `dᵣ` is a pack of (possibly const) integers for which
15
  `sizeof...(dᵣ) == M::extents_type::rank()` is `true`, the rᵗʰ element
16
  is equal to 1, and all other elements are equal to 0.
17
 
18
+ In [[mdspan.layout.reqmts]] through [[mdspan.layout.stride]]:
19
+
20
+ - Let *`is-mapping-of`* be the exposition-only variable template defined
21
  as follows:
 
22
  ``` cpp
23
  template<class Layout, class Mapping>
24
  constexpr bool is-mapping-of = // exposition only
25
  is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
26
  ```
27
+ - Let *`is-layout-left-padded-mapping-of`* be the exposition-only
28
+ variable template defined as follows:
29
+ ``` cpp
30
+ template<class Mapping>
31
+ constexpr bool is-layout-left-padded-mapping-of = see below; // exposition only
32
+ ```
33
+
34
+ where `is-layout-left-padded-mapping-of<Mapping>` is `true` if and
35
+ only if `Mapping` denotes a specialization of
36
+ `layout_left_padded<S>::mapping` for some value `S` of type `size_t`.
37
+ - Let *`is-layout-right-padded-mapping-of`* be the exposition-only
38
+ variable template defined as follows:
39
+ ``` cpp
40
+ template<class Mapping>
41
+ constexpr bool is-layout-right-padded-mapping-of = see below; // exposition only
42
+ ```
43
+
44
+ where `is-layout-right-padded-mapping-of<Mapping>` is `true` if and
45
+ only if `Mapping` denotes a specialization of
46
+ `layout_right_padded<S>::mapping` for some value `S` of type `size_t`.
47
+ - For nonnegative integers x and y, let LEAST-MULTIPLE-AT-LEAST(x, y)
48
+ denote
49
+ - y if x is zero,
50
+ - otherwise, the least multiple of x that is greater than or equal to
51
+ y.
52
 
53
  ##### Requirements <a id="mdspan.layout.reqmts">[[mdspan.layout.reqmts]]</a>
54
 
55
  A type `M` meets the *layout mapping* requirements if
56
 
 
174
 
175
  *Result:* `typename M::index_type`
176
 
177
  *Returns:* sᵣ as defined in `m.is_strided()` above.
178
 
179
+ [*Note 5*: It is not required for `m.stride(r)` to be well-formed if
180
+ `m.extents().rank()` is zero, even if `m.is_always_strided()` is
181
+ `true`. — *end note*]
182
+
183
  ``` cpp
184
  M::is_always_unique()
185
  ```
186
 
187
  *Result:* A constant expression [[expr.const]] of type `bool`.
188
 
189
  *Returns:* `true` only if `m.is_unique()` is `true` for all possible
190
  objects `m` of type `M`.
191
 
192
+ [*Note 6*: A mapping can return `false` even if the above condition is
193
  met. For certain layout mappings, it is possibly not feasible to
194
  determine whether every instance is unique. — *end note*]
195
 
196
  ``` cpp
197
  M::is_always_exhaustive()
 
200
  *Result:* A constant expression [[expr.const]] of type `bool`.
201
 
202
  *Returns:* `true` only if `m.is_exhaustive()` is `true` for all possible
203
  objects `m` of type `M`.
204
 
205
+ [*Note 7*: A mapping can return `false` even if the above condition is
206
  met. For certain layout mappings, it is possibly not feasible to
207
  determine whether every instance is exhaustive. — *end note*]
208
 
209
  ``` cpp
210
  M::is_always_strided()
 
213
  *Result:* A constant expression [[expr.const]] of type `bool`.
214
 
215
  *Returns:* `true` only if `m.is_strided()` is `true` for all possible
216
  objects `m` of type `M`.
217
 
218
+ [*Note 8*: A mapping can return `false` even if the above condition is
219
  met. For certain layout mappings, it is possibly not feasible to
220
  determine whether every instance is strided. — *end note*]
221
 
222
  ##### Layout mapping policy requirements <a id="mdspan.layout.policy.reqmts">[[mdspan.layout.policy.reqmts]]</a>
223
 
 
242
  };
243
  struct layout_stride {
244
  template<class Extents>
245
  class mapping;
246
  };
247
+
248
+ template<size_t PaddingValue>
249
+ struct layout_left_padded {
250
+ template<class Extents> class mapping;
251
+ };
252
+ template<size_t PaddingValue>
253
+ struct layout_right_padded {
254
+ template<class Extents> class mapping;
255
+ };
256
  }
257
  ```
258
 
259
+ Each of `layout_left`, `layout_right`, and `layout_stride`, as well as
260
+ each specialization of `layout_left_padded` and `layout_right_padded`,
261
+ meets the layout mapping policy requirements and is a trivially copyable
262
+ type. Furthermore, `is_trivially_default_constructible_v<T>` is `true`
263
+ for any such type `T`.
264
 
265
  ##### Class template `layout_left::mapping` <a id="mdspan.layout.left">[[mdspan.layout.left]]</a>
266
 
267
  ###### Overview <a id="mdspan.layout.left.overview">[[mdspan.layout.left.overview]]</a>
268
 
 
273
  namespace std {
274
  template<class Extents>
275
  class layout_left::mapping {
276
  public:
277
  using extents_type = Extents;
278
+ using index_type = extents_type::index_type;
279
+ using size_type = extents_type::size_type;
280
+ using rank_type = extents_type::rank_type;
281
  using layout_type = layout_left;
282
 
283
  // [mdspan.layout.left.cons], constructors
284
  constexpr mapping() noexcept = default;
285
  constexpr mapping(const mapping&) noexcept = default;
 
288
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
289
  mapping(const mapping<OtherExtents>&) noexcept;
290
  template<class OtherExtents>
291
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
292
  mapping(const layout_right::mapping<OtherExtents>&) noexcept;
293
+ template<class LayoutLeftPaddedMapping>
294
+ constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
295
+ extents_type>)
296
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
297
  template<class OtherExtents>
298
  constexpr explicit(extents_type::rank() > 0)
299
  mapping(const layout_stride::mapping<OtherExtents>&);
300
 
301
  constexpr mapping& operator=(const mapping&) noexcept = default;
 
321
  template<class OtherExtents>
322
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
323
 
324
  private:
325
  extents_type extents_{}; // exposition only
326
+
327
+ // [mdspan.sub.map], submdspan mapping specialization
328
+ template<class... SliceSpecifiers>
329
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
330
+ -> see below;
331
+
332
+ template<class... SliceSpecifiers>
333
+ friend constexpr auto submdspan_mapping(
334
+ const mapping& src, SliceSpecifiers... slices) {
335
+ return src.submdspan-mapping-impl(slices...);
336
+ }
337
  };
338
  }
339
  ```
340
 
341
  If `Extents` is not a specialization of `extents`, then the program is
 
373
 
374
  *Effects:* Direct-non-list-initializes *extents\_* with
375
  `other.extents()`.
376
 
377
  ``` cpp
378
+ template<class OtherExtents>
379
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
380
  mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
381
  ```
382
 
383
  *Constraints:*
 
389
  value of type `index_type` [[basic.fundamental]].
390
 
391
  *Effects:* Direct-non-list-initializes *extents\_* with
392
  `other.extents()`.
393
 
394
+ ``` cpp
395
+ template<class LayoutLeftPaddedMapping>
396
+ constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
397
+ extents_type>)
398
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
399
+ ```
400
+
401
+ *Constraints:*
402
+
403
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
404
+ `true`.
405
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
406
+ is `true`.
407
+
408
+ *Mandates:* If
409
+
410
+ - `Extents::rank()` is greater than one,
411
+ - `Extents::static_extent(0)` does not equal `dynamic_extent`, and
412
+ - `LayoutLeftPaddedMapping::`*`static-padding-stride`* does not equal
413
+ `dynamic_extent`,
414
+
415
+ then `Extents::static_extent(0)` equals
416
+ `LayoutLeftPaddedMapping::`*`static-padding-stride`*.
417
+
418
+ *Preconditions:*
419
+
420
+ - If `extents_type::rank() > 1` is `true`, then `other.stride(1)` equals
421
+ `other.extents().extent(0)`.
422
+ - `other.required_span_size()` is representable as a value of type
423
+ `index_type`.
424
+
425
+ *Effects:* Direct-non-list-initializes `extents_` with
426
+ `other.extents()`.
427
+
428
  ``` cpp
429
  template<class OtherExtents>
430
  constexpr explicit(extents_type::rank() > 0)
431
  mapping(const layout_stride::mapping<OtherExtents>& other);
432
  ```
 
478
  ``` cpp
479
  return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
480
  ```
481
 
482
  ``` cpp
483
+ constexpr index_type stride(rank_type i) const noexcept;
484
  ```
485
 
486
  *Constraints:* `extents_type::rank() > 0` is `true`.
487
 
488
  *Preconditions:* `i < extents_type::rank()` is `true`.
 
509
  namespace std {
510
  template<class Extents>
511
  class layout_right::mapping {
512
  public:
513
  using extents_type = Extents;
514
+ using index_type = extents_type::index_type;
515
+ using size_type = extents_type::size_type;
516
+ using rank_type = extents_type::rank_type;
517
  using layout_type = layout_right;
518
 
519
  // [mdspan.layout.right.cons], constructors
520
  constexpr mapping() noexcept = default;
521
  constexpr mapping(const mapping&) noexcept = default;
 
524
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
525
  mapping(const mapping<OtherExtents>&) noexcept;
526
  template<class OtherExtents>
527
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
528
  mapping(const layout_left::mapping<OtherExtents>&) noexcept;
529
+ template<class LayoutRightPaddedMapping>
530
+ constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
531
+ extents_type>)
532
+ mapping(const LayoutRightPaddedMapping&) noexcept;
533
  template<class OtherExtents>
534
  constexpr explicit(extents_type::rank() > 0)
535
  mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
536
 
537
  constexpr mapping& operator=(const mapping&) noexcept = default;
 
557
  template<class OtherExtents>
558
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
559
 
560
  private:
561
  extents_type extents_{}; // exposition only
562
+
563
+ // [mdspan.sub.map], submdspan mapping specialization
564
+ template<class... SliceSpecifiers>
565
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
566
+ -> see below;
567
+
568
+ template<class... SliceSpecifiers>
569
+ friend constexpr auto submdspan_mapping(
570
+ const mapping& src, SliceSpecifiers... slices) {
571
+ return src.submdspan-mapping-impl(slices...);
572
+ }
573
  };
574
  }
575
  ```
576
 
577
  If `Extents` is not a specialization of `extents`, then the program is
 
625
  value of type `index_type` [[basic.fundamental]].
626
 
627
  *Effects:* Direct-non-list-initializes *extents\_* with
628
  `other.extents()`.
629
 
630
+ ``` cpp
631
+ template<class LayoutRightPaddedMapping>
632
+ constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
633
+ extents_type>)
634
+ mapping(const LayoutRightPaddedMapping&) noexcept;
635
+ ```
636
+
637
+ *Constraints:*
638
+
639
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
640
+ `true`.
641
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
642
+ is `true`.
643
+
644
+ *Mandates:* If
645
+
646
+ - `Extents::rank()` is greater than one,
647
+ - `Extents::static_extent(Extents::rank() - 1)` does not equal
648
+ `dynamic_extent`, and
649
+ - `LayoutRightPaddedMapping::`*`static-padding-stride`* does not equal
650
+ `dynamic_extent`,
651
+
652
+ then `Extents::static_extent(Extents::rank() - 1)` equals
653
+ `LayoutRightPaddedMapping::`*`static-padding-stride`*.
654
+
655
+ *Preconditions:*
656
+
657
+ - If `extents_type::rank() > 1` is `true`, then
658
+ `other.stride(extents_type::rank() - 2)` equals
659
+ `other.extents().extent(extents_type::rank() - 1)`.
660
+ - `other.required_span_size()` is representable as a value of type
661
+ `index_type`.
662
+
663
+ *Effects:* Direct-non-list-initializes `extents_` with
664
+ `other.extents()`.
665
+
666
  ``` cpp
667
  template<class OtherExtents>
668
  constexpr explicit(extents_type::rank() > 0)
669
  mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
670
  ```
 
684
  `other.extents()`.
685
 
686
  ###### Observers <a id="mdspan.layout.right.obs">[[mdspan.layout.right.obs]]</a>
687
 
688
  ``` cpp
689
+ constexpr index_type required_span_size() const noexcept;
690
  ```
691
 
692
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
693
 
694
  ``` cpp
 
747
  namespace std {
748
  template<class Extents>
749
  class layout_stride::mapping {
750
  public:
751
  using extents_type = Extents;
752
+ using index_type = extents_type::index_type;
753
+ using size_type = extents_type::size_type;
754
+ using rank_type = extents_type::rank_type;
755
  using layout_type = layout_stride;
756
 
757
  private:
758
  static constexpr rank_type rank_ = extents_type::rank(); // exposition only
759
 
 
794
  friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
795
 
796
  private:
797
  extents_type extents_{}; // exposition only
798
  array<index_type, rank_> strides_{}; // exposition only
799
+
800
+ // [mdspan.sub.map], submdspan mapping specialization
801
+ template<class... SliceSpecifiers>
802
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
803
+ -> see below;
804
+
805
+ template<class... SliceSpecifiers>
806
+ friend constexpr auto submdspan_mapping(
807
+ const mapping& src, SliceSpecifiers... slices) {
808
+ return src.submdspan-mapping-impl(slices...);
809
+ }
810
  };
811
  }
812
  ```
813
 
814
  If `Extents` is not a specialization of `extents`, then the program is
 
827
 
828
  - `1`, if `e.rank() == 0` is `true`,
829
  - otherwise `0`, if the size of the multidimensional index space `e` is
830
  0,
831
  - otherwise `1` plus the sum of products of `(e.extent(r) - 1)` and
832
+ ``` cpp
833
+ extents_type::index-cast(strides[r])
834
+ ```
835
+
836
+ for all r in the range [0, `e.rank()`).
837
 
838
  Let `OFFSET(m)` be:
839
 
840
  - `m()`, if `e.rank() == 0` is `true`,
841
  - otherwise `0`, if the size of the multidimensional index space `e` is
 
903
  - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
904
  `true`.
905
 
906
  *Preconditions:*
907
 
908
+ - The result of converting `s[`i`]` to `index_type` is greater than `0`
909
+ for all i in the range [0, rank_).
910
  - *`REQUIRED-SPAN-SIZE`*`(e, s)` is representable as a value of type
911
  `index_type` [[basic.fundamental]].
912
  - If *rank\_* is greater than 0, then there exists a permutation P of
913
  the integers in the range [0, rank_), such that
914
  `s[`pᵢ`] >= s[`pᵢ₋₁`] * e.extent(p`ᵢ₋₁`)` is `true` for all i in the
 
936
  - `StridedLayoutMapping::is_always_strided()` is `true`.
937
 
938
  *Preconditions:*
939
 
940
  - `StridedLayoutMapping` meets the layout mapping
941
+ requirements [[mdspan.layout.reqmts]],
942
  - `other.stride(`r`) > 0` is `true` for every rank index r of
943
  `extents()`,
944
  - `other.required_span_size()` is representable as a value of type
945
  `index_type` [[basic.fundamental]], and
946
  - *`OFFSET`*`(other) == 0` is `true`.
 
952
 
953
  Remarks: The expression inside `explicit` is equivalent to:
954
 
955
  ``` cpp
956
  !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
957
+ (is-mapping-of<layout_left, StridedLayoutMapping> ||
958
+ is-mapping-of<layout_right, StridedLayoutMapping> ||
959
+ is-layout-left-padded-mapping-of<StridedLayoutMapping> ||
960
+ is-layout-right-padded-mapping-of<StridedLayoutMapping> ||
961
+ is-mapping-of<layout_stride, StridedLayoutMapping>))
962
  ```
963
 
964
  ###### Observers <a id="mdspan.layout.stride.obs">[[mdspan.layout.stride.obs]]</a>
965
 
966
  ``` cpp
 
1025
  *Returns:* `true` if `x.extents() == y.extents()` is `true`,
1026
  *`OFFSET`*`(y) == 0` is `true`, and each of
1027
  `x.stride(`r`) == y.stride(`r`)` is `true` for r in the range
1028
  [0, `x.extents().rank()`). Otherwise, `false`.
1029
 
1030
+ ##### Class template `layout_left_padded::mapping` <a id="mdspan.layout.leftpad">[[mdspan.layout.leftpad]]</a>
1031
+
1032
+ ###### Overview <a id="mdspan.layout.leftpad.overview">[[mdspan.layout.leftpad.overview]]</a>
1033
+
1034
+ `layout_left_padded` provides a layout mapping that behaves like
1035
+ `layout_left::mapping`, except that the padding stride `stride(1)` can
1036
+ be greater than or equal to `extent(0)`.
1037
+
1038
+ ``` cpp
1039
+ namespace std {
1040
+ template<size_t PaddingValue>
1041
+ template<class Extents>
1042
+ class layout_left_padded<PaddingValue>::mapping {
1043
+ public:
1044
+ static constexpr size_t padding_value = PaddingValue;
1045
+
1046
+ using extents_type = Extents;
1047
+ using index_type = extents_type::index_type;
1048
+ using size_type = extents_type::size_type;
1049
+ using rank_type = extents_type::rank_type;
1050
+ using layout_type = layout_left_padded<PaddingValue>;
1051
+
1052
+ private:
1053
+ static constexpr size_t rank_ = extents_type::rank(); // exposition only
1054
+ static constexpr size_t first-static-extent = // exposition only
1055
+ extents_type::static_extent(0);
1056
+
1057
+ // [mdspan.layout.leftpad.expo], exposition-only members
1058
+ static constexpr size_t static-padding-stride = see below; // exposition only
1059
+
1060
+ public:
1061
+ // [mdspan.layout.leftpad.cons], constructors
1062
+ constexpr mapping() noexcept : mapping(extents_type{}) {}
1063
+ constexpr mapping(const mapping&) noexcept = default;
1064
+ constexpr mapping(const extents_type&);
1065
+ template<class OtherIndexType>
1066
+ constexpr mapping(const extents_type&, OtherIndexType);
1067
+ template<class OtherExtents>
1068
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1069
+ mapping(const layout_left::mapping<OtherExtents>&);
1070
+ template<class OtherExtents>
1071
+ constexpr explicit(extents_type::rank() > 0)
1072
+ mapping(const layout_stride::mapping<OtherExtents>&);
1073
+ template<class LayoutLeftPaddedMapping>
1074
+ constexpr explicit(see below)
1075
+ mapping(const LayoutLeftPaddedMapping&);
1076
+ template<class LayoutRightPaddedMapping>
1077
+ constexpr explicit(see below)
1078
+ mapping(const LayoutRightPaddedMapping&) noexcept;
1079
+
1080
+ constexpr mapping& operator=(const mapping&) noexcept = default;
1081
+
1082
+ // [mdspan.layout.leftpad.obs], observers
1083
+ constexpr const extents_type& extents() const noexcept { return extents_; }
1084
+ constexpr array<index_type, rank_> strides() const noexcept;
1085
+
1086
+ constexpr index_type required_span_size() const noexcept;
1087
+ template<class... Indices>
1088
+ constexpr index_type operator()(Indices...) const noexcept;
1089
+
1090
+ static constexpr bool is_always_unique() noexcept { return true; }
1091
+ static constexpr bool is_always_exhaustive() noexcept;
1092
+ static constexpr bool is_always_strided() noexcept { return true; }
1093
+
1094
+ static constexpr bool is_unique() noexcept { return true; }
1095
+ constexpr bool is_exhaustive() const noexcept;
1096
+ static constexpr bool is_strided() noexcept { return true; }
1097
+
1098
+ constexpr index_type stride(rank_type) const noexcept;
1099
+
1100
+ template<class LayoutLeftPaddedMapping>
1101
+ friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;
1102
+
1103
+ private:
1104
+ // [mdspan.layout.leftpad.expo], exposition-only members
1105
+ index_type stride-1 = static-padding-stride; // exposition only
1106
+ extents_type extents_{}; // exposition only
1107
+ // [mdspan.sub.map], submdspan mapping specialization
1108
+ template<class... SliceSpecifiers>
1109
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1110
+ -> see below;
1111
+
1112
+ template<class... SliceSpecifiers>
1113
+ friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
1114
+ return src.submdspan-mapping-impl(slices...);
1115
+ }
1116
+ };
1117
+ }
1118
+ ```
1119
+
1120
+ If `Extents` is not a specialization of `extents`, then the program is
1121
+ ill-formed.
1122
+
1123
+ `layout_left_padded::mapping<E>` is a trivially copyable type that
1124
+ models `regular` for each `E`.
1125
+
1126
+ Throughout [[mdspan.layout.leftpad]], let `P_rank` be the following size
1127
+ *`rank_`* parameter pack of `size_`t values:
1128
+
1129
+ - the empty parameter pack, if *`rank_`* equals zero;
1130
+ - otherwise, `0zu`, if *`rank_`* equals one;
1131
+ - otherwise, the parameter pack `0zu`, `1zu`, …, `rank_- 1`.
1132
+
1133
+ *Mandates:*
1134
+
1135
+ - If `rank_dynamic() == 0` is `true`, then the size of the
1136
+ multidimensional index space `Extents()` is representable as a value
1137
+ of type `index_type`.
1138
+ - `padding_value` is representable as a value of type `index_type`.
1139
+ - If
1140
+ - *`rank_`* is greater than one,
1141
+ - `padding_value` does not equal `dynamic_extent`, and
1142
+ - *`first-static-extent`* does not equal `dynamic_extent`,
1143
+
1144
+ then `LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent)` is
1145
+ representable as a value of type `size_t`, and is representable as a
1146
+ value of type `index_type`.
1147
+ - If
1148
+ - *`rank_`* is greater than one,
1149
+ - `padding_value` does not equal `dynamic_extent`, and
1150
+ - `extents_type::static_extent(k)` does not equal `dynamic_extent` for
1151
+ all k in the range \[`0`, `extents_type::rank()`),
1152
+
1153
+ then the product of
1154
+ `LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(0))` and all
1155
+ values `ext.static_extent(k)` with k in the range of \[`1`, *`rank_`*)
1156
+ is representable as a value of type `size_t`, and is representable as
1157
+ a value of type `index_type`.
1158
+
1159
+ ###### Exposition-only members <a id="mdspan.layout.leftpad.expo">[[mdspan.layout.leftpad.expo]]</a>
1160
+
1161
+ ``` cpp
1162
+ static constexpr size_t static-padding-stride = see below;
1163
+ ```
1164
+
1165
+ The value is
1166
+
1167
+ - `0`, if *rank\_* equals zero or one;
1168
+ - otherwise, `dynamic_extent`, if `padding_value` or
1169
+ *first-static-extent* equals `dynamic_extent`;
1170
+ - otherwise, the `size_t` value which is
1171
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, `*`first-static-extent`*`)`.
1172
+
1173
+ ``` cpp
1174
+ index_type stride-1 = static-padding-stride;
1175
+ ```
1176
+
1177
+ *Recommended practice:* Implementations should not store this value if
1178
+ *static-padding-stride* is not `dynamic_extent`.
1179
+
1180
+ [*Note 9*: Using `extents<index_type, `*`static-padding-stride`*`>`
1181
+ instead of `index_type` as the type of *stride-1* would achieve
1182
+ this. — *end note*]
1183
+
1184
+ ###### Constructors <a id="mdspan.layout.leftpad.cons">[[mdspan.layout.leftpad.cons]]</a>
1185
+
1186
+ ``` cpp
1187
+ constexpr mapping(const extents_type& ext);
1188
+ ```
1189
+
1190
+ *Preconditions:*
1191
+
1192
+ - The size of the multidimensional index space `ext` is representable as
1193
+ a value of type `index_type`.
1194
+ - If *rank\_* is greater than one and `padding_value` does not equal
1195
+ `dynamic_extent`, then
1196
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))` is
1197
+ representable as a value of type *index_type*.
1198
+ - If *rank\_* is greater than one and `padding_value` does not equal
1199
+ `dynamic_extent`, then the product of
1200
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))` and all
1201
+ values `ext.extent(`k`)` with k in the range of \[`1`, *`rank_`*) is
1202
+ representable as a value of type `index_type`.
1203
+
1204
+ *Effects:*
1205
+
1206
+ - Direct-non-list-initializes *extents\_* with `ext`; and
1207
+ - if *rank\_* is greater than one, direct-non-list-initializes
1208
+ *stride-1*
1209
+ - with `ext.extent(0)` if padding_value is `dynamic_extent`,
1210
+ - otherwise with
1211
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))`.
1212
+
1213
+ ``` cpp
1214
+ template<class OtherIndexType>
1215
+ constexpr mapping(const extents_type& ext, OtherIndexType pad);
1216
+ ```
1217
+
1218
+ *Constraints:*
1219
+
1220
+ - `is_convertible_v<OtherIndexType, index_type>` is `true`.
1221
+ - `is_nothrow_constructible_v<index_type, OtherIndexType>` is `true`.
1222
+
1223
+ *Preconditions:*
1224
+
1225
+ - `pad` is representable as a value of type `index_type`.
1226
+ - `extents_type::`*`index-cast`*`(pad)` is greater than zero.
1227
+ - If *rank\_* is greater than one, then
1228
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))` is representable as
1229
+ a value of type `index_type.`
1230
+ - If *rank\_* is greater than one, then the product of
1231
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))` and all values
1232
+ `ext.extent(`k`)` with k in the range of \[`1`, *`rank_`*) is
1233
+ representable as a value of type `index_type`.
1234
+ - If `padding_value` is not equal to `dynamic_extent`, `padding_value`
1235
+ equals `extents_type::`*`index-cast`*`(pad)`.
1236
+
1237
+ *Effects:* Direct-non-list-initializes *extents\_* with `ext`, and if
1238
+ *rank\_* is greater than one, direct-non-list-initializes *stride-1*
1239
+ with *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))`.
1240
+
1241
+ ``` cpp
1242
+ template<class OtherExtents>
1243
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1244
+ mapping(const layout_left::mapping<OtherExtents>& other);
1245
+ ```
1246
+
1247
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
1248
+ `true`.
1249
+
1250
+ *Mandates:* If `OtherExtents::rank()` is greater than `1`, then
1251
+
1252
+ ``` cpp
1253
+ (static-padding-stride == dynamic_extent) ||
1254
+ (OtherExtents::static_extent(0) == dynamic_extent) ||
1255
+ (static-padding-stride == OtherExtents::static_extent(0))
1256
+ ```
1257
+
1258
+ is `true`.
1259
+
1260
+ *Preconditions:*
1261
+
1262
+ - If `extents_type::rank() > 1` is `true` and `padding_value` ==
1263
+ `dynamic_extent` is `false`, then `other.stride(1)` equals
1264
+ ``` cpp
1265
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1266
+ extents_type::index-cast(other.extents().extent(0)))
1267
+ ```
1268
+
1269
+ and
1270
+ - `other.required_span_size()` is representable as a value of type
1271
+ `index_type`.
1272
+
1273
+ *Effects:* Equivalent to `mapping(other.extents())`.
1274
+
1275
+ ``` cpp
1276
+ template<class OtherExtents>
1277
+ constexpr explicit(rank_ > 0)
1278
+ mapping(const layout_stride::mapping<OtherExtents>& other);
1279
+ ```
1280
+
1281
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
1282
+ `true`.
1283
+
1284
+ *Preconditions:*
1285
+
1286
+ - If *rank\_* is greater than `1` and `padding_value` does not equal
1287
+ `dynamic_extent`, then `other.stride(1)` equals
1288
+ ``` cpp
1289
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1290
+ extents_type::index-cast(other.extents().extent(0)))
1291
+ ```
1292
+ - If *rank\_* is greater than 0, then `other.stride(0)` equals 1.
1293
+ - If *rank\_* is greater than 2, then for all r in the range \[`2`,
1294
+ *`rank_`*), `other.stride(r)` equals
1295
+ ``` cpp
1296
+ (other.extents().fwd-prod-of-extents(r) / other.extents().extent(0)) * other.stride(1)
1297
+ ```
1298
+ - `other.required_span_size()` is representable as a value of type
1299
+ *index_type*.
1300
+
1301
+ *Effects:*
1302
+
1303
+ - Direct-non-list-initializes *extents\_* with `other.extents()` and
1304
+ - if *rank\_* is greater than one, direct-non-list-initializes
1305
+ *stride-1* with `other.stride(1)`.
1306
+
1307
+ ``` cpp
1308
+ template<class LayoutLeftPaddedMapping>
1309
+ constexpr explicit(see below)
1310
+ mapping(const LayoutLeftPaddedMapping& other);
1311
+ ```
1312
+
1313
+ *Constraints:*
1314
+
1315
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
1316
+ `true`.
1317
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
1318
+ is `true`.
1319
+
1320
+ *Mandates:* If *rank\_* is greater than 1, then
1321
+
1322
+ ``` cpp
1323
+ padding_value == dynamic_extent ||
1324
+ LayoutLeftPaddedMapping::padding_value == dynamic_extent ||
1325
+ padding_value == LayoutLeftPaddedMapping::padding_value
1326
+ ```
1327
+
1328
+ is `true`.
1329
+
1330
+ *Preconditions:*
1331
+
1332
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
1333
+ `dynamic_extent`, then `other.stride(1)` equals
1334
+ ``` cpp
1335
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1336
+ extents_type::index-cast(other.extent(0)))
1337
+ ```
1338
+ - `other.required_span_size()` is representable as a value of type
1339
+ `index_type`.
1340
+
1341
+ *Effects:*
1342
+
1343
+ - Direct-non-list-initializes *extents\_* with `other.extents()` and
1344
+ - if *rank\_* is greater than one, direct-non-list-initializes
1345
+ *stride-1* with `other.stride(1)`.
1346
+
1347
+ *Remarks:* The expression inside `explicit` is equivalent to:
1348
+
1349
+ ``` cpp
1350
+ rank_> 1 &&
1351
+ (padding_value != dynamic_extent ||
1352
+ LayoutLeftPaddedMapping::padding_value == dynamic_extent)
1353
+ ```
1354
+
1355
+ ``` cpp
1356
+ template<class LayoutRightPaddedMapping>
1357
+ constexpr explicit(see below)
1358
+ mapping(const LayoutRightPaddedMapping& other) noexcept;
1359
+ ```
1360
+
1361
+ *Constraints:*
1362
+
1363
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
1364
+ `true` or *`is-mapping-of`*`<layout_right, LayoutRightPaddedMapping>`
1365
+ is `true`.
1366
+ - *rank\_* equals zero or one.
1367
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
1368
+ is `true`.
1369
+
1370
+ *Preconditions:* `other.required_span_size()` is representable as a
1371
+ value of type `index_type`.
1372
+
1373
+ *Effects:* Direct-non-list-initializes *extents\_* with
1374
+ `other.extents()`.
1375
+
1376
+ *Remarks:* The expression inside `explicit` is equivalent to:
1377
+
1378
+ ``` cpp
1379
+ !is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>
1380
+ ```
1381
+
1382
+ [*Note 10*: Neither the input mapping nor the mapping to be constructed
1383
+ uses the padding stride in the rank-0 or rank-1 case, so the padding
1384
+ stride does not affect either the constraints or the
1385
+ preconditions. — *end note*]
1386
+
1387
+ ###### Observers <a id="mdspan.layout.leftpad.obs">[[mdspan.layout.leftpad.obs]]</a>
1388
+
1389
+ ``` cpp
1390
+ constexpr array<index_type, rank_> strides() const noexcept;
1391
+ ```
1392
+
1393
+ *Returns:* `array<index_type, `*`rank_`*`>({stride(P_rank)...})`.
1394
+
1395
+ ``` cpp
1396
+ constexpr index_type required_span_size() const noexcept;
1397
+ ```
1398
+
1399
+ *Returns:*
1400
+
1401
+ - `0` if the multidimensional index space *extents\_* is empty,
1402
+ - otherwise,
1403
+ `(*this)(`*`extents_`*`.extent(P_rank) - index_type(1)...) + 1`.
1404
+
1405
+ ``` cpp
1406
+ template<class... Indices>
1407
+ constexpr size_t operator()(Indices... idxs) const noexcept;
1408
+ ```
1409
+
1410
+ *Constraints:*
1411
+
1412
+ - `sizeof...(Indices) == `*`rank_`* is `true`.
1413
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`.
1414
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
1415
+
1416
+ *Preconditions:* `extents_type::`*`index-cast`*`(idxs)` is a
1417
+ multidimensional index in `extents()` [[mdspan.overview]].
1418
+
1419
+ *Returns:*
1420
+ `((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)`.
1421
+
1422
+ ``` cpp
1423
+ static constexpr bool is_always_exhaustive() noexcept;
1424
+ ```
1425
+
1426
+ *Returns:*
1427
+
1428
+ - If *rank\_* equals zero or one, then `true`;
1429
+ - otherwise, if neither *static-padding-stride* nor
1430
+ *first-static-extent* equal `dynamic_extent`, then
1431
+ *`static-padding-stride`*` == `*`first-static-extent`*;
1432
+ - otherwise, `false`.
1433
+
1434
+ ``` cpp
1435
+ constexpr bool is_exhaustive() const noexcept;
1436
+ ```
1437
+
1438
+ *Returns:* `true` if *rank\_* equals zero or one; otherwise,
1439
+ `extents_.extent(0) == stride(1)`.
1440
+
1441
+ ``` cpp
1442
+ constexpr index_type stride(rank_type r) const noexcept;
1443
+ ```
1444
+
1445
+ *Preconditions:* `r` is smaller than *rank\_*.
1446
+
1447
+ *Returns:*
1448
+
1449
+ - If `r` equals zero: 1;
1450
+ - otherwise, if `r` equals one: *stride-1*;
1451
+ - otherwise, the product of *stride-1* and all values
1452
+ `extents_.extent(`k`)` with k in the range \[`1`, `r`).
1453
+
1454
+ ``` cpp
1455
+ template<class LayoutLeftPaddedMapping>
1456
+ friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
1457
+ ```
1458
+
1459
+ *Constraints:*
1460
+
1461
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
1462
+ `true`.
1463
+ - `LayoutLeftPaddedMapping::extents_type::rank() == rank_` is `true`.
1464
+
1465
+ *Returns:* `true` if `x.extents() == y.extents()` is `true` and
1466
+ *`rank_`*` < 2 || x.stride(1) == y. stride(1)` is `true`. Otherwise,
1467
+ `false`.
1468
+
1469
+ ##### Class template `layout_right_padded::mapping` <a id="mdspan.layout.rightpad">[[mdspan.layout.rightpad]]</a>
1470
+
1471
+ ###### Overview <a id="mdspan.layout.rightpad.overview">[[mdspan.layout.rightpad.overview]]</a>
1472
+
1473
+ `layout_right_padded` provides a layout mapping that behaves like
1474
+ `layout_right::mapping`, except that the padding stride
1475
+ `stride(extents_type::rank() - 2)` can be greater than or equal to
1476
+ `extents_type::extent(extents_type::rank() - 1)`.
1477
+
1478
+ ``` cpp
1479
+ namespace std {
1480
+ template<size_t PaddingValue>
1481
+ template<class Extents>
1482
+ class layout_right_padded<PaddingValue>::mapping {
1483
+ public:
1484
+ static constexpr size_t padding_value = PaddingValue;
1485
+
1486
+ using extents_type = Extents;
1487
+ using index_type = extents_type::index_type;
1488
+ using size_type = extents_type::size_type;
1489
+ using rank_type = extents_type::rank_type;
1490
+ using layout_type = layout_right_padded<PaddingValue>;
1491
+
1492
+ private:
1493
+ static constexpr size_t rank_ = extents_type::rank(); // exposition only
1494
+ static constexpr size_t last-static-extent = // exposition only
1495
+ extents_type::static_extent(rank_ - 1);
1496
+
1497
+ // [mdspan.layout.rightpad.expo], exposition-only members
1498
+ static constexpr size_t static-padding-stride = see below; // exposition only
1499
+
1500
+ public:
1501
+ // [mdspan.layout.rightpad.cons], constructors
1502
+ constexpr mapping() noexcept : mapping(extents_type{}) {}
1503
+ constexpr mapping(const mapping&) noexcept = default;
1504
+ constexpr mapping(const extents_type&);
1505
+ template<class OtherIndexType>
1506
+ constexpr mapping(const extents_type&, OtherIndexType);
1507
+
1508
+ template<class OtherExtents>
1509
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1510
+ mapping(const layout_right::mapping<OtherExtents>&);
1511
+ template<class OtherExtents>
1512
+ constexpr explicit(rank_ > 0)
1513
+ mapping(const layout_stride::mapping<OtherExtents>&);
1514
+ template<class LayoutRightPaddedMapping>
1515
+ constexpr explicit(see below)
1516
+ mapping(const LayoutRightPaddedMapping&);
1517
+ template<class LayoutLeftPaddedMapping>
1518
+ constexpr explicit(see below)
1519
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
1520
+
1521
+ constexpr mapping& operator=(const mapping&) noexcept = default;
1522
+
1523
+ // [mdspan.layout.rightpad.obs], observers
1524
+ constexpr const extents_type& extents() const noexcept { return extents_; }
1525
+ constexpr array<index_type, rank_> strides() const noexcept;
1526
+
1527
+ constexpr index_type required_span_size() const noexcept;
1528
+
1529
+ template<class... Indices>
1530
+ constexpr index_type operator()(Indices...) const noexcept;
1531
+
1532
+ static constexpr bool is_always_unique() noexcept { return true; }
1533
+ static constexpr bool is_always_exhaustive() noexcept;
1534
+ static constexpr bool is_always_strided() noexcept { return true; }
1535
+
1536
+ static constexpr bool is_unique() noexcept { return true; }
1537
+ constexpr bool is_exhaustive() const noexcept;
1538
+ static constexpr bool is_strided() noexcept { return true; }
1539
+
1540
+ constexpr index_type stride(rank_type) const noexcept;
1541
+
1542
+ template<class LayoutRightPaddedMapping>
1543
+ friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;
1544
+
1545
+ private:
1546
+ // [mdspan.layout.rightpad.expo], exposition-only members
1547
+ index_type stride-rm2 = static-padding-stride; // exposition only
1548
+ extents_type extents_{}; // exposition only
1549
+
1550
+ // [mdspan.sub.map], submdspan mapping specialization
1551
+ template<class... SliceSpecifiers>
1552
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1553
+ -> see below;
1554
+
1555
+ template<class... SliceSpecifiers>
1556
+ friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
1557
+ return src.submdspan-mapping-impl(slices...);
1558
+ }
1559
+ };
1560
+ }
1561
+ ```
1562
+
1563
+ If `Extents` is not a specialization of `extents`, then the program is
1564
+ ill-formed.
1565
+
1566
+ `layout_right_padded::mapping<E>` is a trivially copyable type that
1567
+ models `regular` for each `E`.
1568
+
1569
+ Throughout [[mdspan.layout.rightpad]], let `P_rank` be the following
1570
+ size *`rank_`* parameter pack of `size_`t values:
1571
+
1572
+ - the empty parameter pack, if *`rank_`* equals zero;
1573
+ - otherwise, `0zu`, if *`rank_`* equals one;
1574
+ - otherwise, the parameter pack `0zu`, `1zu`, …, `rank_- 1`.
1575
+
1576
+ *Mandates:*
1577
+
1578
+ - If `rank_dynamic() == 0` is `true`, then the size of the
1579
+ multidimensional index space `Extents()` is representable as a value
1580
+ of type `index_type`.
1581
+ - `padding_value` is representable as a value of type `index_type`.
1582
+ - If
1583
+ - *`rank_`* is greater than one,
1584
+ - `padding_value` does not equal `dynamic_extent`, and
1585
+ - *`last-static-extent`* does not equal `dynamic_extent`,
1586
+
1587
+ then `LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent)` is
1588
+ representable as a value of type `size_t`, and is representable as a
1589
+ value of type `index_type`.
1590
+ - If
1591
+ - *`rank_`* is greater than one,
1592
+ - `padding_value` does not equal `dynamic_extent`, and
1593
+ - `extents_type::static_extent(k)` does not equal `dynamic_extent` for
1594
+ all k in the range \[`0`, *`rank_`*),
1595
+
1596
+ then the product of
1597
+ `LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(rank_ - 1))`
1598
+ and all values `ext.static_extent(k)` with k in the range of \[`0`,
1599
+ *`rank_`*` - 1`) is representable as a value of type `size_t`, and is
1600
+ representable as a value of type `index_type`.
1601
+
1602
+ ###### Exposition-only members <a id="mdspan.layout.rightpad.expo">[[mdspan.layout.rightpad.expo]]</a>
1603
+
1604
+ ``` cpp
1605
+ static constexpr size_t static-padding-stride = see below;
1606
+ ```
1607
+
1608
+ The value is
1609
+
1610
+ - `0`, if *rank\_* equals zero or one;
1611
+ - otherwise, `dynamic_extent`, if `padding_value` or
1612
+ *last-static-extent* equals `dynamic_extent`;
1613
+ - otherwise, the `size_t` value which is
1614
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, `*`last-static-extent`*`)`.
1615
+
1616
+ ``` cpp
1617
+ index_type stride-rm2 = static-padding-stride;
1618
+ ```
1619
+
1620
+ *Recommended practice:* Implementations should not store this value if
1621
+ *static-padding-stride* is not `dynamic_extent`.
1622
+
1623
+ [*Note 11*: Using `extents<index_type, `*`static-padding-stride`*`>`
1624
+ instead of `index_type` as the type of *stride-rm2* would achieve
1625
+ this. — *end note*]
1626
+
1627
+ ###### Constructors <a id="mdspan.layout.rightpad.cons">[[mdspan.layout.rightpad.cons]]</a>
1628
+
1629
+ ``` cpp
1630
+ constexpr mapping(const extents_type& ext);
1631
+ ```
1632
+
1633
+ *Preconditions:*
1634
+
1635
+ - The size of the multidimensional index space `ext` is representable as
1636
+ a value of type `index_type`.
1637
+ - If *rank\_* is greater than one and `padding_value` does not equal
1638
+ `dynamic_extent`, then
1639
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`
1640
+ is representable as a value of type *index_type*.
1641
+ - If *rank\_* is greater than one and `padding_value` does not equal
1642
+ `dynamic_extent`, then the product of
1643
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`
1644
+ and all values `ext.extent(`k`)` with k in the range of \[`0`,
1645
+ *`rank_`*` - 1`) is representable as a value of type `index_type`.
1646
+
1647
+ *Effects:*
1648
+
1649
+ - Direct-non-list-initializes *extents\_* with `ext`; and
1650
+ - if *rank\_* is greater than one, direct-non-list-initializes
1651
+ *stride-rm2*
1652
+ - with `ext.extent(`*`rank_`*` - 1)` if `padding_value` is
1653
+ `dynamic_extent`,
1654
+ - otherwise with
1655
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`.
1656
+
1657
+ ``` cpp
1658
+ template<class OtherIndexType>
1659
+ constexpr mapping(const extents_type& ext, OtherIndexType pad);
1660
+ ```
1661
+
1662
+ *Constraints:*
1663
+
1664
+ - `is_convertible_v<OtherIndexType, index_type>` is `true`.
1665
+ - `is_nothrow_constructible_v<index_type, OtherIndexType>` is `true`.
1666
+
1667
+ *Preconditions:*
1668
+
1669
+ - `pad` is representable as a value of type `index_type`.
1670
+ - `extents_type::`*`index-cast`*`(pad)` is greater than zero.
1671
+ - If *rank\_* is greater than one, then
1672
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))` is
1673
+ representable as a value of type `index_type`.
1674
+ - If *rank\_* is greater than one, then the product of
1675
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))` and
1676
+ all values `ext.extent(`k`)` with k in the range of \[`0`,
1677
+ *`rank_`*` - 1`) is representable as a value of type `index_type`.
1678
+ - If `padding_value` is not equal to `dynamic_extent`, `padding_value`
1679
+ equals `extents_type::`*`index-cast`*`(pad)`.
1680
+
1681
+ *Effects:* Direct-non-list-initializes *extents\_* with `ext`, and if
1682
+ *rank\_* is greater than one, direct-non-list-initializes *stride-rm2*
1683
+ with *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))`.
1684
+
1685
+ ``` cpp
1686
+ template<class OtherExtents>
1687
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1688
+ mapping(const layout_right::mapping<OtherExtents>& other);
1689
+ ```
1690
+
1691
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
1692
+ `true`.
1693
+
1694
+ *Mandates:* If `OtherExtents::rank()` is greater than 1, then
1695
+
1696
+ ``` cpp
1697
+ (static-padding-stride == dynamic_extent) ||
1698
+ (OtherExtents::static_extent(rank_ - 1) == dynamic_extent) ||
1699
+ (static-padding-stride == OtherExtents::static_extent(rank_ - 1))
1700
+ ```
1701
+
1702
+ is `true`.
1703
+
1704
+ *Preconditions:*
1705
+
1706
+ - If *`rank_`*` > 1` is `true` and `padding_value == dynamic_extent` is
1707
+ `false`, then `other.stride( `*`rank_`*` - 2)` equals
1708
+ ``` cpp
1709
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1710
+ extents_type::index-cast(other.extents().extent(rank_ - 1)))
1711
+ ```
1712
+
1713
+ and
1714
+ - `other.required_span_size()` is representable as a value of type
1715
+ `index_type`.
1716
+
1717
+ *Effects:* Equivalent to `mapping(other.extents())`.
1718
+
1719
+ ``` cpp
1720
+ template<class OtherExtents>
1721
+ constexpr explicit(rank_ > 0)
1722
+ mapping(const layout_stride::mapping<OtherExtents>& other);
1723
+ ```
1724
+
1725
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
1726
+ `true`.
1727
+
1728
+ *Preconditions:*
1729
+
1730
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
1731
+ `dynamic_extent`, then `other.stride(`*`rank_`*` - 2)` equals
1732
+ ``` cpp
1733
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1734
+ extents_type::index-cast(other.extents().extent(rank_ - 1)))
1735
+ ```
1736
+ - If *rank\_* is greater than 0, then other.stride(*rank\_* - 1) equals
1737
+ 1.
1738
+ - If *rank\_* is greater than 2, then for all r in the range \[`0`,
1739
+ *`rank_`*` - 2`), `other.stride(`r`)` equals
1740
+ ``` cpp
1741
+ (other.extents().rev-prod-of-extents(r) / other.extents().extent(rank_ - 1)) *
1742
+ other.stride(rank_ - 2)
1743
+ ```
1744
+ - `other.required_span_size()` is representable as a value of type
1745
+ `index_type`.
1746
+
1747
+ *Effects:*
1748
+
1749
+ - Direct-non-list-initializes *extents\_* with `other.extents()`; and
1750
+ - if *rank\_* is greater than one, direct-non-list-initializes
1751
+ *stride-rm2* with `other.stride(`*`rank_`*` - 2)`.
1752
+
1753
+ ``` cpp
1754
+ template<class LayoutRightPaddedMapping>
1755
+ constexpr explicit(see below)
1756
+ mapping(const LayoutRightPaddedMapping& other);
1757
+ ```
1758
+
1759
+ *Constraints:*
1760
+
1761
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
1762
+ `true`.
1763
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
1764
+ is `true`.
1765
+
1766
+ *Mandates:* If *rank\_* is greater than 1, then
1767
+
1768
+ ``` cpp
1769
+ padding_value == dynamic_extent ||
1770
+ LayoutRightPaddedMapping::padding_value == dynamic_extent ||
1771
+ padding_value == LayoutRightPaddedMapping::padding_value
1772
+ ```
1773
+
1774
+ is `true`.
1775
+
1776
+ *Preconditions:*
1777
+
1778
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
1779
+ `dynamic_extent`, then `other.stride(`*`rank_`*` - 2)` equals
1780
+ ``` cpp
1781
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1782
+ extents_type::index-cast(other.extent(rank_ - 1)))
1783
+ ```
1784
+ - `other.required_span_size()` is representable as a value of type
1785
+ `index_type`.
1786
+
1787
+ *Effects:*
1788
+
1789
+ - Direct-non-list-initializes *extents\_* with `other.extents()`; and
1790
+ - if *rank\_* is greater than one, direct-non-list-initializes
1791
+ *stride-rm2* with `other.stride(rank_ - 2)`.
1792
+
1793
+ *Remarks:* The expression inside `explicit` is equivalent to:
1794
+
1795
+ ``` cpp
1796
+ rank_ > 1 &&
1797
+ (padding_value != dynamic_extent ||
1798
+ LayoutRightPaddedMapping::padding_value == dynamic_extent)
1799
+ ```
1800
+
1801
+ ``` cpp
1802
+ template<class LayoutLeftPaddedMapping>
1803
+ constexpr explicit(see below)
1804
+ mapping(const LayoutLeftPaddedMapping& other) noexcept;
1805
+ ```
1806
+
1807
+ *Constraints:*
1808
+
1809
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
1810
+ `true` or *`is-mapping-of`*`<layout_left, LayoutLeftPaddedMapping>` is
1811
+ `true`.
1812
+ - *rank\_* equals zero or one.
1813
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
1814
+ is `true`.
1815
+
1816
+ *Preconditions:* `other.required_span_size()` is representable as a
1817
+ value of type `index_type`.
1818
+
1819
+ *Effects:* Direct-non-list-initializes *extents\_* with
1820
+ `other.extents()`.
1821
+
1822
+ *Remarks:* The expression inside `explicit` is equivalent to:
1823
+
1824
+ ``` cpp
1825
+ !is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>
1826
+ ```
1827
+
1828
+ [*Note 12*: Neither the input mapping nor the mapping to be constructed
1829
+ uses the padding stride in the rank-0 or rank-1 case, so the padding
1830
+ stride affects neither the constraints nor the
1831
+ preconditions. — *end note*]
1832
+
1833
+ ###### Observers <a id="mdspan.layout.rightpad.obs">[[mdspan.layout.rightpad.obs]]</a>
1834
+
1835
+ ``` cpp
1836
+ constexpr array<index_type, rank_> strides() const noexcept;
1837
+ ```
1838
+
1839
+ *Returns:* `array<index_type, `*`rank_`*`>(``stride(P_rank)...``)`.
1840
+
1841
+ ``` cpp
1842
+ constexpr index_type required_span_size() const noexcept;
1843
+ ```
1844
+
1845
+ *Returns:* `0` if the multidimensional index space *extents\_* is empty,
1846
+ otherwise
1847
+ `(*this)(`*`extents_`*`.extent(P_rank) - index_type(1)...) + 1`.
1848
+
1849
+ ``` cpp
1850
+ template<class... Indices>
1851
+ constexpr size_t operator()(Indices... idxs) const noexcept;
1852
+ ```
1853
+
1854
+ *Constraints:*
1855
+
1856
+ - `sizeof...(Indices) == `*`rank_`* is `true`.
1857
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`.
1858
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
1859
+
1860
+ *Preconditions:* `extents_type::`*`index-cast`*`(idxs)` is a
1861
+ multidimensional index in `extents()` [[mdspan.overview]].
1862
+
1863
+ *Returns:*
1864
+ `((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)`.
1865
+
1866
+ ``` cpp
1867
+ static constexpr bool is_always_exhaustive() noexcept;
1868
+ ```
1869
+
1870
+ *Returns:*
1871
+
1872
+ - If *rank\_* equals zero or one, then `true`;
1873
+ - otherwise, if neither *static-padding-stride* nor *last-static-extent*
1874
+ equal `dynamic_extent`, then
1875
+ *`static-padding-stride`*` == `*`last-static-extent`*;
1876
+ - otherwise, `false`.
1877
+
1878
+ ``` cpp
1879
+ constexpr bool is_exhaustive() const noexcept;
1880
+ ```
1881
+
1882
+ *Returns:* `true` if *rank\_* equals zero or one; otherwise,
1883
+
1884
+ ``` cpp
1885
+ extents_.extent(rank_ - 1) == stride(rank_ - 2)
1886
+ ```
1887
+
1888
+ ``` cpp
1889
+ constexpr index_type stride(rank_type r) const noexcept;
1890
+ ```
1891
+
1892
+ *Preconditions:* `r` is smaller than *rank\_*.
1893
+
1894
+ *Returns:*
1895
+
1896
+ - If `r` equals *`rank_`*` - 1`: `1`;
1897
+ - otherwise, if `r` equals *`rank_`*` - 2`: *stride-rm2*;
1898
+ - otherwise, the product of *stride-rm2* and all values
1899
+ `extents_.extent(`k`)` with k in the range of \[`r + 1`,
1900
+ *`rank_`*` - 1`).
1901
+
1902
+ ``` cpp
1903
+ template<class LayoutRightPaddedMapping>
1904
+ friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;
1905
+ ```
1906
+
1907
+ *Constraints:*
1908
+
1909
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
1910
+ `true`.
1911
+ - `LayoutRightPaddedMapping::extents_type::rank() == `*`rank_`* is
1912
+ `true`.
1913
+
1914
+ *Returns:* `true` if `x.extents() == y.extents()` is `true` and
1915
+ *`rank_`*` < 2 || x.stride(`*`rank_`*` - 2) == y.stride(`*`rank_`*` - 2)`
1916
+ is `true`. Otherwise, `false`.
1917
+