From Jason Turner

[views.multidim]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmplf9zx76c/{from.md → to.md} +1994 -57
tmp/tmplf9zx76c/{from.md → to.md} RENAMED
@@ -22,42 +22,81 @@ the following are true:
22
  the interval [Lᵢ, Uᵢ) of S.
23
 
24
  #### Header `<mdspan>` synopsis <a id="mdspan.syn">[[mdspan.syn]]</a>
25
 
26
  ``` cpp
 
27
  namespace std {
28
  // [mdspan.extents], class template extents
29
  template<class IndexType, size_t... Extents>
30
  class extents;
31
 
32
  // [mdspan.extents.dextents], alias template dextents
33
  template<class IndexType, size_t Rank>
34
  using dextents = see below;
35
 
 
 
 
 
36
  // [mdspan.layout], layout mapping
37
  struct layout_left;
38
  struct layout_right;
39
  struct layout_stride;
 
 
 
 
40
 
41
  // [mdspan.accessor.default], class template default_accessor
42
  template<class ElementType>
43
  class default_accessor;
44
 
 
 
 
 
45
  // [mdspan.mdspan], class template mdspan
46
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
47
  class AccessorPolicy = default_accessor<ElementType>>
48
- class mdspan;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
  ```
51
 
52
  #### Class template `extents` <a id="mdspan.extents">[[mdspan.extents]]</a>
53
 
54
  ##### Overview <a id="mdspan.extents.overview">[[mdspan.extents.overview]]</a>
55
 
56
  The class template `extents` represents a multidimensional index space
57
- of rank equal to `sizeof...(Extents)`. In subclause [[views]], `extents`
58
- is used synonymously with multidimensional index space.
59
 
60
  ``` cpp
61
  namespace std {
62
  template<class IndexType, size_t... Extents>
63
  class extents {
@@ -237,12 +276,12 @@ Let `N` be `sizeof...(OtherIndexTypes)`, and let `exts_arr` be
237
 
238
  - If `N != rank_dynamic()` is `true`, `exts_arr[`r`]` equals Eᵣ for each
239
  r for which Eᵣ is a static extent, and
240
  - either
241
  - `sizeof...(exts) == 0` is `true`, or
242
- - each element of `exts` is nonnegative and is representable as a
243
- value of type `index_type`.
244
 
245
  *Ensures:* `*this == extents(exts_arr)` is `true`.
246
 
247
  ``` cpp
248
  template<class OtherIndexType, size_t N>
@@ -264,16 +303,16 @@ template<class OtherIndexType, size_t N>
264
 
265
  - If `N != rank_dynamic()` is `true`, `exts[`r`]` equals Eᵣ for each r
266
  for which Eᵣ is a static extent, and
267
  - either
268
  - `N` is zero, or
269
- - `exts[`r`]` is nonnegative and is representable as a value of type
270
  `index_type` for every rank index r.
271
 
272
  *Effects:*
273
 
274
- - If `N` equals `dynamic_rank()`, for all d in the range
275
  [0, `rank_dynamic()`), direct-non-list-initializes
276
  *`dynamic-extents`*`[`d`]` with `as_const(exts[`d`])`.
277
  - Otherwise, for all d in the range [0, `rank_dynamic()`),
278
  direct-non-list-initializes *`dynamic-extents`*`[`d`]` with
279
  `as_const(exts[`*`dynamic-index-inv`*`(`d`)])`.
@@ -283,11 +322,12 @@ template<class... Integrals>
283
  explicit extents(Integrals...) -> see below;
284
  ```
285
 
286
  *Constraints:* `(is_convertible_v<Integrals, size_t> && ...)` is `true`.
287
 
288
- *Remarks:* The deduced type is `dextents<size_t, sizeof...(Integrals)>`.
 
289
 
290
  ##### Observers of the multidimensional index space <a id="mdspan.extents.obs">[[mdspan.extents.obs]]</a>
291
 
292
  ``` cpp
293
  static constexpr size_t static_extent(rank_type i) noexcept;
@@ -326,16 +366,26 @@ template<class IndexType, size_t Rank>
326
 
327
  *Result:* A type `E` that is a specialization of `extents` such that
328
  `E::rank() == Rank && E::rank() == E::rank_dynamic()` is `true`, and
329
  `E::index_type` denotes `IndexType`.
330
 
 
 
 
 
 
 
 
 
 
 
 
331
  #### Layout mapping <a id="mdspan.layout">[[mdspan.layout]]</a>
332
 
333
  ##### General <a id="mdspan.layout.general">[[mdspan.layout.general]]</a>
334
 
335
- In subclauses [[mdspan.layout.reqmts]] and
336
- [[mdspan.layout.policy.reqmts]]:
337
 
338
  - `M` denotes a layout mapping class.
339
  - `m` denotes a (possibly const) value of type `M`.
340
  - `i` and `j` are packs of (possibly const) integers that are
341
  multidimensional indices in `m.extents()` [[mdspan.overview]].
@@ -344,19 +394,44 @@ In subclauses [[mdspan.layout.reqmts]] and
344
  - `r` is a (possibly const) rank index of `typename M::extents_type`.
345
  - `dᵣ` is a pack of (possibly const) integers for which
346
  `sizeof...(dᵣ) == M::extents_type::rank()` is `true`, the rᵗʰ element
347
  is equal to 1, and all other elements are equal to 0.
348
 
349
- In subclauses [[mdspan.layout.reqmts]] through [[mdspan.layout.stride]],
350
- let *`is-mapping-of`* be the exposition-only variable template defined
 
351
  as follows:
352
-
353
  ``` cpp
354
  template<class Layout, class Mapping>
355
  constexpr bool is-mapping-of = // exposition only
356
  is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
357
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
  ##### Requirements <a id="mdspan.layout.reqmts">[[mdspan.layout.reqmts]]</a>
360
 
361
  A type `M` meets the *layout mapping* requirements if
362
 
@@ -480,20 +555,24 @@ m.stride(r)
480
 
481
  *Result:* `typename M::index_type`
482
 
483
  *Returns:* sᵣ as defined in `m.is_strided()` above.
484
 
 
 
 
 
485
  ``` cpp
486
  M::is_always_unique()
487
  ```
488
 
489
  *Result:* A constant expression [[expr.const]] of type `bool`.
490
 
491
  *Returns:* `true` only if `m.is_unique()` is `true` for all possible
492
  objects `m` of type `M`.
493
 
494
- [*Note 5*: A mapping can return `false` even if the above condition is
495
  met. For certain layout mappings, it is possibly not feasible to
496
  determine whether every instance is unique. — *end note*]
497
 
498
  ``` cpp
499
  M::is_always_exhaustive()
@@ -502,11 +581,11 @@ M::is_always_exhaustive()
502
  *Result:* A constant expression [[expr.const]] of type `bool`.
503
 
504
  *Returns:* `true` only if `m.is_exhaustive()` is `true` for all possible
505
  objects `m` of type `M`.
506
 
507
- [*Note 6*: A mapping can return `false` even if the above condition is
508
  met. For certain layout mappings, it is possibly not feasible to
509
  determine whether every instance is exhaustive. — *end note*]
510
 
511
  ``` cpp
512
  M::is_always_strided()
@@ -515,11 +594,11 @@ M::is_always_strided()
515
  *Result:* A constant expression [[expr.const]] of type `bool`.
516
 
517
  *Returns:* `true` only if `m.is_strided()` is `true` for all possible
518
  objects `m` of type `M`.
519
 
520
- [*Note 7*: A mapping can return `false` even if the above condition is
521
  met. For certain layout mappings, it is possibly not feasible to
522
  determine whether every instance is strided. — *end note*]
523
 
524
  ##### Layout mapping policy requirements <a id="mdspan.layout.policy.reqmts">[[mdspan.layout.policy.reqmts]]</a>
525
 
@@ -544,15 +623,27 @@ namespace std {
544
  };
545
  struct layout_stride {
546
  template<class Extents>
547
  class mapping;
548
  };
 
 
 
 
 
 
 
 
 
549
  }
550
  ```
551
 
552
- Each of `layout_left`, `layout_right`, and `layout_stride` meets the
553
- layout mapping policy requirements and is a trivial type.
 
 
 
554
 
555
  ##### Class template `layout_left::mapping` <a id="mdspan.layout.left">[[mdspan.layout.left]]</a>
556
 
557
  ###### Overview <a id="mdspan.layout.left.overview">[[mdspan.layout.left.overview]]</a>
558
 
@@ -563,13 +654,13 @@ stride 1, and strides increase left-to-right as the product of extents.
563
  namespace std {
564
  template<class Extents>
565
  class layout_left::mapping {
566
  public:
567
  using extents_type = Extents;
568
- using index_type = typename extents_type::index_type;
569
- using size_type = typename extents_type::size_type;
570
- using rank_type = typename extents_type::rank_type;
571
  using layout_type = layout_left;
572
 
573
  // [mdspan.layout.left.cons], constructors
574
  constexpr mapping() noexcept = default;
575
  constexpr mapping(const mapping&) noexcept = default;
@@ -578,10 +669,14 @@ namespace std {
578
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
579
  mapping(const mapping<OtherExtents>&) noexcept;
580
  template<class OtherExtents>
581
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
582
  mapping(const layout_right::mapping<OtherExtents>&) noexcept;
 
 
 
 
583
  template<class OtherExtents>
584
  constexpr explicit(extents_type::rank() > 0)
585
  mapping(const layout_stride::mapping<OtherExtents>&);
586
 
587
  constexpr mapping& operator=(const mapping&) noexcept = default;
@@ -607,10 +702,21 @@ namespace std {
607
  template<class OtherExtents>
608
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
609
 
610
  private:
611
  extents_type extents_{}; // exposition only
 
 
 
 
 
 
 
 
 
 
 
612
  };
613
  }
614
  ```
615
 
616
  If `Extents` is not a specialization of `extents`, then the program is
@@ -648,11 +754,11 @@ value of type `index_type` [[basic.fundamental]].
648
 
649
  *Effects:* Direct-non-list-initializes *extents\_* with
650
  `other.extents()`.
651
 
652
  ``` cpp
653
- template<class OtherExents>
654
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
655
  mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
656
  ```
657
 
658
  *Constraints:*
@@ -664,10 +770,44 @@ template<class OtherExents>
664
  value of type `index_type` [[basic.fundamental]].
665
 
666
  *Effects:* Direct-non-list-initializes *extents\_* with
667
  `other.extents()`.
668
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
  ``` cpp
670
  template<class OtherExtents>
671
  constexpr explicit(extents_type::rank() > 0)
672
  mapping(const layout_stride::mapping<OtherExtents>& other);
673
  ```
@@ -719,11 +859,11 @@ is `true`. Equivalent to:
719
  ``` cpp
720
  return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
721
  ```
722
 
723
  ``` cpp
724
- constexpr index_type stride(rank_type i) const;
725
  ```
726
 
727
  *Constraints:* `extents_type::rank() > 0` is `true`.
728
 
729
  *Preconditions:* `i < extents_type::rank()` is `true`.
@@ -750,13 +890,13 @@ stride 1, and strides increase right-to-left as the product of extents.
750
  namespace std {
751
  template<class Extents>
752
  class layout_right::mapping {
753
  public:
754
  using extents_type = Extents;
755
- using index_type = typename extents_type::index_type;
756
- using size_type = typename extents_type::size_type;
757
- using rank_type = typename extents_type::rank_type;
758
  using layout_type = layout_right;
759
 
760
  // [mdspan.layout.right.cons], constructors
761
  constexpr mapping() noexcept = default;
762
  constexpr mapping(const mapping&) noexcept = default;
@@ -765,10 +905,14 @@ namespace std {
765
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
766
  mapping(const mapping<OtherExtents>&) noexcept;
767
  template<class OtherExtents>
768
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
769
  mapping(const layout_left::mapping<OtherExtents>&) noexcept;
 
 
 
 
770
  template<class OtherExtents>
771
  constexpr explicit(extents_type::rank() > 0)
772
  mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
773
 
774
  constexpr mapping& operator=(const mapping&) noexcept = default;
@@ -794,10 +938,21 @@ namespace std {
794
  template<class OtherExtents>
795
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
796
 
797
  private:
798
  extents_type extents_{}; // exposition only
 
 
 
 
 
 
 
 
 
 
 
799
  };
800
  }
801
  ```
802
 
803
  If `Extents` is not a specialization of `extents`, then the program is
@@ -851,10 +1006,46 @@ template<class OtherExtents>
851
  value of type `index_type` [[basic.fundamental]].
852
 
853
  *Effects:* Direct-non-list-initializes *extents\_* with
854
  `other.extents()`.
855
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
856
  ``` cpp
857
  template<class OtherExtents>
858
  constexpr explicit(extents_type::rank() > 0)
859
  mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
860
  ```
@@ -874,11 +1065,11 @@ template<class OtherExtents>
874
  `other.extents()`.
875
 
876
  ###### Observers <a id="mdspan.layout.right.obs">[[mdspan.layout.right.obs]]</a>
877
 
878
  ``` cpp
879
- index_type required_span_size() const noexcept;
880
  ```
881
 
882
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
883
 
884
  ``` cpp
@@ -937,13 +1128,13 @@ user-defined.
937
  namespace std {
938
  template<class Extents>
939
  class layout_stride::mapping {
940
  public:
941
  using extents_type = Extents;
942
- using index_type = typename extents_type::index_type;
943
- using size_type = typename extents_type::size_type;
944
- using rank_type = typename extents_type::rank_type;
945
  using layout_type = layout_stride;
946
 
947
  private:
948
  static constexpr rank_type rank_ = extents_type::rank(); // exposition only
949
 
@@ -984,10 +1175,21 @@ namespace std {
984
  friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
985
 
986
  private:
987
  extents_type extents_{}; // exposition only
988
  array<index_type, rank_> strides_{}; // exposition only
 
 
 
 
 
 
 
 
 
 
 
989
  };
990
  }
991
  ```
992
 
993
  If `Extents` is not a specialization of `extents`, then the program is
@@ -1006,11 +1208,15 @@ Let `REQUIRED-SPAN-SIZE(e, strides)` be:
1006
 
1007
  - `1`, if `e.rank() == 0` is `true`,
1008
  - otherwise `0`, if the size of the multidimensional index space `e` is
1009
  0,
1010
  - otherwise `1` plus the sum of products of `(e.extent(r) - 1)` and
1011
- `strides[r]` for all r in the range [0, `e.rank()`).
 
 
 
 
1012
 
1013
  Let `OFFSET(m)` be:
1014
 
1015
  - `m()`, if `e.rank() == 0` is `true`,
1016
  - otherwise `0`, if the size of the multidimensional index space `e` is
@@ -1078,11 +1284,12 @@ template<class OtherIndexType>
1078
  - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
1079
  `true`.
1080
 
1081
  *Preconditions:*
1082
 
1083
- - `s[`i`] > 0` is `true` for all i in the range [0, rank_).
 
1084
  - *`REQUIRED-SPAN-SIZE`*`(e, s)` is representable as a value of type
1085
  `index_type` [[basic.fundamental]].
1086
  - If *rank\_* is greater than 0, then there exists a permutation P of
1087
  the integers in the range [0, rank_), such that
1088
  `s[`pᵢ`] >= s[`pᵢ₋₁`] * e.extent(p`ᵢ₋₁`)` is `true` for all i in the
@@ -1110,11 +1317,11 @@ template<class StridedLayoutMapping>
1110
  - `StridedLayoutMapping::is_always_strided()` is `true`.
1111
 
1112
  *Preconditions:*
1113
 
1114
  - `StridedLayoutMapping` meets the layout mapping
1115
- requirements [[mdspan.layout.policy.reqmts]],
1116
  - `other.stride(`r`) > 0` is `true` for every rank index r of
1117
  `extents()`,
1118
  - `other.required_span_size()` is representable as a value of type
1119
  `index_type` [[basic.fundamental]], and
1120
  - *`OFFSET`*`(other) == 0` is `true`.
@@ -1126,13 +1333,15 @@ direct-non-list-initializes *`strides_`*`[`d`]` with
1126
 
1127
  Remarks: The expression inside `explicit` is equivalent to:
1128
 
1129
  ``` cpp
1130
  !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
1131
- (is-mapping-of<layout_left, LayoutStrideMapping> ||
1132
- is-mapping-of<layout_right, LayoutStrideMapping> ||
1133
- is-mapping-of<layout_stride, LayoutStrideMapping>))
 
 
1134
  ```
1135
 
1136
  ###### Observers <a id="mdspan.layout.stride.obs">[[mdspan.layout.stride.obs]]</a>
1137
 
1138
  ``` cpp
@@ -1197,10 +1406,898 @@ requirements [[mdspan.layout.policy.reqmts]].
1197
  *Returns:* `true` if `x.extents() == y.extents()` is `true`,
1198
  *`OFFSET`*`(y) == 0` is `true`, and each of
1199
  `x.stride(`r`) == y.stride(`r`)` is `true` for r in the range
1200
  [0, `x.extents().rank()`). Otherwise, `false`.
1201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1202
  #### Accessor policy <a id="mdspan.accessor">[[mdspan.accessor]]</a>
1203
 
1204
  ##### General <a id="mdspan.accessor.general">[[mdspan.accessor.general]]</a>
1205
 
1206
  An *accessor policy* defines types and operations by which a reference
@@ -1209,11 +2306,11 @@ of such objects and an index.
1209
 
1210
  A range of indices [0, N) is an *accessible range* of a given data
1211
  handle and an accessor if, for each i in the range, the accessor
1212
  policy’s `access` function produces a valid reference to an object.
1213
 
1214
- In subclause [[mdspan.accessor.reqmts]],
1215
 
1216
  - `A` denotes an accessor policy.
1217
  - `a` denotes a value of type `A` or `const A`.
1218
  - `p` denotes a value of type `A::data_handle_type` or
1219
  `const A::data_handle_type`. \[*Note 1*: The type
@@ -1353,10 +2450,155 @@ constexpr reference access(data_handle_type p, size_t i) const noexcept;
1353
  constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
1354
  ```
1355
 
1356
  *Effects:* Equivalent to: `return p + i;`
1357
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1358
  #### Class template `mdspan` <a id="mdspan.mdspan">[[mdspan.mdspan]]</a>
1359
 
1360
  ##### Overview <a id="mdspan.mdspan.overview">[[mdspan.mdspan.overview]]</a>
1361
 
1362
  `mdspan` is a view of a multidimensional array of elements.
@@ -1368,18 +2610,18 @@ namespace std {
1368
  class mdspan {
1369
  public:
1370
  using extents_type = Extents;
1371
  using layout_type = LayoutPolicy;
1372
  using accessor_type = AccessorPolicy;
1373
- using mapping_type = typename layout_type::template mapping<extents_type>;
1374
  using element_type = ElementType;
1375
  using value_type = remove_cv_t<element_type>;
1376
- using index_type = typename extents_type::index_type;
1377
- using size_type = typename extents_type::size_type;
1378
- using rank_type = typename extents_type::rank_type;
1379
- using data_handle_type = typename accessor_type::data_handle_type;
1380
- using reference = typename accessor_type::reference;
1381
 
1382
  static constexpr rank_type rank() noexcept { return extents_type::rank(); }
1383
  static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
1384
  static constexpr size_t static_extent(rank_type r) noexcept
1385
  { return extents_type::static_extent(r); }
@@ -1417,12 +2659,22 @@ namespace std {
1417
  template<class OtherIndexType>
1418
  constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
1419
  template<class OtherIndexType>
1420
  constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
1421
 
 
 
 
 
 
 
 
 
 
 
1422
  constexpr size_type size() const noexcept;
1423
- [[nodiscard]] constexpr bool empty() const noexcept;
1424
 
1425
  friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
1426
 
1427
  constexpr const extents_type& extents() const noexcept { return map_.extents(); }
1428
  constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
@@ -1462,11 +2714,11 @@ namespace std {
1462
  -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
1463
 
1464
  template<class ElementType, class... Integrals>
1465
  requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
1466
  explicit mdspan(ElementType*, Integrals...)
1467
- -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
1468
 
1469
  template<class ElementType, class OtherIndexType, size_t N>
1470
  mdspan(ElementType*, span<OtherIndexType, N>)
1471
  -> mdspan<ElementType, dextents<size_t, N>>;
1472
 
@@ -1569,12 +2821,12 @@ template<class OtherIndexType, size_t N>
1569
  ```
1570
 
1571
  *Constraints:*
1572
 
1573
  - `is_convertible_v<const OtherIndexType&, index_type>` is `true`,
1574
- - `(is_nothrow_constructible<index_type, const OtherIndexType&> && ...)`
1575
- is `true`,
1576
  - `N == rank() || N == rank_dynamic()` is `true`,
1577
  - `is_constructible_v<mapping_type, extents_type>` is `true`, and
1578
  - `is_default_constructible_v<accessor_type>` is `true`.
1579
 
1580
  *Preconditions:* $[0, \texttt{\textit{map_}.required_span_size()})$ is
@@ -1653,18 +2905,17 @@ template<class OtherElementType, class OtherExtents,
1653
 
1654
  - `is_constructible_v<data_handle_type, const OtherAccessor::data_handle_type&>`
1655
  is `true`, and
1656
  - `is_constructible_v<extents_type, OtherExtents>` is `true`.
1657
 
1658
- *Preconditions:*
 
 
1659
 
1660
- - For each rank index `r` of `extents_type`,
1661
  `static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)`
1662
  is `true`.
1663
- - $[0, \texttt{\textit{map_}.required_span_size()})$ is an accessible
1664
- range of *ptr\_* and *acc\_* for values of *ptr\_*, *map\_*, and
1665
- *acc\_* after the invocation of this constructor.
1666
 
1667
  *Effects:*
1668
 
1669
  - Direct-non-list-initializes *ptr\_* with `other.`*`ptr_`*,
1670
  - direct-non-list-initializes *map\_* with `other.`*`map_`*, and
@@ -1691,11 +2942,11 @@ template<class... OtherIndexTypes>
1691
  `true`, and
1692
  - `sizeof...(OtherIndexTypes) == rank()` is `true`.
1693
 
1694
  Let `I` be `extents_type::`*`index-cast`*`(std::move(indices))`.
1695
 
1696
- *Preconditions:* `I` is a multidimensional index in `extents()`.
1697
 
1698
  [*Note 1*: This implies that
1699
  *`map_`*`(I) < `*`map_`*`.required_span_size()` is
1700
  `true`. — *end note*]
1701
 
@@ -1725,11 +2976,55 @@ is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
1725
  ```
1726
 
1727
  is `true`. Equivalent to:
1728
 
1729
  ``` cpp
1730
- return operator[](as_const(indices[P])...);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1731
  ```
1732
 
1733
  ``` cpp
1734
  constexpr size_type size() const noexcept;
1735
  ```
@@ -1739,11 +3034,11 @@ constexpr size_type size() const noexcept;
1739
  [[basic.fundamental]].
1740
 
1741
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(rank())`.
1742
 
1743
  ``` cpp
1744
- [[nodiscard]] constexpr bool empty() const noexcept;
1745
  ```
1746
 
1747
  *Returns:* `true` if the size of the multidimensional index space
1748
  `extents()` is 0, otherwise `false`.
1749
 
@@ -1757,10 +3052,599 @@ friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
1757
  swap(x.ptr_, y.ptr_);
1758
  swap(x.map_, y.map_);
1759
  swap(x.acc_, y.acc_);
1760
  ```
1761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1762
  <!-- Link reference definitions -->
1763
  [alg.equal]: algorithms.md#alg.equal
1764
  [alg.sorting]: algorithms.md#alg.sorting
1765
  [algorithm.stable]: library.md#algorithm.stable
1766
  [algorithms]: algorithms.md#algorithms
@@ -1784,20 +3668,21 @@ swap(x.acc_, y.acc_);
1784
  [associative.reqmts]: #associative.reqmts
1785
  [associative.reqmts.except]: #associative.reqmts.except
1786
  [associative.reqmts.general]: #associative.reqmts.general
1787
  [associative.set.syn]: #associative.set.syn
1788
  [basic.fundamental]: basic.md#basic.fundamental
 
1789
  [basic.string]: strings.md#basic.string
1790
  [class.copy.ctor]: class.md#class.copy.ctor
1791
  [class.default.ctor]: class.md#class.default.ctor
1792
  [class.dtor]: class.md#class.dtor
1793
  [container.adaptors]: #container.adaptors
1794
  [container.adaptors.format]: #container.adaptors.format
1795
  [container.adaptors.general]: #container.adaptors.general
1796
  [container.alloc.reqmts]: #container.alloc.reqmts
1797
- [container.gen.reqmts]: #container.gen.reqmts
1798
  [container.insert.return]: #container.insert.return
 
1799
  [container.node]: #container.node
1800
  [container.node.compat]: #container.node.compat
1801
  [container.node.cons]: #container.node.cons
1802
  [container.node.dtor]: #container.node.dtor
1803
  [container.node.modifiers]: #container.node.modifiers
@@ -1825,28 +3710,32 @@ swap(x.acc_, y.acc_);
1825
  [expr.const]: expr.md#expr.const
1826
  [flat.map]: #flat.map
1827
  [flat.map.access]: #flat.map.access
1828
  [flat.map.capacity]: #flat.map.capacity
1829
  [flat.map.cons]: #flat.map.cons
 
1830
  [flat.map.defn]: #flat.map.defn
1831
  [flat.map.erasure]: #flat.map.erasure
1832
  [flat.map.modifiers]: #flat.map.modifiers
1833
  [flat.map.overview]: #flat.map.overview
1834
  [flat.map.syn]: #flat.map.syn
1835
  [flat.multimap]: #flat.multimap
1836
  [flat.multimap.cons]: #flat.multimap.cons
 
1837
  [flat.multimap.defn]: #flat.multimap.defn
1838
  [flat.multimap.erasure]: #flat.multimap.erasure
1839
  [flat.multimap.overview]: #flat.multimap.overview
1840
  [flat.multiset]: #flat.multiset
1841
  [flat.multiset.cons]: #flat.multiset.cons
 
1842
  [flat.multiset.defn]: #flat.multiset.defn
1843
  [flat.multiset.erasure]: #flat.multiset.erasure
1844
  [flat.multiset.modifiers]: #flat.multiset.modifiers
1845
  [flat.multiset.overview]: #flat.multiset.overview
1846
  [flat.set]: #flat.set
1847
  [flat.set.cons]: #flat.set.cons
 
1848
  [flat.set.defn]: #flat.set.defn
1849
  [flat.set.erasure]: #flat.set.erasure
1850
  [flat.set.modifiers]: #flat.set.modifiers
1851
  [flat.set.overview]: #flat.set.overview
1852
  [flat.set.syn]: #flat.set.syn
@@ -1859,10 +3748,26 @@ swap(x.acc_, y.acc_);
1859
  [forward.list.modifiers]: #forward.list.modifiers
1860
  [forward.list.ops]: #forward.list.ops
1861
  [forward.list.overview]: #forward.list.overview
1862
  [forward.list.syn]: #forward.list.syn
1863
  [hash.requirements]: library.md#hash.requirements
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1864
  [iterator.concept.contiguous]: iterators.md#iterator.concept.contiguous
1865
  [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
1866
  [iterator.requirements]: iterators.md#iterator.requirements
1867
  [iterator.requirements.general]: iterators.md#iterator.requirements.general
1868
  [list]: #list
@@ -1878,45 +3783,73 @@ swap(x.acc_, y.acc_);
1878
  [map.cons]: #map.cons
1879
  [map.erasure]: #map.erasure
1880
  [map.modifiers]: #map.modifiers
1881
  [map.overview]: #map.overview
1882
  [mdspan.accessor]: #mdspan.accessor
 
 
 
1883
  [mdspan.accessor.default]: #mdspan.accessor.default
1884
  [mdspan.accessor.default.members]: #mdspan.accessor.default.members
1885
  [mdspan.accessor.default.overview]: #mdspan.accessor.default.overview
1886
  [mdspan.accessor.general]: #mdspan.accessor.general
1887
  [mdspan.accessor.reqmts]: #mdspan.accessor.reqmts
1888
  [mdspan.extents]: #mdspan.extents
1889
  [mdspan.extents.cmp]: #mdspan.extents.cmp
1890
  [mdspan.extents.cons]: #mdspan.extents.cons
1891
  [mdspan.extents.dextents]: #mdspan.extents.dextents
 
1892
  [mdspan.extents.expo]: #mdspan.extents.expo
1893
  [mdspan.extents.obs]: #mdspan.extents.obs
1894
  [mdspan.extents.overview]: #mdspan.extents.overview
1895
  [mdspan.layout]: #mdspan.layout
1896
  [mdspan.layout.general]: #mdspan.layout.general
1897
  [mdspan.layout.left]: #mdspan.layout.left
1898
  [mdspan.layout.left.cons]: #mdspan.layout.left.cons
1899
  [mdspan.layout.left.obs]: #mdspan.layout.left.obs
1900
  [mdspan.layout.left.overview]: #mdspan.layout.left.overview
 
 
 
 
 
1901
  [mdspan.layout.policy.overview]: #mdspan.layout.policy.overview
1902
  [mdspan.layout.policy.reqmts]: #mdspan.layout.policy.reqmts
1903
  [mdspan.layout.reqmts]: #mdspan.layout.reqmts
1904
  [mdspan.layout.right]: #mdspan.layout.right
1905
  [mdspan.layout.right.cons]: #mdspan.layout.right.cons
1906
  [mdspan.layout.right.obs]: #mdspan.layout.right.obs
1907
  [mdspan.layout.right.overview]: #mdspan.layout.right.overview
 
 
 
 
 
1908
  [mdspan.layout.stride]: #mdspan.layout.stride
1909
  [mdspan.layout.stride.cons]: #mdspan.layout.stride.cons
1910
  [mdspan.layout.stride.expo]: #mdspan.layout.stride.expo
1911
  [mdspan.layout.stride.obs]: #mdspan.layout.stride.obs
1912
  [mdspan.layout.stride.overview]: #mdspan.layout.stride.overview
1913
  [mdspan.mdspan]: #mdspan.mdspan
1914
  [mdspan.mdspan.cons]: #mdspan.mdspan.cons
1915
  [mdspan.mdspan.members]: #mdspan.mdspan.members
1916
  [mdspan.mdspan.overview]: #mdspan.mdspan.overview
1917
  [mdspan.overview]: #mdspan.overview
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1918
  [mdspan.syn]: #mdspan.syn
1919
  [multimap]: #multimap
1920
  [multimap.cons]: #multimap.cons
1921
  [multimap.erasure]: #multimap.erasure
1922
  [multimap.modifiers]: #multimap.modifiers
@@ -1938,17 +3871,19 @@ swap(x.acc_, y.acc_);
1938
  [queue.mod]: #queue.mod
1939
  [queue.ops]: #queue.ops
1940
  [queue.special]: #queue.special
1941
  [queue.syn]: #queue.syn
1942
  [random.access.iterators]: iterators.md#random.access.iterators
 
1943
  [res.on.data.races]: library.md#res.on.data.races
1944
  [sequence.reqmts]: #sequence.reqmts
1945
  [sequences]: #sequences
1946
  [sequences.general]: #sequences.general
1947
  [set]: #set
1948
  [set.cons]: #set.cons
1949
  [set.erasure]: #set.erasure
 
1950
  [set.overview]: #set.overview
1951
  [span.cons]: #span.cons
1952
  [span.deduct]: #span.deduct
1953
  [span.elem]: #span.elem
1954
  [span.iterators]: #span.iterators
@@ -1964,15 +3899,16 @@ swap(x.acc_, y.acc_);
1964
  [stack.general]: #stack.general
1965
  [stack.mod]: #stack.mod
1966
  [stack.ops]: #stack.ops
1967
  [stack.special]: #stack.special
1968
  [stack.syn]: #stack.syn
 
1969
  [strings]: strings.md#strings
1970
  [swappable.requirements]: library.md#swappable.requirements
1971
  [temp.deduct]: temp.md#temp.deduct
1972
- [temp.param]: temp.md#temp.param
1973
  [temp.type]: temp.md#temp.type
 
1974
  [term.trivially.copyable.type]: basic.md#term.trivially.copyable.type
1975
  [unord]: #unord
1976
  [unord.general]: #unord.general
1977
  [unord.hash]: utilities.md#unord.hash
1978
  [unord.map]: #unord.map
@@ -1995,10 +3931,11 @@ swap(x.acc_, y.acc_);
1995
  [unord.req.except]: #unord.req.except
1996
  [unord.req.general]: #unord.req.general
1997
  [unord.set]: #unord.set
1998
  [unord.set.cnstr]: #unord.set.cnstr
1999
  [unord.set.erasure]: #unord.set.erasure
 
2000
  [unord.set.overview]: #unord.set.overview
2001
  [unord.set.syn]: #unord.set.syn
2002
  [vector]: #vector
2003
  [vector.bool]: #vector.bool
2004
  [vector.bool.fmt]: #vector.bool.fmt
 
22
  the interval [Lᵢ, Uᵢ) of S.
23
 
24
  #### Header `<mdspan>` synopsis <a id="mdspan.syn">[[mdspan.syn]]</a>
25
 
26
  ``` cpp
27
+ // mostly freestanding
28
  namespace std {
29
  // [mdspan.extents], class template extents
30
  template<class IndexType, size_t... Extents>
31
  class extents;
32
 
33
  // [mdspan.extents.dextents], alias template dextents
34
  template<class IndexType, size_t Rank>
35
  using dextents = see below;
36
 
37
+ // [mdspan.extents.dims], alias template dims
38
+ template<size_t Rank, class IndexType = size_t>
39
+ using dims = see below;
40
+
41
  // [mdspan.layout], layout mapping
42
  struct layout_left;
43
  struct layout_right;
44
  struct layout_stride;
45
+ template<size_t PaddingValue = dynamic_extent>
46
+ struct layout_left_padded;
47
+ template<size_t PaddingValue = dynamic_extent>
48
+ struct layout_right_padded;
49
 
50
  // [mdspan.accessor.default], class template default_accessor
51
  template<class ElementType>
52
  class default_accessor;
53
 
54
+ // [mdspan.accessor.aligned], class template aligned_accessor
55
+ template<class ElementType, size_t ByteAlignment>
56
+ class aligned_accessor;
57
+
58
  // [mdspan.mdspan], class template mdspan
59
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
60
  class AccessorPolicy = default_accessor<ElementType>>
61
+ class mdspan; // partially freestanding
62
+
63
+ // [mdspan.sub], submdspan creation
64
+ template<class OffsetType, class LengthType, class StrideType>
65
+ struct strided_slice;
66
+
67
+ template<class LayoutMapping>
68
+ struct submdspan_mapping_result;
69
+
70
+ struct full_extent_t { explicit full_extent_t() = default; };
71
+ inline constexpr full_extent_t full_extent{};
72
+
73
+ template<class IndexType, size_t... Extents, class... SliceSpecifiers>
74
+ constexpr auto submdspan_extents(const extents<IndexType, Extents...>&, SliceSpecifiers...);
75
+
76
+ // [mdspan.sub.sub], submdspan function template
77
+ template<class ElementType, class Extents, class LayoutPolicy,
78
+ class AccessorPolicy, class... SliceSpecifiers>
79
+ constexpr auto submdspan(
80
+ const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
81
+ SliceSpecifiers... slices) -> see below;
82
+
83
+ template<class T, class IndexType>
84
+ concept index-pair-like = // exposition only
85
+ pair-like<T> &&
86
+ convertible_to<tuple_element_t<0, T>, IndexType> &&
87
+ convertible_to<tuple_element_t<1, T>, IndexType>;
88
  }
89
  ```
90
 
91
  #### Class template `extents` <a id="mdspan.extents">[[mdspan.extents]]</a>
92
 
93
  ##### Overview <a id="mdspan.extents.overview">[[mdspan.extents.overview]]</a>
94
 
95
  The class template `extents` represents a multidimensional index space
96
+ of rank equal to `sizeof...(Extents)`. In  [[views]], `extents` is used
97
+ synonymously with multidimensional index space.
98
 
99
  ``` cpp
100
  namespace std {
101
  template<class IndexType, size_t... Extents>
102
  class extents {
 
276
 
277
  - If `N != rank_dynamic()` is `true`, `exts_arr[`r`]` equals Eᵣ for each
278
  r for which Eᵣ is a static extent, and
279
  - either
280
  - `sizeof...(exts) == 0` is `true`, or
281
+ - each element of `exts` is representable as a nonnegative value of
282
+ type `index_type`.
283
 
284
  *Ensures:* `*this == extents(exts_arr)` is `true`.
285
 
286
  ``` cpp
287
  template<class OtherIndexType, size_t N>
 
303
 
304
  - If `N != rank_dynamic()` is `true`, `exts[`r`]` equals Eᵣ for each r
305
  for which Eᵣ is a static extent, and
306
  - either
307
  - `N` is zero, or
308
+ - `exts[`r`]` is representable as a nonnegative value of type
309
  `index_type` for every rank index r.
310
 
311
  *Effects:*
312
 
313
+ - If `N` equals `rank_dynamic()`, for all d in the range
314
  [0, `rank_dynamic()`), direct-non-list-initializes
315
  *`dynamic-extents`*`[`d`]` with `as_const(exts[`d`])`.
316
  - Otherwise, for all d in the range [0, `rank_dynamic()`),
317
  direct-non-list-initializes *`dynamic-extents`*`[`d`]` with
318
  `as_const(exts[`*`dynamic-index-inv`*`(`d`)])`.
 
322
  explicit extents(Integrals...) -> see below;
323
  ```
324
 
325
  *Constraints:* `(is_convertible_v<Integrals, size_t> && ...)` is `true`.
326
 
327
+ *Remarks:* The deduced type is
328
+ `extents<size_t, maybe-static-ext<Integrals>...>`.
329
 
330
  ##### Observers of the multidimensional index space <a id="mdspan.extents.obs">[[mdspan.extents.obs]]</a>
331
 
332
  ``` cpp
333
  static constexpr size_t static_extent(rank_type i) noexcept;
 
366
 
367
  *Result:* A type `E` that is a specialization of `extents` such that
368
  `E::rank() == Rank && E::rank() == E::rank_dynamic()` is `true`, and
369
  `E::index_type` denotes `IndexType`.
370
 
371
+ ##### Alias template `dims` <a id="mdspan.extents.dims">[[mdspan.extents.dims]]</a>
372
+
373
+ ``` cpp
374
+ template<size_t Rank, class IndexType = size_t>
375
+ using dims = see below;
376
+ ```
377
+
378
+ *Result:* A type `E` that is a specialization of `extents` such that
379
+ `E::rank() == Rank && E::rank() == E::rank_dynamic()` is `true`, and
380
+ `E::index_type` denotes `IndexType`.
381
+
382
  #### Layout mapping <a id="mdspan.layout">[[mdspan.layout]]</a>
383
 
384
  ##### General <a id="mdspan.layout.general">[[mdspan.layout.general]]</a>
385
 
386
+ In [[mdspan.layout.reqmts]] and [[mdspan.layout.policy.reqmts]]:
 
387
 
388
  - `M` denotes a layout mapping class.
389
  - `m` denotes a (possibly const) value of type `M`.
390
  - `i` and `j` are packs of (possibly const) integers that are
391
  multidimensional indices in `m.extents()` [[mdspan.overview]].
 
394
  - `r` is a (possibly const) rank index of `typename M::extents_type`.
395
  - `dᵣ` is a pack of (possibly const) integers for which
396
  `sizeof...(dᵣ) == M::extents_type::rank()` is `true`, the rᵗʰ element
397
  is equal to 1, and all other elements are equal to 0.
398
 
399
+ In [[mdspan.layout.reqmts]] through [[mdspan.layout.stride]]:
400
+
401
+ - Let *`is-mapping-of`* be the exposition-only variable template defined
402
  as follows:
 
403
  ``` cpp
404
  template<class Layout, class Mapping>
405
  constexpr bool is-mapping-of = // exposition only
406
  is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
407
  ```
408
+ - Let *`is-layout-left-padded-mapping-of`* be the exposition-only
409
+ variable template defined as follows:
410
+ ``` cpp
411
+ template<class Mapping>
412
+ constexpr bool is-layout-left-padded-mapping-of = see below; // exposition only
413
+ ```
414
+
415
+ where `is-layout-left-padded-mapping-of<Mapping>` is `true` if and
416
+ only if `Mapping` denotes a specialization of
417
+ `layout_left_padded<S>::mapping` for some value `S` of type `size_t`.
418
+ - Let *`is-layout-right-padded-mapping-of`* be the exposition-only
419
+ variable template defined as follows:
420
+ ``` cpp
421
+ template<class Mapping>
422
+ constexpr bool is-layout-right-padded-mapping-of = see below; // exposition only
423
+ ```
424
+
425
+ where `is-layout-right-padded-mapping-of<Mapping>` is `true` if and
426
+ only if `Mapping` denotes a specialization of
427
+ `layout_right_padded<S>::mapping` for some value `S` of type `size_t`.
428
+ - For nonnegative integers x and y, let LEAST-MULTIPLE-AT-LEAST(x, y)
429
+ denote
430
+ - y if x is zero,
431
+ - otherwise, the least multiple of x that is greater than or equal to
432
+ y.
433
 
434
  ##### Requirements <a id="mdspan.layout.reqmts">[[mdspan.layout.reqmts]]</a>
435
 
436
  A type `M` meets the *layout mapping* requirements if
437
 
 
555
 
556
  *Result:* `typename M::index_type`
557
 
558
  *Returns:* sᵣ as defined in `m.is_strided()` above.
559
 
560
+ [*Note 5*: It is not required for `m.stride(r)` to be well-formed if
561
+ `m.extents().rank()` is zero, even if `m.is_always_strided()` is
562
+ `true`. — *end note*]
563
+
564
  ``` cpp
565
  M::is_always_unique()
566
  ```
567
 
568
  *Result:* A constant expression [[expr.const]] of type `bool`.
569
 
570
  *Returns:* `true` only if `m.is_unique()` is `true` for all possible
571
  objects `m` of type `M`.
572
 
573
+ [*Note 6*: A mapping can return `false` even if the above condition is
574
  met. For certain layout mappings, it is possibly not feasible to
575
  determine whether every instance is unique. — *end note*]
576
 
577
  ``` cpp
578
  M::is_always_exhaustive()
 
581
  *Result:* A constant expression [[expr.const]] of type `bool`.
582
 
583
  *Returns:* `true` only if `m.is_exhaustive()` is `true` for all possible
584
  objects `m` of type `M`.
585
 
586
+ [*Note 7*: A mapping can return `false` even if the above condition is
587
  met. For certain layout mappings, it is possibly not feasible to
588
  determine whether every instance is exhaustive. — *end note*]
589
 
590
  ``` cpp
591
  M::is_always_strided()
 
594
  *Result:* A constant expression [[expr.const]] of type `bool`.
595
 
596
  *Returns:* `true` only if `m.is_strided()` is `true` for all possible
597
  objects `m` of type `M`.
598
 
599
+ [*Note 8*: A mapping can return `false` even if the above condition is
600
  met. For certain layout mappings, it is possibly not feasible to
601
  determine whether every instance is strided. — *end note*]
602
 
603
  ##### Layout mapping policy requirements <a id="mdspan.layout.policy.reqmts">[[mdspan.layout.policy.reqmts]]</a>
604
 
 
623
  };
624
  struct layout_stride {
625
  template<class Extents>
626
  class mapping;
627
  };
628
+
629
+ template<size_t PaddingValue>
630
+ struct layout_left_padded {
631
+ template<class Extents> class mapping;
632
+ };
633
+ template<size_t PaddingValue>
634
+ struct layout_right_padded {
635
+ template<class Extents> class mapping;
636
+ };
637
  }
638
  ```
639
 
640
+ Each of `layout_left`, `layout_right`, and `layout_stride`, as well as
641
+ each specialization of `layout_left_padded` and `layout_right_padded`,
642
+ meets the layout mapping policy requirements and is a trivially copyable
643
+ type. Furthermore, `is_trivially_default_constructible_v<T>` is `true`
644
+ for any such type `T`.
645
 
646
  ##### Class template `layout_left::mapping` <a id="mdspan.layout.left">[[mdspan.layout.left]]</a>
647
 
648
  ###### Overview <a id="mdspan.layout.left.overview">[[mdspan.layout.left.overview]]</a>
649
 
 
654
  namespace std {
655
  template<class Extents>
656
  class layout_left::mapping {
657
  public:
658
  using extents_type = Extents;
659
+ using index_type = extents_type::index_type;
660
+ using size_type = extents_type::size_type;
661
+ using rank_type = extents_type::rank_type;
662
  using layout_type = layout_left;
663
 
664
  // [mdspan.layout.left.cons], constructors
665
  constexpr mapping() noexcept = default;
666
  constexpr mapping(const mapping&) noexcept = default;
 
669
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
670
  mapping(const mapping<OtherExtents>&) noexcept;
671
  template<class OtherExtents>
672
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
673
  mapping(const layout_right::mapping<OtherExtents>&) noexcept;
674
+ template<class LayoutLeftPaddedMapping>
675
+ constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
676
+ extents_type>)
677
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
678
  template<class OtherExtents>
679
  constexpr explicit(extents_type::rank() > 0)
680
  mapping(const layout_stride::mapping<OtherExtents>&);
681
 
682
  constexpr mapping& operator=(const mapping&) noexcept = default;
 
702
  template<class OtherExtents>
703
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
704
 
705
  private:
706
  extents_type extents_{}; // exposition only
707
+
708
+ // [mdspan.sub.map], submdspan mapping specialization
709
+ template<class... SliceSpecifiers>
710
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
711
+ -> see below;
712
+
713
+ template<class... SliceSpecifiers>
714
+ friend constexpr auto submdspan_mapping(
715
+ const mapping& src, SliceSpecifiers... slices) {
716
+ return src.submdspan-mapping-impl(slices...);
717
+ }
718
  };
719
  }
720
  ```
721
 
722
  If `Extents` is not a specialization of `extents`, then the program is
 
754
 
755
  *Effects:* Direct-non-list-initializes *extents\_* with
756
  `other.extents()`.
757
 
758
  ``` cpp
759
+ template<class OtherExtents>
760
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
761
  mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
762
  ```
763
 
764
  *Constraints:*
 
770
  value of type `index_type` [[basic.fundamental]].
771
 
772
  *Effects:* Direct-non-list-initializes *extents\_* with
773
  `other.extents()`.
774
 
775
+ ``` cpp
776
+ template<class LayoutLeftPaddedMapping>
777
+ constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
778
+ extents_type>)
779
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
780
+ ```
781
+
782
+ *Constraints:*
783
+
784
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
785
+ `true`.
786
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
787
+ is `true`.
788
+
789
+ *Mandates:* If
790
+
791
+ - `Extents::rank()` is greater than one,
792
+ - `Extents::static_extent(0)` does not equal `dynamic_extent`, and
793
+ - `LayoutLeftPaddedMapping::`*`static-padding-stride`* does not equal
794
+ `dynamic_extent`,
795
+
796
+ then `Extents::static_extent(0)` equals
797
+ `LayoutLeftPaddedMapping::`*`static-padding-stride`*.
798
+
799
+ *Preconditions:*
800
+
801
+ - If `extents_type::rank() > 1` is `true`, then `other.stride(1)` equals
802
+ `other.extents().extent(0)`.
803
+ - `other.required_span_size()` is representable as a value of type
804
+ `index_type`.
805
+
806
+ *Effects:* Direct-non-list-initializes `extents_` with
807
+ `other.extents()`.
808
+
809
  ``` cpp
810
  template<class OtherExtents>
811
  constexpr explicit(extents_type::rank() > 0)
812
  mapping(const layout_stride::mapping<OtherExtents>& other);
813
  ```
 
859
  ``` cpp
860
  return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
861
  ```
862
 
863
  ``` cpp
864
+ constexpr index_type stride(rank_type i) const noexcept;
865
  ```
866
 
867
  *Constraints:* `extents_type::rank() > 0` is `true`.
868
 
869
  *Preconditions:* `i < extents_type::rank()` is `true`.
 
890
  namespace std {
891
  template<class Extents>
892
  class layout_right::mapping {
893
  public:
894
  using extents_type = Extents;
895
+ using index_type = extents_type::index_type;
896
+ using size_type = extents_type::size_type;
897
+ using rank_type = extents_type::rank_type;
898
  using layout_type = layout_right;
899
 
900
  // [mdspan.layout.right.cons], constructors
901
  constexpr mapping() noexcept = default;
902
  constexpr mapping(const mapping&) noexcept = default;
 
905
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
906
  mapping(const mapping<OtherExtents>&) noexcept;
907
  template<class OtherExtents>
908
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
909
  mapping(const layout_left::mapping<OtherExtents>&) noexcept;
910
+ template<class LayoutRightPaddedMapping>
911
+ constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
912
+ extents_type>)
913
+ mapping(const LayoutRightPaddedMapping&) noexcept;
914
  template<class OtherExtents>
915
  constexpr explicit(extents_type::rank() > 0)
916
  mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
917
 
918
  constexpr mapping& operator=(const mapping&) noexcept = default;
 
938
  template<class OtherExtents>
939
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
940
 
941
  private:
942
  extents_type extents_{}; // exposition only
943
+
944
+ // [mdspan.sub.map], submdspan mapping specialization
945
+ template<class... SliceSpecifiers>
946
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
947
+ -> see below;
948
+
949
+ template<class... SliceSpecifiers>
950
+ friend constexpr auto submdspan_mapping(
951
+ const mapping& src, SliceSpecifiers... slices) {
952
+ return src.submdspan-mapping-impl(slices...);
953
+ }
954
  };
955
  }
956
  ```
957
 
958
  If `Extents` is not a specialization of `extents`, then the program is
 
1006
  value of type `index_type` [[basic.fundamental]].
1007
 
1008
  *Effects:* Direct-non-list-initializes *extents\_* with
1009
  `other.extents()`.
1010
 
1011
+ ``` cpp
1012
+ template<class LayoutRightPaddedMapping>
1013
+ constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
1014
+ extents_type>)
1015
+ mapping(const LayoutRightPaddedMapping&) noexcept;
1016
+ ```
1017
+
1018
+ *Constraints:*
1019
+
1020
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
1021
+ `true`.
1022
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
1023
+ is `true`.
1024
+
1025
+ *Mandates:* If
1026
+
1027
+ - `Extents::rank()` is greater than one,
1028
+ - `Extents::static_extent(Extents::rank() - 1)` does not equal
1029
+ `dynamic_extent`, and
1030
+ - `LayoutRightPaddedMapping::`*`static-padding-stride`* does not equal
1031
+ `dynamic_extent`,
1032
+
1033
+ then `Extents::static_extent(Extents::rank() - 1)` equals
1034
+ `LayoutRightPaddedMapping::`*`static-padding-stride`*.
1035
+
1036
+ *Preconditions:*
1037
+
1038
+ - If `extents_type::rank() > 1` is `true`, then
1039
+ `other.stride(extents_type::rank() - 2)` equals
1040
+ `other.extents().extent(extents_type::rank() - 1)`.
1041
+ - `other.required_span_size()` is representable as a value of type
1042
+ `index_type`.
1043
+
1044
+ *Effects:* Direct-non-list-initializes `extents_` with
1045
+ `other.extents()`.
1046
+
1047
  ``` cpp
1048
  template<class OtherExtents>
1049
  constexpr explicit(extents_type::rank() > 0)
1050
  mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
1051
  ```
 
1065
  `other.extents()`.
1066
 
1067
  ###### Observers <a id="mdspan.layout.right.obs">[[mdspan.layout.right.obs]]</a>
1068
 
1069
  ``` cpp
1070
+ constexpr index_type required_span_size() const noexcept;
1071
  ```
1072
 
1073
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
1074
 
1075
  ``` cpp
 
1128
  namespace std {
1129
  template<class Extents>
1130
  class layout_stride::mapping {
1131
  public:
1132
  using extents_type = Extents;
1133
+ using index_type = extents_type::index_type;
1134
+ using size_type = extents_type::size_type;
1135
+ using rank_type = extents_type::rank_type;
1136
  using layout_type = layout_stride;
1137
 
1138
  private:
1139
  static constexpr rank_type rank_ = extents_type::rank(); // exposition only
1140
 
 
1175
  friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
1176
 
1177
  private:
1178
  extents_type extents_{}; // exposition only
1179
  array<index_type, rank_> strides_{}; // exposition only
1180
+
1181
+ // [mdspan.sub.map], submdspan mapping specialization
1182
+ template<class... SliceSpecifiers>
1183
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1184
+ -> see below;
1185
+
1186
+ template<class... SliceSpecifiers>
1187
+ friend constexpr auto submdspan_mapping(
1188
+ const mapping& src, SliceSpecifiers... slices) {
1189
+ return src.submdspan-mapping-impl(slices...);
1190
+ }
1191
  };
1192
  }
1193
  ```
1194
 
1195
  If `Extents` is not a specialization of `extents`, then the program is
 
1208
 
1209
  - `1`, if `e.rank() == 0` is `true`,
1210
  - otherwise `0`, if the size of the multidimensional index space `e` is
1211
  0,
1212
  - otherwise `1` plus the sum of products of `(e.extent(r) - 1)` and
1213
+ ``` cpp
1214
+ extents_type::index-cast(strides[r])
1215
+ ```
1216
+
1217
+ for all r in the range [0, `e.rank()`).
1218
 
1219
  Let `OFFSET(m)` be:
1220
 
1221
  - `m()`, if `e.rank() == 0` is `true`,
1222
  - otherwise `0`, if the size of the multidimensional index space `e` is
 
1284
  - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
1285
  `true`.
1286
 
1287
  *Preconditions:*
1288
 
1289
+ - The result of converting `s[`i`]` to `index_type` is greater than `0`
1290
+ for all i in the range [0, rank_).
1291
  - *`REQUIRED-SPAN-SIZE`*`(e, s)` is representable as a value of type
1292
  `index_type` [[basic.fundamental]].
1293
  - If *rank\_* is greater than 0, then there exists a permutation P of
1294
  the integers in the range [0, rank_), such that
1295
  `s[`pᵢ`] >= s[`pᵢ₋₁`] * e.extent(p`ᵢ₋₁`)` is `true` for all i in the
 
1317
  - `StridedLayoutMapping::is_always_strided()` is `true`.
1318
 
1319
  *Preconditions:*
1320
 
1321
  - `StridedLayoutMapping` meets the layout mapping
1322
+ requirements [[mdspan.layout.reqmts]],
1323
  - `other.stride(`r`) > 0` is `true` for every rank index r of
1324
  `extents()`,
1325
  - `other.required_span_size()` is representable as a value of type
1326
  `index_type` [[basic.fundamental]], and
1327
  - *`OFFSET`*`(other) == 0` is `true`.
 
1333
 
1334
  Remarks: The expression inside `explicit` is equivalent to:
1335
 
1336
  ``` cpp
1337
  !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
1338
+ (is-mapping-of<layout_left, StridedLayoutMapping> ||
1339
+ is-mapping-of<layout_right, StridedLayoutMapping> ||
1340
+ is-layout-left-padded-mapping-of<StridedLayoutMapping> ||
1341
+ is-layout-right-padded-mapping-of<StridedLayoutMapping> ||
1342
+ is-mapping-of<layout_stride, StridedLayoutMapping>))
1343
  ```
1344
 
1345
  ###### Observers <a id="mdspan.layout.stride.obs">[[mdspan.layout.stride.obs]]</a>
1346
 
1347
  ``` cpp
 
1406
  *Returns:* `true` if `x.extents() == y.extents()` is `true`,
1407
  *`OFFSET`*`(y) == 0` is `true`, and each of
1408
  `x.stride(`r`) == y.stride(`r`)` is `true` for r in the range
1409
  [0, `x.extents().rank()`). Otherwise, `false`.
1410
 
1411
+ ##### Class template `layout_left_padded::mapping` <a id="mdspan.layout.leftpad">[[mdspan.layout.leftpad]]</a>
1412
+
1413
+ ###### Overview <a id="mdspan.layout.leftpad.overview">[[mdspan.layout.leftpad.overview]]</a>
1414
+
1415
+ `layout_left_padded` provides a layout mapping that behaves like
1416
+ `layout_left::mapping`, except that the padding stride `stride(1)` can
1417
+ be greater than or equal to `extent(0)`.
1418
+
1419
+ ``` cpp
1420
+ namespace std {
1421
+ template<size_t PaddingValue>
1422
+ template<class Extents>
1423
+ class layout_left_padded<PaddingValue>::mapping {
1424
+ public:
1425
+ static constexpr size_t padding_value = PaddingValue;
1426
+
1427
+ using extents_type = Extents;
1428
+ using index_type = extents_type::index_type;
1429
+ using size_type = extents_type::size_type;
1430
+ using rank_type = extents_type::rank_type;
1431
+ using layout_type = layout_left_padded<PaddingValue>;
1432
+
1433
+ private:
1434
+ static constexpr size_t rank_ = extents_type::rank(); // exposition only
1435
+ static constexpr size_t first-static-extent = // exposition only
1436
+ extents_type::static_extent(0);
1437
+
1438
+ // [mdspan.layout.leftpad.expo], exposition-only members
1439
+ static constexpr size_t static-padding-stride = see below; // exposition only
1440
+
1441
+ public:
1442
+ // [mdspan.layout.leftpad.cons], constructors
1443
+ constexpr mapping() noexcept : mapping(extents_type{}) {}
1444
+ constexpr mapping(const mapping&) noexcept = default;
1445
+ constexpr mapping(const extents_type&);
1446
+ template<class OtherIndexType>
1447
+ constexpr mapping(const extents_type&, OtherIndexType);
1448
+ template<class OtherExtents>
1449
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1450
+ mapping(const layout_left::mapping<OtherExtents>&);
1451
+ template<class OtherExtents>
1452
+ constexpr explicit(extents_type::rank() > 0)
1453
+ mapping(const layout_stride::mapping<OtherExtents>&);
1454
+ template<class LayoutLeftPaddedMapping>
1455
+ constexpr explicit(see below)
1456
+ mapping(const LayoutLeftPaddedMapping&);
1457
+ template<class LayoutRightPaddedMapping>
1458
+ constexpr explicit(see below)
1459
+ mapping(const LayoutRightPaddedMapping&) noexcept;
1460
+
1461
+ constexpr mapping& operator=(const mapping&) noexcept = default;
1462
+
1463
+ // [mdspan.layout.leftpad.obs], observers
1464
+ constexpr const extents_type& extents() const noexcept { return extents_; }
1465
+ constexpr array<index_type, rank_> strides() const noexcept;
1466
+
1467
+ constexpr index_type required_span_size() const noexcept;
1468
+ template<class... Indices>
1469
+ constexpr index_type operator()(Indices...) const noexcept;
1470
+
1471
+ static constexpr bool is_always_unique() noexcept { return true; }
1472
+ static constexpr bool is_always_exhaustive() noexcept;
1473
+ static constexpr bool is_always_strided() noexcept { return true; }
1474
+
1475
+ static constexpr bool is_unique() noexcept { return true; }
1476
+ constexpr bool is_exhaustive() const noexcept;
1477
+ static constexpr bool is_strided() noexcept { return true; }
1478
+
1479
+ constexpr index_type stride(rank_type) const noexcept;
1480
+
1481
+ template<class LayoutLeftPaddedMapping>
1482
+ friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;
1483
+
1484
+ private:
1485
+ // [mdspan.layout.leftpad.expo], exposition-only members
1486
+ index_type stride-1 = static-padding-stride; // exposition only
1487
+ extents_type extents_{}; // exposition only
1488
+ // [mdspan.sub.map], submdspan mapping specialization
1489
+ template<class... SliceSpecifiers>
1490
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1491
+ -> see below;
1492
+
1493
+ template<class... SliceSpecifiers>
1494
+ friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
1495
+ return src.submdspan-mapping-impl(slices...);
1496
+ }
1497
+ };
1498
+ }
1499
+ ```
1500
+
1501
+ If `Extents` is not a specialization of `extents`, then the program is
1502
+ ill-formed.
1503
+
1504
+ `layout_left_padded::mapping<E>` is a trivially copyable type that
1505
+ models `regular` for each `E`.
1506
+
1507
+ Throughout [[mdspan.layout.leftpad]], let `P_rank` be the following size
1508
+ *`rank_`* parameter pack of `size_`t values:
1509
+
1510
+ - the empty parameter pack, if *`rank_`* equals zero;
1511
+ - otherwise, `0zu`, if *`rank_`* equals one;
1512
+ - otherwise, the parameter pack `0zu`, `1zu`, …, `rank_- 1`.
1513
+
1514
+ *Mandates:*
1515
+
1516
+ - If `rank_dynamic() == 0` is `true`, then the size of the
1517
+ multidimensional index space `Extents()` is representable as a value
1518
+ of type `index_type`.
1519
+ - `padding_value` is representable as a value of type `index_type`.
1520
+ - If
1521
+ - *`rank_`* is greater than one,
1522
+ - `padding_value` does not equal `dynamic_extent`, and
1523
+ - *`first-static-extent`* does not equal `dynamic_extent`,
1524
+
1525
+ then `LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent)` is
1526
+ representable as a value of type `size_t`, and is representable as a
1527
+ value of type `index_type`.
1528
+ - If
1529
+ - *`rank_`* is greater than one,
1530
+ - `padding_value` does not equal `dynamic_extent`, and
1531
+ - `extents_type::static_extent(k)` does not equal `dynamic_extent` for
1532
+ all k in the range \[`0`, `extents_type::rank()`),
1533
+
1534
+ then the product of
1535
+ `LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(0))` and all
1536
+ values `ext.static_extent(k)` with k in the range of \[`1`, *`rank_`*)
1537
+ is representable as a value of type `size_t`, and is representable as
1538
+ a value of type `index_type`.
1539
+
1540
+ ###### Exposition-only members <a id="mdspan.layout.leftpad.expo">[[mdspan.layout.leftpad.expo]]</a>
1541
+
1542
+ ``` cpp
1543
+ static constexpr size_t static-padding-stride = see below;
1544
+ ```
1545
+
1546
+ The value is
1547
+
1548
+ - `0`, if *rank\_* equals zero or one;
1549
+ - otherwise, `dynamic_extent`, if `padding_value` or
1550
+ *first-static-extent* equals `dynamic_extent`;
1551
+ - otherwise, the `size_t` value which is
1552
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, `*`first-static-extent`*`)`.
1553
+
1554
+ ``` cpp
1555
+ index_type stride-1 = static-padding-stride;
1556
+ ```
1557
+
1558
+ *Recommended practice:* Implementations should not store this value if
1559
+ *static-padding-stride* is not `dynamic_extent`.
1560
+
1561
+ [*Note 9*: Using `extents<index_type, `*`static-padding-stride`*`>`
1562
+ instead of `index_type` as the type of *stride-1* would achieve
1563
+ this. — *end note*]
1564
+
1565
+ ###### Constructors <a id="mdspan.layout.leftpad.cons">[[mdspan.layout.leftpad.cons]]</a>
1566
+
1567
+ ``` cpp
1568
+ constexpr mapping(const extents_type& ext);
1569
+ ```
1570
+
1571
+ *Preconditions:*
1572
+
1573
+ - The size of the multidimensional index space `ext` is representable as
1574
+ a value of type `index_type`.
1575
+ - If *rank\_* is greater than one and `padding_value` does not equal
1576
+ `dynamic_extent`, then
1577
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))` is
1578
+ representable as a value of type *index_type*.
1579
+ - If *rank\_* is greater than one and `padding_value` does not equal
1580
+ `dynamic_extent`, then the product of
1581
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))` and all
1582
+ values `ext.extent(`k`)` with k in the range of \[`1`, *`rank_`*) is
1583
+ representable as a value of type `index_type`.
1584
+
1585
+ *Effects:*
1586
+
1587
+ - Direct-non-list-initializes *extents\_* with `ext`; and
1588
+ - if *rank\_* is greater than one, direct-non-list-initializes
1589
+ *stride-1*
1590
+ - with `ext.extent(0)` if padding_value is `dynamic_extent`,
1591
+ - otherwise with
1592
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))`.
1593
+
1594
+ ``` cpp
1595
+ template<class OtherIndexType>
1596
+ constexpr mapping(const extents_type& ext, OtherIndexType pad);
1597
+ ```
1598
+
1599
+ *Constraints:*
1600
+
1601
+ - `is_convertible_v<OtherIndexType, index_type>` is `true`.
1602
+ - `is_nothrow_constructible_v<index_type, OtherIndexType>` is `true`.
1603
+
1604
+ *Preconditions:*
1605
+
1606
+ - `pad` is representable as a value of type `index_type`.
1607
+ - `extents_type::`*`index-cast`*`(pad)` is greater than zero.
1608
+ - If *rank\_* is greater than one, then
1609
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))` is representable as
1610
+ a value of type `index_type.`
1611
+ - If *rank\_* is greater than one, then the product of
1612
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))` and all values
1613
+ `ext.extent(`k`)` with k in the range of \[`1`, *`rank_`*) is
1614
+ representable as a value of type `index_type`.
1615
+ - If `padding_value` is not equal to `dynamic_extent`, `padding_value`
1616
+ equals `extents_type::`*`index-cast`*`(pad)`.
1617
+
1618
+ *Effects:* Direct-non-list-initializes *extents\_* with `ext`, and if
1619
+ *rank\_* is greater than one, direct-non-list-initializes *stride-1*
1620
+ with *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))`.
1621
+
1622
+ ``` cpp
1623
+ template<class OtherExtents>
1624
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1625
+ mapping(const layout_left::mapping<OtherExtents>& other);
1626
+ ```
1627
+
1628
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
1629
+ `true`.
1630
+
1631
+ *Mandates:* If `OtherExtents::rank()` is greater than `1`, then
1632
+
1633
+ ``` cpp
1634
+ (static-padding-stride == dynamic_extent) ||
1635
+ (OtherExtents::static_extent(0) == dynamic_extent) ||
1636
+ (static-padding-stride == OtherExtents::static_extent(0))
1637
+ ```
1638
+
1639
+ is `true`.
1640
+
1641
+ *Preconditions:*
1642
+
1643
+ - If `extents_type::rank() > 1` is `true` and `padding_value` ==
1644
+ `dynamic_extent` is `false`, then `other.stride(1)` equals
1645
+ ``` cpp
1646
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1647
+ extents_type::index-cast(other.extents().extent(0)))
1648
+ ```
1649
+
1650
+ and
1651
+ - `other.required_span_size()` is representable as a value of type
1652
+ `index_type`.
1653
+
1654
+ *Effects:* Equivalent to `mapping(other.extents())`.
1655
+
1656
+ ``` cpp
1657
+ template<class OtherExtents>
1658
+ constexpr explicit(rank_ > 0)
1659
+ mapping(const layout_stride::mapping<OtherExtents>& other);
1660
+ ```
1661
+
1662
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
1663
+ `true`.
1664
+
1665
+ *Preconditions:*
1666
+
1667
+ - If *rank\_* is greater than `1` and `padding_value` does not equal
1668
+ `dynamic_extent`, then `other.stride(1)` equals
1669
+ ``` cpp
1670
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1671
+ extents_type::index-cast(other.extents().extent(0)))
1672
+ ```
1673
+ - If *rank\_* is greater than 0, then `other.stride(0)` equals 1.
1674
+ - If *rank\_* is greater than 2, then for all r in the range \[`2`,
1675
+ *`rank_`*), `other.stride(r)` equals
1676
+ ``` cpp
1677
+ (other.extents().fwd-prod-of-extents(r) / other.extents().extent(0)) * other.stride(1)
1678
+ ```
1679
+ - `other.required_span_size()` is representable as a value of type
1680
+ *index_type*.
1681
+
1682
+ *Effects:*
1683
+
1684
+ - Direct-non-list-initializes *extents\_* with `other.extents()` and
1685
+ - if *rank\_* is greater than one, direct-non-list-initializes
1686
+ *stride-1* with `other.stride(1)`.
1687
+
1688
+ ``` cpp
1689
+ template<class LayoutLeftPaddedMapping>
1690
+ constexpr explicit(see below)
1691
+ mapping(const LayoutLeftPaddedMapping& other);
1692
+ ```
1693
+
1694
+ *Constraints:*
1695
+
1696
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
1697
+ `true`.
1698
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
1699
+ is `true`.
1700
+
1701
+ *Mandates:* If *rank\_* is greater than 1, then
1702
+
1703
+ ``` cpp
1704
+ padding_value == dynamic_extent ||
1705
+ LayoutLeftPaddedMapping::padding_value == dynamic_extent ||
1706
+ padding_value == LayoutLeftPaddedMapping::padding_value
1707
+ ```
1708
+
1709
+ is `true`.
1710
+
1711
+ *Preconditions:*
1712
+
1713
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
1714
+ `dynamic_extent`, then `other.stride(1)` equals
1715
+ ``` cpp
1716
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
1717
+ extents_type::index-cast(other.extent(0)))
1718
+ ```
1719
+ - `other.required_span_size()` is representable as a value of type
1720
+ `index_type`.
1721
+
1722
+ *Effects:*
1723
+
1724
+ - Direct-non-list-initializes *extents\_* with `other.extents()` and
1725
+ - if *rank\_* is greater than one, direct-non-list-initializes
1726
+ *stride-1* with `other.stride(1)`.
1727
+
1728
+ *Remarks:* The expression inside `explicit` is equivalent to:
1729
+
1730
+ ``` cpp
1731
+ rank_> 1 &&
1732
+ (padding_value != dynamic_extent ||
1733
+ LayoutLeftPaddedMapping::padding_value == dynamic_extent)
1734
+ ```
1735
+
1736
+ ``` cpp
1737
+ template<class LayoutRightPaddedMapping>
1738
+ constexpr explicit(see below)
1739
+ mapping(const LayoutRightPaddedMapping& other) noexcept;
1740
+ ```
1741
+
1742
+ *Constraints:*
1743
+
1744
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
1745
+ `true` or *`is-mapping-of`*`<layout_right, LayoutRightPaddedMapping>`
1746
+ is `true`.
1747
+ - *rank\_* equals zero or one.
1748
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
1749
+ is `true`.
1750
+
1751
+ *Preconditions:* `other.required_span_size()` is representable as a
1752
+ value of type `index_type`.
1753
+
1754
+ *Effects:* Direct-non-list-initializes *extents\_* with
1755
+ `other.extents()`.
1756
+
1757
+ *Remarks:* The expression inside `explicit` is equivalent to:
1758
+
1759
+ ``` cpp
1760
+ !is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>
1761
+ ```
1762
+
1763
+ [*Note 10*: Neither the input mapping nor the mapping to be constructed
1764
+ uses the padding stride in the rank-0 or rank-1 case, so the padding
1765
+ stride does not affect either the constraints or the
1766
+ preconditions. — *end note*]
1767
+
1768
+ ###### Observers <a id="mdspan.layout.leftpad.obs">[[mdspan.layout.leftpad.obs]]</a>
1769
+
1770
+ ``` cpp
1771
+ constexpr array<index_type, rank_> strides() const noexcept;
1772
+ ```
1773
+
1774
+ *Returns:* `array<index_type, `*`rank_`*`>({stride(P_rank)...})`.
1775
+
1776
+ ``` cpp
1777
+ constexpr index_type required_span_size() const noexcept;
1778
+ ```
1779
+
1780
+ *Returns:*
1781
+
1782
+ - `0` if the multidimensional index space *extents\_* is empty,
1783
+ - otherwise,
1784
+ `(*this)(`*`extents_`*`.extent(P_rank) - index_type(1)...) + 1`.
1785
+
1786
+ ``` cpp
1787
+ template<class... Indices>
1788
+ constexpr size_t operator()(Indices... idxs) const noexcept;
1789
+ ```
1790
+
1791
+ *Constraints:*
1792
+
1793
+ - `sizeof...(Indices) == `*`rank_`* is `true`.
1794
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`.
1795
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
1796
+
1797
+ *Preconditions:* `extents_type::`*`index-cast`*`(idxs)` is a
1798
+ multidimensional index in `extents()` [[mdspan.overview]].
1799
+
1800
+ *Returns:*
1801
+ `((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)`.
1802
+
1803
+ ``` cpp
1804
+ static constexpr bool is_always_exhaustive() noexcept;
1805
+ ```
1806
+
1807
+ *Returns:*
1808
+
1809
+ - If *rank\_* equals zero or one, then `true`;
1810
+ - otherwise, if neither *static-padding-stride* nor
1811
+ *first-static-extent* equal `dynamic_extent`, then
1812
+ *`static-padding-stride`*` == `*`first-static-extent`*;
1813
+ - otherwise, `false`.
1814
+
1815
+ ``` cpp
1816
+ constexpr bool is_exhaustive() const noexcept;
1817
+ ```
1818
+
1819
+ *Returns:* `true` if *rank\_* equals zero or one; otherwise,
1820
+ `extents_.extent(0) == stride(1)`.
1821
+
1822
+ ``` cpp
1823
+ constexpr index_type stride(rank_type r) const noexcept;
1824
+ ```
1825
+
1826
+ *Preconditions:* `r` is smaller than *rank\_*.
1827
+
1828
+ *Returns:*
1829
+
1830
+ - If `r` equals zero: 1;
1831
+ - otherwise, if `r` equals one: *stride-1*;
1832
+ - otherwise, the product of *stride-1* and all values
1833
+ `extents_.extent(`k`)` with k in the range \[`1`, `r`).
1834
+
1835
+ ``` cpp
1836
+ template<class LayoutLeftPaddedMapping>
1837
+ friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
1838
+ ```
1839
+
1840
+ *Constraints:*
1841
+
1842
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
1843
+ `true`.
1844
+ - `LayoutLeftPaddedMapping::extents_type::rank() == rank_` is `true`.
1845
+
1846
+ *Returns:* `true` if `x.extents() == y.extents()` is `true` and
1847
+ *`rank_`*` < 2 || x.stride(1) == y. stride(1)` is `true`. Otherwise,
1848
+ `false`.
1849
+
1850
+ ##### Class template `layout_right_padded::mapping` <a id="mdspan.layout.rightpad">[[mdspan.layout.rightpad]]</a>
1851
+
1852
+ ###### Overview <a id="mdspan.layout.rightpad.overview">[[mdspan.layout.rightpad.overview]]</a>
1853
+
1854
+ `layout_right_padded` provides a layout mapping that behaves like
1855
+ `layout_right::mapping`, except that the padding stride
1856
+ `stride(extents_type::rank() - 2)` can be greater than or equal to
1857
+ `extents_type::extent(extents_type::rank() - 1)`.
1858
+
1859
+ ``` cpp
1860
+ namespace std {
1861
+ template<size_t PaddingValue>
1862
+ template<class Extents>
1863
+ class layout_right_padded<PaddingValue>::mapping {
1864
+ public:
1865
+ static constexpr size_t padding_value = PaddingValue;
1866
+
1867
+ using extents_type = Extents;
1868
+ using index_type = extents_type::index_type;
1869
+ using size_type = extents_type::size_type;
1870
+ using rank_type = extents_type::rank_type;
1871
+ using layout_type = layout_right_padded<PaddingValue>;
1872
+
1873
+ private:
1874
+ static constexpr size_t rank_ = extents_type::rank(); // exposition only
1875
+ static constexpr size_t last-static-extent = // exposition only
1876
+ extents_type::static_extent(rank_ - 1);
1877
+
1878
+ // [mdspan.layout.rightpad.expo], exposition-only members
1879
+ static constexpr size_t static-padding-stride = see below; // exposition only
1880
+
1881
+ public:
1882
+ // [mdspan.layout.rightpad.cons], constructors
1883
+ constexpr mapping() noexcept : mapping(extents_type{}) {}
1884
+ constexpr mapping(const mapping&) noexcept = default;
1885
+ constexpr mapping(const extents_type&);
1886
+ template<class OtherIndexType>
1887
+ constexpr mapping(const extents_type&, OtherIndexType);
1888
+
1889
+ template<class OtherExtents>
1890
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1891
+ mapping(const layout_right::mapping<OtherExtents>&);
1892
+ template<class OtherExtents>
1893
+ constexpr explicit(rank_ > 0)
1894
+ mapping(const layout_stride::mapping<OtherExtents>&);
1895
+ template<class LayoutRightPaddedMapping>
1896
+ constexpr explicit(see below)
1897
+ mapping(const LayoutRightPaddedMapping&);
1898
+ template<class LayoutLeftPaddedMapping>
1899
+ constexpr explicit(see below)
1900
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
1901
+
1902
+ constexpr mapping& operator=(const mapping&) noexcept = default;
1903
+
1904
+ // [mdspan.layout.rightpad.obs], observers
1905
+ constexpr const extents_type& extents() const noexcept { return extents_; }
1906
+ constexpr array<index_type, rank_> strides() const noexcept;
1907
+
1908
+ constexpr index_type required_span_size() const noexcept;
1909
+
1910
+ template<class... Indices>
1911
+ constexpr index_type operator()(Indices...) const noexcept;
1912
+
1913
+ static constexpr bool is_always_unique() noexcept { return true; }
1914
+ static constexpr bool is_always_exhaustive() noexcept;
1915
+ static constexpr bool is_always_strided() noexcept { return true; }
1916
+
1917
+ static constexpr bool is_unique() noexcept { return true; }
1918
+ constexpr bool is_exhaustive() const noexcept;
1919
+ static constexpr bool is_strided() noexcept { return true; }
1920
+
1921
+ constexpr index_type stride(rank_type) const noexcept;
1922
+
1923
+ template<class LayoutRightPaddedMapping>
1924
+ friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;
1925
+
1926
+ private:
1927
+ // [mdspan.layout.rightpad.expo], exposition-only members
1928
+ index_type stride-rm2 = static-padding-stride; // exposition only
1929
+ extents_type extents_{}; // exposition only
1930
+
1931
+ // [mdspan.sub.map], submdspan mapping specialization
1932
+ template<class... SliceSpecifiers>
1933
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1934
+ -> see below;
1935
+
1936
+ template<class... SliceSpecifiers>
1937
+ friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
1938
+ return src.submdspan-mapping-impl(slices...);
1939
+ }
1940
+ };
1941
+ }
1942
+ ```
1943
+
1944
+ If `Extents` is not a specialization of `extents`, then the program is
1945
+ ill-formed.
1946
+
1947
+ `layout_right_padded::mapping<E>` is a trivially copyable type that
1948
+ models `regular` for each `E`.
1949
+
1950
+ Throughout [[mdspan.layout.rightpad]], let `P_rank` be the following
1951
+ size *`rank_`* parameter pack of `size_`t values:
1952
+
1953
+ - the empty parameter pack, if *`rank_`* equals zero;
1954
+ - otherwise, `0zu`, if *`rank_`* equals one;
1955
+ - otherwise, the parameter pack `0zu`, `1zu`, …, `rank_- 1`.
1956
+
1957
+ *Mandates:*
1958
+
1959
+ - If `rank_dynamic() == 0` is `true`, then the size of the
1960
+ multidimensional index space `Extents()` is representable as a value
1961
+ of type `index_type`.
1962
+ - `padding_value` is representable as a value of type `index_type`.
1963
+ - If
1964
+ - *`rank_`* is greater than one,
1965
+ - `padding_value` does not equal `dynamic_extent`, and
1966
+ - *`last-static-extent`* does not equal `dynamic_extent`,
1967
+
1968
+ then `LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent)` is
1969
+ representable as a value of type `size_t`, and is representable as a
1970
+ value of type `index_type`.
1971
+ - If
1972
+ - *`rank_`* is greater than one,
1973
+ - `padding_value` does not equal `dynamic_extent`, and
1974
+ - `extents_type::static_extent(k)` does not equal `dynamic_extent` for
1975
+ all k in the range \[`0`, *`rank_`*),
1976
+
1977
+ then the product of
1978
+ `LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(rank_ - 1))`
1979
+ and all values `ext.static_extent(k)` with k in the range of \[`0`,
1980
+ *`rank_`*` - 1`) is representable as a value of type `size_t`, and is
1981
+ representable as a value of type `index_type`.
1982
+
1983
+ ###### Exposition-only members <a id="mdspan.layout.rightpad.expo">[[mdspan.layout.rightpad.expo]]</a>
1984
+
1985
+ ``` cpp
1986
+ static constexpr size_t static-padding-stride = see below;
1987
+ ```
1988
+
1989
+ The value is
1990
+
1991
+ - `0`, if *rank\_* equals zero or one;
1992
+ - otherwise, `dynamic_extent`, if `padding_value` or
1993
+ *last-static-extent* equals `dynamic_extent`;
1994
+ - otherwise, the `size_t` value which is
1995
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, `*`last-static-extent`*`)`.
1996
+
1997
+ ``` cpp
1998
+ index_type stride-rm2 = static-padding-stride;
1999
+ ```
2000
+
2001
+ *Recommended practice:* Implementations should not store this value if
2002
+ *static-padding-stride* is not `dynamic_extent`.
2003
+
2004
+ [*Note 11*: Using `extents<index_type, `*`static-padding-stride`*`>`
2005
+ instead of `index_type` as the type of *stride-rm2* would achieve
2006
+ this. — *end note*]
2007
+
2008
+ ###### Constructors <a id="mdspan.layout.rightpad.cons">[[mdspan.layout.rightpad.cons]]</a>
2009
+
2010
+ ``` cpp
2011
+ constexpr mapping(const extents_type& ext);
2012
+ ```
2013
+
2014
+ *Preconditions:*
2015
+
2016
+ - The size of the multidimensional index space `ext` is representable as
2017
+ a value of type `index_type`.
2018
+ - If *rank\_* is greater than one and `padding_value` does not equal
2019
+ `dynamic_extent`, then
2020
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`
2021
+ is representable as a value of type *index_type*.
2022
+ - If *rank\_* is greater than one and `padding_value` does not equal
2023
+ `dynamic_extent`, then the product of
2024
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`
2025
+ and all values `ext.extent(`k`)` with k in the range of \[`0`,
2026
+ *`rank_`*` - 1`) is representable as a value of type `index_type`.
2027
+
2028
+ *Effects:*
2029
+
2030
+ - Direct-non-list-initializes *extents\_* with `ext`; and
2031
+ - if *rank\_* is greater than one, direct-non-list-initializes
2032
+ *stride-rm2*
2033
+ - with `ext.extent(`*`rank_`*` - 1)` if `padding_value` is
2034
+ `dynamic_extent`,
2035
+ - otherwise with
2036
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`.
2037
+
2038
+ ``` cpp
2039
+ template<class OtherIndexType>
2040
+ constexpr mapping(const extents_type& ext, OtherIndexType pad);
2041
+ ```
2042
+
2043
+ *Constraints:*
2044
+
2045
+ - `is_convertible_v<OtherIndexType, index_type>` is `true`.
2046
+ - `is_nothrow_constructible_v<index_type, OtherIndexType>` is `true`.
2047
+
2048
+ *Preconditions:*
2049
+
2050
+ - `pad` is representable as a value of type `index_type`.
2051
+ - `extents_type::`*`index-cast`*`(pad)` is greater than zero.
2052
+ - If *rank\_* is greater than one, then
2053
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))` is
2054
+ representable as a value of type `index_type`.
2055
+ - If *rank\_* is greater than one, then the product of
2056
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))` and
2057
+ all values `ext.extent(`k`)` with k in the range of \[`0`,
2058
+ *`rank_`*` - 1`) is representable as a value of type `index_type`.
2059
+ - If `padding_value` is not equal to `dynamic_extent`, `padding_value`
2060
+ equals `extents_type::`*`index-cast`*`(pad)`.
2061
+
2062
+ *Effects:* Direct-non-list-initializes *extents\_* with `ext`, and if
2063
+ *rank\_* is greater than one, direct-non-list-initializes *stride-rm2*
2064
+ with *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))`.
2065
+
2066
+ ``` cpp
2067
+ template<class OtherExtents>
2068
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
2069
+ mapping(const layout_right::mapping<OtherExtents>& other);
2070
+ ```
2071
+
2072
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
2073
+ `true`.
2074
+
2075
+ *Mandates:* If `OtherExtents::rank()` is greater than 1, then
2076
+
2077
+ ``` cpp
2078
+ (static-padding-stride == dynamic_extent) ||
2079
+ (OtherExtents::static_extent(rank_ - 1) == dynamic_extent) ||
2080
+ (static-padding-stride == OtherExtents::static_extent(rank_ - 1))
2081
+ ```
2082
+
2083
+ is `true`.
2084
+
2085
+ *Preconditions:*
2086
+
2087
+ - If *`rank_`*` > 1` is `true` and `padding_value == dynamic_extent` is
2088
+ `false`, then `other.stride( `*`rank_`*` - 2)` equals
2089
+ ``` cpp
2090
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2091
+ extents_type::index-cast(other.extents().extent(rank_ - 1)))
2092
+ ```
2093
+
2094
+ and
2095
+ - `other.required_span_size()` is representable as a value of type
2096
+ `index_type`.
2097
+
2098
+ *Effects:* Equivalent to `mapping(other.extents())`.
2099
+
2100
+ ``` cpp
2101
+ template<class OtherExtents>
2102
+ constexpr explicit(rank_ > 0)
2103
+ mapping(const layout_stride::mapping<OtherExtents>& other);
2104
+ ```
2105
+
2106
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
2107
+ `true`.
2108
+
2109
+ *Preconditions:*
2110
+
2111
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
2112
+ `dynamic_extent`, then `other.stride(`*`rank_`*` - 2)` equals
2113
+ ``` cpp
2114
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2115
+ extents_type::index-cast(other.extents().extent(rank_ - 1)))
2116
+ ```
2117
+ - If *rank\_* is greater than 0, then other.stride(*rank\_* - 1) equals
2118
+ 1.
2119
+ - If *rank\_* is greater than 2, then for all r in the range \[`0`,
2120
+ *`rank_`*` - 2`), `other.stride(`r`)` equals
2121
+ ``` cpp
2122
+ (other.extents().rev-prod-of-extents(r) / other.extents().extent(rank_ - 1)) *
2123
+ other.stride(rank_ - 2)
2124
+ ```
2125
+ - `other.required_span_size()` is representable as a value of type
2126
+ `index_type`.
2127
+
2128
+ *Effects:*
2129
+
2130
+ - Direct-non-list-initializes *extents\_* with `other.extents()`; and
2131
+ - if *rank\_* is greater than one, direct-non-list-initializes
2132
+ *stride-rm2* with `other.stride(`*`rank_`*` - 2)`.
2133
+
2134
+ ``` cpp
2135
+ template<class LayoutRightPaddedMapping>
2136
+ constexpr explicit(see below)
2137
+ mapping(const LayoutRightPaddedMapping& other);
2138
+ ```
2139
+
2140
+ *Constraints:*
2141
+
2142
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
2143
+ `true`.
2144
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
2145
+ is `true`.
2146
+
2147
+ *Mandates:* If *rank\_* is greater than 1, then
2148
+
2149
+ ``` cpp
2150
+ padding_value == dynamic_extent ||
2151
+ LayoutRightPaddedMapping::padding_value == dynamic_extent ||
2152
+ padding_value == LayoutRightPaddedMapping::padding_value
2153
+ ```
2154
+
2155
+ is `true`.
2156
+
2157
+ *Preconditions:*
2158
+
2159
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
2160
+ `dynamic_extent`, then `other.stride(`*`rank_`*` - 2)` equals
2161
+ ``` cpp
2162
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2163
+ extents_type::index-cast(other.extent(rank_ - 1)))
2164
+ ```
2165
+ - `other.required_span_size()` is representable as a value of type
2166
+ `index_type`.
2167
+
2168
+ *Effects:*
2169
+
2170
+ - Direct-non-list-initializes *extents\_* with `other.extents()`; and
2171
+ - if *rank\_* is greater than one, direct-non-list-initializes
2172
+ *stride-rm2* with `other.stride(rank_ - 2)`.
2173
+
2174
+ *Remarks:* The expression inside `explicit` is equivalent to:
2175
+
2176
+ ``` cpp
2177
+ rank_ > 1 &&
2178
+ (padding_value != dynamic_extent ||
2179
+ LayoutRightPaddedMapping::padding_value == dynamic_extent)
2180
+ ```
2181
+
2182
+ ``` cpp
2183
+ template<class LayoutLeftPaddedMapping>
2184
+ constexpr explicit(see below)
2185
+ mapping(const LayoutLeftPaddedMapping& other) noexcept;
2186
+ ```
2187
+
2188
+ *Constraints:*
2189
+
2190
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
2191
+ `true` or *`is-mapping-of`*`<layout_left, LayoutLeftPaddedMapping>` is
2192
+ `true`.
2193
+ - *rank\_* equals zero or one.
2194
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
2195
+ is `true`.
2196
+
2197
+ *Preconditions:* `other.required_span_size()` is representable as a
2198
+ value of type `index_type`.
2199
+
2200
+ *Effects:* Direct-non-list-initializes *extents\_* with
2201
+ `other.extents()`.
2202
+
2203
+ *Remarks:* The expression inside `explicit` is equivalent to:
2204
+
2205
+ ``` cpp
2206
+ !is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>
2207
+ ```
2208
+
2209
+ [*Note 12*: Neither the input mapping nor the mapping to be constructed
2210
+ uses the padding stride in the rank-0 or rank-1 case, so the padding
2211
+ stride affects neither the constraints nor the
2212
+ preconditions. — *end note*]
2213
+
2214
+ ###### Observers <a id="mdspan.layout.rightpad.obs">[[mdspan.layout.rightpad.obs]]</a>
2215
+
2216
+ ``` cpp
2217
+ constexpr array<index_type, rank_> strides() const noexcept;
2218
+ ```
2219
+
2220
+ *Returns:* `array<index_type, `*`rank_`*`>(``stride(P_rank)...``)`.
2221
+
2222
+ ``` cpp
2223
+ constexpr index_type required_span_size() const noexcept;
2224
+ ```
2225
+
2226
+ *Returns:* `0` if the multidimensional index space *extents\_* is empty,
2227
+ otherwise
2228
+ `(*this)(`*`extents_`*`.extent(P_rank) - index_type(1)...) + 1`.
2229
+
2230
+ ``` cpp
2231
+ template<class... Indices>
2232
+ constexpr size_t operator()(Indices... idxs) const noexcept;
2233
+ ```
2234
+
2235
+ *Constraints:*
2236
+
2237
+ - `sizeof...(Indices) == `*`rank_`* is `true`.
2238
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`.
2239
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
2240
+
2241
+ *Preconditions:* `extents_type::`*`index-cast`*`(idxs)` is a
2242
+ multidimensional index in `extents()` [[mdspan.overview]].
2243
+
2244
+ *Returns:*
2245
+ `((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)`.
2246
+
2247
+ ``` cpp
2248
+ static constexpr bool is_always_exhaustive() noexcept;
2249
+ ```
2250
+
2251
+ *Returns:*
2252
+
2253
+ - If *rank\_* equals zero or one, then `true`;
2254
+ - otherwise, if neither *static-padding-stride* nor *last-static-extent*
2255
+ equal `dynamic_extent`, then
2256
+ *`static-padding-stride`*` == `*`last-static-extent`*;
2257
+ - otherwise, `false`.
2258
+
2259
+ ``` cpp
2260
+ constexpr bool is_exhaustive() const noexcept;
2261
+ ```
2262
+
2263
+ *Returns:* `true` if *rank\_* equals zero or one; otherwise,
2264
+
2265
+ ``` cpp
2266
+ extents_.extent(rank_ - 1) == stride(rank_ - 2)
2267
+ ```
2268
+
2269
+ ``` cpp
2270
+ constexpr index_type stride(rank_type r) const noexcept;
2271
+ ```
2272
+
2273
+ *Preconditions:* `r` is smaller than *rank\_*.
2274
+
2275
+ *Returns:*
2276
+
2277
+ - If `r` equals *`rank_`*` - 1`: `1`;
2278
+ - otherwise, if `r` equals *`rank_`*` - 2`: *stride-rm2*;
2279
+ - otherwise, the product of *stride-rm2* and all values
2280
+ `extents_.extent(`k`)` with k in the range of \[`r + 1`,
2281
+ *`rank_`*` - 1`).
2282
+
2283
+ ``` cpp
2284
+ template<class LayoutRightPaddedMapping>
2285
+ friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;
2286
+ ```
2287
+
2288
+ *Constraints:*
2289
+
2290
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
2291
+ `true`.
2292
+ - `LayoutRightPaddedMapping::extents_type::rank() == `*`rank_`* is
2293
+ `true`.
2294
+
2295
+ *Returns:* `true` if `x.extents() == y.extents()` is `true` and
2296
+ *`rank_`*` < 2 || x.stride(`*`rank_`*` - 2) == y.stride(`*`rank_`*` - 2)`
2297
+ is `true`. Otherwise, `false`.
2298
+
2299
  #### Accessor policy <a id="mdspan.accessor">[[mdspan.accessor]]</a>
2300
 
2301
  ##### General <a id="mdspan.accessor.general">[[mdspan.accessor.general]]</a>
2302
 
2303
  An *accessor policy* defines types and operations by which a reference
 
2306
 
2307
  A range of indices [0, N) is an *accessible range* of a given data
2308
  handle and an accessor if, for each i in the range, the accessor
2309
  policy’s `access` function produces a valid reference to an object.
2310
 
2311
+ In [[mdspan.accessor.reqmts]],
2312
 
2313
  - `A` denotes an accessor policy.
2314
  - `a` denotes a value of type `A` or `const A`.
2315
  - `p` denotes a value of type `A::data_handle_type` or
2316
  `const A::data_handle_type`. \[*Note 1*: The type
 
2450
  constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
2451
  ```
2452
 
2453
  *Effects:* Equivalent to: `return p + i;`
2454
 
2455
+ ##### Class template `aligned_accessor` <a id="mdspan.accessor.aligned">[[mdspan.accessor.aligned]]</a>
2456
+
2457
+ ###### Overview <a id="mdspan.accessor.aligned.overview">[[mdspan.accessor.aligned.overview]]</a>
2458
+
2459
+ ``` cpp
2460
+ namespace std {
2461
+ template<class ElementType, size_t ByteAlignment>
2462
+ struct aligned_accessor {
2463
+ using offset_policy = default_accessor<ElementType>;
2464
+ using element_type = ElementType;
2465
+ using reference = ElementType&;
2466
+ using data_handle_type = ElementType*;
2467
+
2468
+ static constexpr size_t byte_alignment = ByteAlignment;
2469
+
2470
+ constexpr aligned_accessor() noexcept = default;
2471
+ template<class OtherElementType, size_t OtherByteAlignment>
2472
+ constexpr aligned_accessor(
2473
+ aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
2474
+ template<class OtherElementType>
2475
+ constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
2476
+
2477
+ template<class OtherElementType>
2478
+ constexpr operator default_accessor<OtherElementType>() const noexcept;
2479
+
2480
+ constexpr reference access(data_handle_type p, size_t i) const noexcept;
2481
+
2482
+ constexpr typename offset_policy::data_handle_type offset(
2483
+ data_handle_type p, size_t i) const noexcept;
2484
+ };
2485
+ }
2486
+ ```
2487
+
2488
+ *Mandates:*
2489
+
2490
+ - `byte_alignment` is a power of two, and
2491
+ - `byte_alignment >= alignof(ElementType)` is `true`.
2492
+
2493
+ `aligned_accessor` meets the accessor policy requirements.
2494
+
2495
+ `ElementType` is required to be a complete object type that is neither
2496
+ an abstract class type nor an array type.
2497
+
2498
+ Each specialization of `aligned_accessor` is a trivially copyable type
2499
+ that models `semiregular`.
2500
+
2501
+ \[`0`, n) is an accessible range for an object `p` of type
2502
+ `data_handle_type` and an object of type `aligned_accessor` if and only
2503
+ if
2504
+
2505
+ - \[`p`, `p + `n) is a valid range, and,
2506
+ - if n is greater than zero, then
2507
+ `is_sufficiently_aligned<byte_alignment>(p)` is `true`.
2508
+
2509
+ [*Example 1*:
2510
+
2511
+ The following function `compute` uses `is_sufficiently_aligned` to check
2512
+ whether a given `mdspan` with `default_accessor` has a data handle with
2513
+ sufficient alignment to be used with
2514
+ `aligned_accessor<float, 4 * sizeof(float)>`. If so, the function
2515
+ dispatches to a function `compute_using_fourfold_overalignment` that
2516
+ requires fourfold over-alignment of arrays, but can therefore use
2517
+ hardware-specific instructions, such as four-wide SIMD (Single
2518
+ Instruction Multiple Data) instructions. Otherwise, `compute` dispatches
2519
+ to a possibly less optimized function
2520
+ `compute_without_requiring_overalignment` that has no over-alignment
2521
+ requirement.
2522
+
2523
+ ``` cpp
2524
+ void compute_using_fourfold_overalignment(
2525
+ mdspan<float, dims<1>, layout_right, aligned_accessor<float, 4 * alignof(float)>> x);
2526
+
2527
+ void compute_without_requiring_overalignment(
2528
+ mdspan<float, dims<1>, layout_right> x);
2529
+
2530
+ void compute(mdspan<float, dims<1>> x) {
2531
+ constexpr auto byte_alignment = 4 * sizeof(float);
2532
+ auto accessor = aligned_accessor<float, byte_alignment>{};
2533
+ auto x_handle = x.data_handle();
2534
+
2535
+ if (is_sufficiently_aligned<byte_alignment>(x_handle)) {
2536
+ compute_using_fourfold_overalignment(mdspan{x_handle, x.mapping(), accessor});
2537
+ } else {
2538
+ compute_without_requiring_overalignment(x);
2539
+ }
2540
+ }
2541
+ ```
2542
+
2543
+ — *end example*]
2544
+
2545
+ ###### Members <a id="mdspan.accessor.aligned.members">[[mdspan.accessor.aligned.members]]</a>
2546
+
2547
+ ``` cpp
2548
+ template<class OtherElementType, size_t OtherByteAlignment>
2549
+ constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
2550
+ ```
2551
+
2552
+ *Constraints:*
2553
+
2554
+ - `is_convertible_v<OtherElementType(*)[], element_type(*)[]>` is
2555
+ `true`.
2556
+ - `OtherByteAlignment >= byte_alignment` is `true`.
2557
+
2558
+ *Effects:* None.
2559
+
2560
+ ``` cpp
2561
+ template<class OtherElementType>
2562
+ constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
2563
+ ```
2564
+
2565
+ *Constraints:*
2566
+ `is_convertible_v<OtherElementType(*)[], element_type(*)[]>` is `true`.
2567
+
2568
+ *Effects:* None.
2569
+
2570
+ ``` cpp
2571
+ constexpr reference access(data_handle_type p, size_t i) const noexcept;
2572
+ ```
2573
+
2574
+ *Preconditions:* \[`0`, `i + 1`) is an accessible range for `p` and
2575
+ `*this`.
2576
+
2577
+ *Effects:* Equivalent to: `return assume_aligned<byte_alignment>(p)[i];`
2578
+
2579
+ ``` cpp
2580
+ template<class OtherElementType>
2581
+ constexpr operator default_accessor<OtherElementType>() const noexcept;
2582
+ ```
2583
+
2584
+ *Constraints:*
2585
+ `is_convertible_v<element_type(*)[], OtherElementType(*)[]>` is `true`.
2586
+
2587
+ *Effects:* Equivalent to: `return {};`
2588
+
2589
+ ``` cpp
2590
+ constexpr typename offset_policy::data_handle_type
2591
+ offset(data_handle_type p, size_t i) const noexcept;
2592
+ ```
2593
+
2594
+ *Preconditions:* \[`0`, `i + 1`) is an accessible range for `p` and
2595
+ `*this`.
2596
+
2597
+ *Effects:* Equivalent to:
2598
+ `return assume_aligned<byte_alignment>(p) + i;`
2599
+
2600
  #### Class template `mdspan` <a id="mdspan.mdspan">[[mdspan.mdspan]]</a>
2601
 
2602
  ##### Overview <a id="mdspan.mdspan.overview">[[mdspan.mdspan.overview]]</a>
2603
 
2604
  `mdspan` is a view of a multidimensional array of elements.
 
2610
  class mdspan {
2611
  public:
2612
  using extents_type = Extents;
2613
  using layout_type = LayoutPolicy;
2614
  using accessor_type = AccessorPolicy;
2615
+ using mapping_type = layout_type::template mapping<extents_type>;
2616
  using element_type = ElementType;
2617
  using value_type = remove_cv_t<element_type>;
2618
+ using index_type = extents_type::index_type;
2619
+ using size_type = extents_type::size_type;
2620
+ using rank_type = extents_type::rank_type;
2621
+ using data_handle_type = accessor_type::data_handle_type;
2622
+ using reference = accessor_type::reference;
2623
 
2624
  static constexpr rank_type rank() noexcept { return extents_type::rank(); }
2625
  static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
2626
  static constexpr size_t static_extent(rank_type r) noexcept
2627
  { return extents_type::static_extent(r); }
 
2659
  template<class OtherIndexType>
2660
  constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
2661
  template<class OtherIndexType>
2662
  constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
2663
 
2664
+ template<class... OtherIndexTypes>
2665
+ constexpr reference
2666
+ at(OtherIndexTypes... indices) const; // freestanding-deleted
2667
+ template<class OtherIndexType>
2668
+ constexpr reference
2669
+ at(span<OtherIndexType, rank()> indices) const; // freestanding-deleted
2670
+ template<class OtherIndexType>
2671
+ constexpr reference
2672
+ at(const array<OtherIndexType, rank()>& indices) const; // freestanding-deleted
2673
+
2674
  constexpr size_type size() const noexcept;
2675
+ constexpr bool empty() const noexcept;
2676
 
2677
  friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
2678
 
2679
  constexpr const extents_type& extents() const noexcept { return map_.extents(); }
2680
  constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
 
2714
  -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
2715
 
2716
  template<class ElementType, class... Integrals>
2717
  requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
2718
  explicit mdspan(ElementType*, Integrals...)
2719
+ -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;
2720
 
2721
  template<class ElementType, class OtherIndexType, size_t N>
2722
  mdspan(ElementType*, span<OtherIndexType, N>)
2723
  -> mdspan<ElementType, dextents<size_t, N>>;
2724
 
 
2821
  ```
2822
 
2823
  *Constraints:*
2824
 
2825
  - `is_convertible_v<const OtherIndexType&, index_type>` is `true`,
2826
+ - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
2827
+ `true`,
2828
  - `N == rank() || N == rank_dynamic()` is `true`,
2829
  - `is_constructible_v<mapping_type, extents_type>` is `true`, and
2830
  - `is_default_constructible_v<accessor_type>` is `true`.
2831
 
2832
  *Preconditions:* $[0, \texttt{\textit{map_}.required_span_size()})$ is
 
2905
 
2906
  - `is_constructible_v<data_handle_type, const OtherAccessor::data_handle_type&>`
2907
  is `true`, and
2908
  - `is_constructible_v<extents_type, OtherExtents>` is `true`.
2909
 
2910
+ *Preconditions:* $[0, \texttt{\textit{map_}.required_span_size()})$ is
2911
+ an accessible range of *ptr\_* and *acc\_* for values of *ptr\_*,
2912
+ *map\_*, and *acc\_* after the invocation of this constructor.
2913
 
2914
+ For each rank index `r` of `extents_type`,
2915
  `static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)`
2916
  is `true`.
 
 
 
2917
 
2918
  *Effects:*
2919
 
2920
  - Direct-non-list-initializes *ptr\_* with `other.`*`ptr_`*,
2921
  - direct-non-list-initializes *map\_* with `other.`*`map_`*, and
 
2942
  `true`, and
2943
  - `sizeof...(OtherIndexTypes) == rank()` is `true`.
2944
 
2945
  Let `I` be `extents_type::`*`index-cast`*`(std::move(indices))`.
2946
 
2947
+ `I` is a multidimensional index in `extents()`.
2948
 
2949
  [*Note 1*: This implies that
2950
  *`map_`*`(I) < `*`map_`*`.required_span_size()` is
2951
  `true`. — *end note*]
2952
 
 
2976
  ```
2977
 
2978
  is `true`. Equivalent to:
2979
 
2980
  ``` cpp
2981
+ return operator[](extents_type::index-cast(as_const(indices[P]))...);
2982
+ ```
2983
+
2984
+ ``` cpp
2985
+ template<class... OtherIndexTypes>
2986
+ constexpr reference at(OtherIndexTypes... indices) const;
2987
+ ```
2988
+
2989
+ *Constraints:*
2990
+
2991
+ - `(is_convertible_v<OtherIndexTypes, index_type> && ...)` is `true`,
2992
+ - `(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...)` is
2993
+ `true`, and
2994
+ - `sizeof...(OtherIndexTypes) == rank()` is `true`.
2995
+
2996
+ Let `I` be `extents_type::`*`index-cast`*`(std::move(indices))`.
2997
+
2998
+ *Returns:* `(*this)[I...]`.
2999
+
3000
+ *Throws:* `out_of_range` if `I` is not a multidimensional index in
3001
+ `extents()`.
3002
+
3003
+ ``` cpp
3004
+ template<class OtherIndexType>
3005
+ constexpr reference at(span<OtherIndexType, rank()> indices) const;
3006
+ template<class OtherIndexType>
3007
+ constexpr reference at(const array<OtherIndexType, rank()>& indices) const;
3008
+ ```
3009
+
3010
+ *Constraints:*
3011
+
3012
+ - `is_convertible_v<const OtherIndexType&, index_type>` is `true`, and
3013
+ - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
3014
+ `true`.
3015
+
3016
+ *Effects:* Let `P` be a parameter pack such that
3017
+
3018
+ ``` cpp
3019
+ is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
3020
+ ```
3021
+
3022
+ is `true`. Equivalent to:
3023
+
3024
+ ``` cpp
3025
+ return at(extents_type::index-cast(as_const(indices[P]))...);
3026
  ```
3027
 
3028
  ``` cpp
3029
  constexpr size_type size() const noexcept;
3030
  ```
 
3034
  [[basic.fundamental]].
3035
 
3036
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(rank())`.
3037
 
3038
  ``` cpp
3039
+ constexpr bool empty() const noexcept;
3040
  ```
3041
 
3042
  *Returns:* `true` if the size of the multidimensional index space
3043
  `extents()` is 0, otherwise `false`.
3044
 
 
3052
  swap(x.ptr_, y.ptr_);
3053
  swap(x.map_, y.map_);
3054
  swap(x.acc_, y.acc_);
3055
  ```
3056
 
3057
+ #### `submdspan` <a id="mdspan.sub">[[mdspan.sub]]</a>
3058
+
3059
+ ##### Overview <a id="mdspan.sub.overview">[[mdspan.sub.overview]]</a>
3060
+
3061
+ The `submdspan` facilities create a new `mdspan` viewing a subset of
3062
+ elements of an existing input `mdspan`. The subset viewed by the created
3063
+ `mdspan` is determined by the `SliceSpecifier` arguments.
3064
+
3065
+ For each function defined in [[mdspan.sub]] that takes a parameter pack
3066
+ named `slices` as an argument:
3067
+
3068
+ - let `index_type` be
3069
+ - `M::index_type` if the function is a member of a class `M`,
3070
+ - otherwise, `remove_reference_t<decltype(src)>::index_type` if the
3071
+ function has a parameter named `src`,
3072
+ - otherwise, the same type as the function’s template argument
3073
+ `IndexType`;
3074
+ - let `rank` be the number of elements in `slices`;
3075
+ - let sₖ be the kᵗʰ element of `slices`;
3076
+ - let Sₖ be the type of sₖ; and
3077
+ - let `map-rank` be an `array<size_t, rank>` such that for each k in the
3078
+ range \[`0`, `rank`), `map-rank[k]` equals:
3079
+ - `dynamic_extent` if Sₖ models `convertible_to<index_type>`,
3080
+ - otherwise, the number of types Sⱼ with j < k that do not model
3081
+ `convertible_to<index_type>`.
3082
+
3083
+ ##### `strided_slice` <a id="mdspan.sub.strided.slice">[[mdspan.sub.strided.slice]]</a>
3084
+
3085
+ `strided_slice` represents a set of `extent` regularly spaced integer
3086
+ indices. The indices start at `offset`, and increase by increments of
3087
+ `stride`.
3088
+
3089
+ ``` cpp
3090
+ namespace std {
3091
+ template<class OffsetType, class ExtentType, class StrideType>
3092
+ struct strided_slice {
3093
+ using offset_type = OffsetType;
3094
+ using extent_type = ExtentType;
3095
+ using stride_type = StrideType;
3096
+
3097
+ [[no_unique_address]] offset_type offset{};
3098
+ [[no_unique_address]] extent_type extent{};
3099
+ [[no_unique_address]] stride_type stride{};
3100
+ };
3101
+ }
3102
+ ```
3103
+
3104
+ `strided_slice` has the data members and special members specified
3105
+ above. It has no base classes or members other than those specified.
3106
+
3107
+ *Mandates:* `OffsetType`, `ExtentType`, and `StrideType` are signed or
3108
+ unsigned integer types, or model `integral-constant-like`.
3109
+
3110
+ [*Note 1*:
3111
+
3112
+ `strided_slice{.offset = 1, .extent = 10, .stride = 3}`
3113
+
3114
+ indicates the indices `1`, `4`, `7`, and `10`. Indices are selected from
3115
+ the half-open interval \[`1`, `1 + 10`).
3116
+
3117
+ — *end note*]
3118
+
3119
+ ##### `submdspan_mapping_result` <a id="mdspan.sub.map.result">[[mdspan.sub.map.result]]</a>
3120
+
3121
+ Specializations of `submdspan_mapping_result` are returned by overloads
3122
+ of `submdspan_mapping`.
3123
+
3124
+ ``` cpp
3125
+ namespace std {
3126
+ template<class LayoutMapping>
3127
+ struct submdspan_mapping_result {
3128
+ [[no_unique_address]] LayoutMapping mapping = LayoutMapping();
3129
+ size_t offset{};
3130
+ };
3131
+ }
3132
+ ```
3133
+
3134
+ `submdspan_mapping_result` has the data members and special members
3135
+ specified above. It has no base classes or members other than those
3136
+ specified.
3137
+
3138
+ `LayoutMapping` shall meet the layout mapping requirements
3139
+ [[mdspan.layout.policy.reqmts]].
3140
+
3141
+ ##### Exposition-only helpers <a id="mdspan.sub.helpers">[[mdspan.sub.helpers]]</a>
3142
+
3143
+ ``` cpp
3144
+ template<class T>
3145
+ constexpr T de-ice(T val) { return val; }
3146
+ template<integral-constant-like T>
3147
+ constexpr auto de-ice(T) { return T::value; }
3148
+
3149
+ template<class IndexType, size_t k, class... SliceSpecifiers>
3150
+ constexpr IndexType first_(SliceSpecifiers... slices);
3151
+ ```
3152
+
3153
+ *Mandates:* `IndexType` is a signed or unsigned integer type.
3154
+
3155
+ Let φₖ denote the following value:
3156
+
3157
+ - sₖ if Sₖ models `convertible_to<IndexType>`;
3158
+ - otherwise, `get<0>(`sₖ`)` if Sₖ models `index-pair-like<IndexType>`;
3159
+ - otherwise, *`de-ice`*`(`sₖ`.offset)` if Sₖ is a specialization of
3160
+ `strided_slice`;
3161
+ - otherwise, `0`.
3162
+
3163
+ *Preconditions:* φₖ is representable as a value of type `IndexType`.
3164
+
3165
+ *Returns:* `extents<IndexType>::`*`index-cast`*`(`φₖ`)`.
3166
+
3167
+ ``` cpp
3168
+ template<size_t k, class Extents, class... SliceSpecifiers>
3169
+ constexpr auto last_(const Extents& src, SliceSpecifiers... slices);
3170
+ ```
3171
+
3172
+ *Mandates:* `Extents` is a specialization of `extents`.
3173
+
3174
+ Let `index_type` be `typename Extents::index_type`.
3175
+
3176
+ Let λₖ denote the following value:
3177
+
3178
+ - *`de-ice`*`(`sₖ`) + 1` if Sₖ models `convertible_to<index_type>`;
3179
+ otherwise
3180
+ - `get<1>(`sₖ`)` if Sₖ models `index-pair-like<index_type>`; otherwise
3181
+ - *`de-ice`*`(`sₖ`.offset)` `+` *`de-ice`*`(`sₖ`.extent)` if Sₖ is a
3182
+ specialization of `strided_slice`; otherwise
3183
+ - `src.extent(k)`.
3184
+
3185
+ *Preconditions:* λₖ is representable as a value of type `index_type`.
3186
+
3187
+ *Returns:* `Extents::`*`index-cast`*`(`λₖ`)`.
3188
+
3189
+ ``` cpp
3190
+ template<class IndexType, size_t N, class... SliceSpecifiers>
3191
+ constexpr array<IndexType, sizeof...(SliceSpecifiers)>
3192
+ src-indices(const array<IndexType, N>& indices, SliceSpecifiers... slices);
3193
+ ```
3194
+
3195
+ *Mandates:* `IndexType` is a signed or unsigned integer type.
3196
+
3197
+ *Returns:* An `array<IndexType, sizeof...(SliceSpecifiers)> src_idx`
3198
+ such that for each k in the range \[`0`, `sizeof...(SliceSpecifiers)`),
3199
+ `src_idx[`k`]` equals
3200
+
3201
+ - *`first_`*`<IndexType, `k`>(slices...)` for each k where
3202
+ *`map-rank`*`[`k`]` equals `dynamic_extent`,
3203
+ - otherwise, *`first_`*`<IndexType, `k`>(slices...)` `+`
3204
+ `indices[`*`map-rank`*`[`k`]]`.
3205
+
3206
+ ##### `submdspan_extents` function <a id="mdspan.sub.extents">[[mdspan.sub.extents]]</a>
3207
+
3208
+ ``` cpp
3209
+ template<class IndexType, size_t... Extents, class... SliceSpecifiers>
3210
+ constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src,
3211
+ SliceSpecifiers... slices);
3212
+ ```
3213
+
3214
+ *Constraints:* `sizeof...(slices)` equals `sizeof...(Extents)`.
3215
+
3216
+ *Mandates:* For each rank index k of `src.extents()`, exactly one of the
3217
+ following is true:
3218
+
3219
+ - Sₖ models `convertible_to<IndexType>`,
3220
+ - Sₖ models `index-pair-like<IndexType>`,
3221
+ - `is_convertible_v<`Sₖ`, full_extent_t>` is `true`, or
3222
+ - Sₖ is a specialization of `strided_slice`.
3223
+
3224
+ *Preconditions:* For each rank index k of `src.extents()`, all of the
3225
+ following are `true`:
3226
+
3227
+ - if Sₖ is a specialization of `strided_slice`
3228
+ - `$s_k$.extent` = 0, or
3229
+ - `$s_k$.stride` > 0
3230
+ - $0 \le \texttt{\textit{first_}<IndexType, $k$>(slices...)}$
3231
+ $\le \texttt{\textit{last_}<$k$>(src, slices...)}$ ≤ `src.extent($k$)`
3232
+
3233
+ Let `SubExtents` be a specialization of `extents` such that:
3234
+
3235
+ - `SubExtents::rank()` equals the number of k such that Sₖ does not
3236
+ model `convertible_to<IndexType>`; and
3237
+ - for each rank index k of `Extents` such that
3238
+ *`map-rank`*`[`k`] != dynamic_extent` is `true`,
3239
+ `SubExtents::static_extent(`*`map-rank`*`[`k`])` equals:
3240
+ - `Extents::static_extent(`k`)` if
3241
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; otherwise
3242
+ - *`de-ice`*`(tuple_element_t<1, `Sₖ`>()) -`
3243
+ *`de-ice`*`(tuple_element_t<0, `Sₖ`>())` if Sₖ models
3244
+ `index-pair-like<IndexType>`, and both `tuple_element_t<0, `Sₖ`>`
3245
+ and `tuple_element_t<1, `Sₖ`>` model `integral-constant-like`;
3246
+ otherwise
3247
+ - `0`, if Sₖ is a specialization of `strided_slice`, whose
3248
+ `extent_type` models *`integral-constant-like`*, for which
3249
+ `extent_type()` equals zero; otherwise
3250
+ - `1 + (`*`de-ice`*`(`Sₖ`::extent_type()) - 1) /`
3251
+ *`de-ice`*`(`Sₖ`::stride_type())`, if Sₖ is a specialization of
3252
+ `strided_slice` whose `extent_type` and `stride_type` model
3253
+ *`integral-constant-like`*;
3254
+ - otherwise, `dynamic_extent`.
3255
+
3256
+ *Returns:* A value `ext` of type `SubExtents` such that for each k for
3257
+ which *`map-rank`*`[`k`] != dynamic_extent` is `true`,
3258
+ `ext.extent(`*`map-rank`*`[`k`])` equals:
3259
+
3260
+ - sₖ`.extent == 0 ? 0 : 1 + (`*`de-ice`*`(`sₖ`.extent) - 1) / `*`de-ice`*`(`sₖ`.stride)`
3261
+ if Sₖ is a specialization of `strided_slice`,
3262
+ - otherwise,
3263
+ *`last_`*`<`k`>(src, slices...) - `*`first_`*`<IndexType, `k`>(slices...)`.
3264
+
3265
+ ##### Specializations of `submdspan_mapping` <a id="mdspan.sub.map">[[mdspan.sub.map]]</a>
3266
+
3267
+ ###### Common <a id="mdspan.sub.map.common">[[mdspan.sub.map.common]]</a>
3268
+
3269
+ The following elements apply to all functions in [[mdspan.sub.map]].
3270
+
3271
+ *Constraints:* `sizeof...(slices)` equals `extents_type::rank()`.
3272
+
3273
+ *Mandates:* For each rank index k of `extents()`, exactly one of the
3274
+ following is true:
3275
+
3276
+ - Sₖ models `convertible_to<index_type>`,
3277
+ - Sₖ models `index-pair-like<index_type>`,
3278
+ - `is_convertible_v<Sₖ, full_extent_t>` is `true`, or
3279
+ - Sₖ is a specialization of `strided_slice`.
3280
+
3281
+ *Preconditions:* For each rank index k of `extents()`, all of the
3282
+ following are `true`:
3283
+
3284
+ - if Sₖ is a specialization of `strided_slice`, `sₖ.extent` is equal to
3285
+ zero or `sₖ.stride` is greater than zero; and
3286
+ - $0 \leq \tcode{\exposid{first_}<index_type, $k$>(slices...)} \\
3287
+ \hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\
3288
+ \hphantom{0 } \leq \tcode{extents().extent($k$)}$
3289
+
3290
+ Let `sub_ext` be the result of `submdspan_extents(extents(), slices...)`
3291
+ and let `SubExtents` be `decltype(sub_ext)`.
3292
+
3293
+ Let `sub_strides` be an
3294
+ `array<SubExtents::index_type, SubExtents::rank()>` such that for each
3295
+ rank index k of `extents()` for which `map-rank[k]` is not
3296
+ `dynamic_extent`, `sub_strides[map-rank[k]]` equals:
3297
+
3298
+ - `stride(k) * de-ice(sₖ.stride)` if Sₖ is a specialization of
3299
+ `strided_slice` and `sₖ.stride < sₖ.extent` is `true`;
3300
+ - otherwise, `stride(k)`.
3301
+
3302
+ Let `P` be a parameter pack such that
3303
+ `is_same_v<make_index_sequence<rank()>, index_sequence<P...>>` is
3304
+ `true`.
3305
+
3306
+ If `first_<index_type, k>(slices...)` equals `extents().extent(k)` for
3307
+ any rank index k of `extents()`, then let `offset` be a value of type
3308
+ `size_t` equal to `(*this).required_span_size()`. Otherwise, let
3309
+ `offset` be a value of type `size_t` equal to
3310
+ `(*this)(first_<index_type, P>(slices...)...)`.
3311
+
3312
+ Given a layout mapping type `M`, a type `S` is a *unit-stride slice for
3313
+ `M`* if
3314
+
3315
+ - `S` is a specialization of `strided_slice` where `S::stride_type`
3316
+ models `integral-constant-like` and `S::stride_type::value` equals
3317
+ `1`,
3318
+ - `S` models `index-pair-like<M::index_type>`, or
3319
+ - `is_convertible_v<S, full_extent_t>` is `true`.
3320
+
3321
+ ###### `layout_left` specialization of `submdspan_mapping` <a id="mdspan.sub.map.left">[[mdspan.sub.map.left]]</a>
3322
+
3323
+ ``` cpp
3324
+ template<class Extents>
3325
+ template<class... SliceSpecifiers>
3326
+ constexpr auto layout_left::mapping<Extents>::submdspan-mapping-impl(
3327
+ SliceSpecifiers... slices) const -> see below;
3328
+ ```
3329
+
3330
+ *Returns:*
3331
+
3332
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
3333
+ `true`;
3334
+ - otherwise,
3335
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
3336
+ `SubExtents::rank() == 0` is `true`;
3337
+ - otherwise,
3338
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
3339
+ - for each k in the range \[`0`, `SubExtents::rank() - 1)`),
3340
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3341
+ - for k equal to `SubExtents::rank() - 1`, Sₖ is a unit-stride slice
3342
+ for `mapping`;
3343
+
3344
+ \[*Note 2*: If the above conditions are true, all Sₖ with k larger
3345
+ than `SubExtents::rank() - 1` are convertible to
3346
+ `index_type`. — *end note*]
3347
+ - otherwise,
3348
+ ``` cpp
3349
+ submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
3350
+ offset}
3351
+ ```
3352
+
3353
+ if for a value u for which u+1 is the smallest value p larger than
3354
+ zero for which Sₚ is a unit-stride slice for `mapping`, the following
3355
+ conditions are met:
3356
+ - S₀ is a unit-stride slice for `mapping`; and
3357
+ - for each k in the range \[u` + 1`, u` + SubExtents::rank() - 1`),
3358
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3359
+ - for k equal to u` + SubExtents::rank() - 1`, Sₖ is a unit-stride
3360
+ slice for `mapping`;
3361
+
3362
+ and where `S_static` is:
3363
+ - `dynamic_extent`, if `static_extent(`k`)` is `dynamic_extent` for
3364
+ any k in the range \[`0`, u` + 1`),
3365
+ - otherwise, the product of all values `static_extent(`k`)` for k in
3366
+ the range \[`0`, u` + 1`);
3367
+ - otherwise,
3368
+ ``` cpp
3369
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3370
+ ```
3371
+
3372
+ ###### `layout_right` specialization of `submdspan_mapping` <a id="mdspan.sub.map.right">[[mdspan.sub.map.right]]</a>
3373
+
3374
+ ``` cpp
3375
+ template<class Extents>
3376
+ template<class... SliceSpecifiers>
3377
+ constexpr auto layout_right::mapping<Extents>::submdspan-mapping-impl(
3378
+ SliceSpecifiers... slices) const -> see below;
3379
+ ```
3380
+
3381
+ *Returns:*
3382
+
3383
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
3384
+ `true`;
3385
+ - otherwise,
3386
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
3387
+ `SubExtents::rank() == 0` is `true`;
3388
+ - otherwise,
3389
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
3390
+ - for each k in the range \[*`rank_`*` - SubExtents::rank() + 1`,
3391
+ *`rank_`*), `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3392
+ - for k equal to *rank\_* - `SubExtents::rank()`, Sₖ is a unit-stride
3393
+ slice for `mapping`;
3394
+
3395
+ \[*Note 3*: If the above conditions are true, all Sₖ with
3396
+ $k < \texttt{\textit{rank_} - SubExtents::rank()}$ are convertible to
3397
+ `index_type`. — *end note*]
3398
+ - otherwise,
3399
+ ``` cpp
3400
+ submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
3401
+ stride(rank_ - u - 2)), offset}
3402
+ ```
3403
+
3404
+ if for a value u for which rank_ - u - 2 is the largest value p
3405
+ smaller than *`rank_`*` - 1` for which Sₚ is a unit-stride slice for
3406
+ `mapping`, the following conditions are met:
3407
+ - for k equal to *`rank_`*` - 1`, Sₖ is a unit-stride slice for
3408
+ `mapping`; and
3409
+ - for each k in the range
3410
+ \[*`rank_`*` - SubExtents::rank() - `u` + 1`,
3411
+ *`rank_`*` - `u` - 1`), `is_convertible_v<`Sₖ`, full_extent_t>` is
3412
+ `true`; and
3413
+ - for k equal to *`rank_`*` - SubExtents::rank() - `u, Sₖ is a
3414
+ unit-stride slice for `mapping`;
3415
+
3416
+ and where `S_static` is:
3417
+ - `dynamic_extent`, if `static_extent(`k`)` is `dynamic_extent` for
3418
+ any k in the range \[*`rank_`*` - `u` - 1`, *`rank_`*),
3419
+ - otherwise, the product of all values `static_extent(`k`)` for k in
3420
+ the range \[*`rank_`*` - `u` - 1`, *`rank_`*);
3421
+ - otherwise,
3422
+ ``` cpp
3423
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3424
+ ```
3425
+
3426
+ ###### `layout_stride` specialization of `submdspan_mapping` <a id="mdspan.sub.map.stride">[[mdspan.sub.map.stride]]</a>
3427
+
3428
+ ``` cpp
3429
+ template<class Extents>
3430
+ template<class... SliceSpecifiers>
3431
+ constexpr auto layout_stride::mapping<Extents>::submdspan-mapping-impl(
3432
+ SliceSpecifiers... slices) const -> see below;
3433
+ ```
3434
+
3435
+ *Returns:*
3436
+
3437
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
3438
+ `true`;
3439
+ - otherwise,
3440
+ ``` cpp
3441
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3442
+ ```
3443
+
3444
+ ###### `layout_left_padded` specialization of `submdspan_mapping` <a id="mdspan.sub.map.leftpad">[[mdspan.sub.map.leftpad]]</a>
3445
+
3446
+ ``` cpp
3447
+ template<class Extents>
3448
+ template<class... SliceSpecifiers>
3449
+ constexpr auto layout_left_padded::mapping<Extents>::submdspan-mapping-impl(
3450
+ SliceSpecifiers... slices) const -> see below;
3451
+ ```
3452
+
3453
+ *Returns:*
3454
+
3455
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
3456
+ `true`;
3457
+ - otherwise,
3458
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
3459
+ *`rank_`*` == 1` is `true` or `SubExtents::rank() == 0` is `true`;
3460
+ - otherwise,
3461
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
3462
+ - `SubExtents::rank() == 1` is `true` and
3463
+ - S₀ is a unit-stride slice for `mapping`;
3464
+ - otherwise,
3465
+ ``` cpp
3466
+ submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
3467
+ offset}
3468
+ ```
3469
+
3470
+ if for a value u for which u` + 1` is the smallest value p larger than
3471
+ zero for which Sₚ is a unit-stride slice for `mapping`, the following
3472
+ conditions are met:
3473
+ - S₀ is a unit-stride slice for `mapping`; and
3474
+ - for each k in the range \[u` + 1`, u` + SubExtents::rank() - 1`),
3475
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3476
+ - for k equal to u` + SubExtents::rank() - 1`, Sₖ is a unit-stride
3477
+ slice for `mapping`;
3478
+
3479
+ where `S_static` is:
3480
+ - `dynamic_extent`, if *static-padding-stride* is `dynamic_extent` or
3481
+ `static_extent(`k`)` is `dynamic_extent` for any k in the range
3482
+ \[`1`, u` + 1`),
3483
+ - otherwise, the product of *static-padding-stride* and all values
3484
+ `static_extent(`k`)` for k in the range \[`1`, u` + 1`);
3485
+ - otherwise,
3486
+ ``` cpp
3487
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3488
+ ```
3489
+
3490
+ ###### `layout_right_padded` specialization of `submdspan_mapping` <a id="mdspan.sub.map.rightpad">[[mdspan.sub.map.rightpad]]</a>
3491
+
3492
+ ``` cpp
3493
+ template<class Extents>
3494
+ template<class... SliceSpecifiers>
3495
+ constexpr auto layout_right_padded::mapping<Extents>::submdspan-mapping-impl(
3496
+ SliceSpecifiers... slices) const -> see below;
3497
+ ```
3498
+
3499
+ *Returns:*
3500
+
3501
+ - `submdspan_mapping_result{*this, 0}`, if *`rank_`*` == 0` is `true`;
3502
+ - otherwise,
3503
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
3504
+ *`rank_`*` == 1` is `true` or `SubExtents::rank() == 0` is `true`;
3505
+ - otherwise,
3506
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
3507
+ - `SubExtents::rank() == 1` is `true` and
3508
+ - for k equal to *`rank_`*` - 1`, Sₖ is a unit-stride slice for
3509
+ `mapping`;
3510
+ - otherwise,
3511
+ ``` cpp
3512
+ submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
3513
+ stride(rank_ - u - 2)), offset}
3514
+ ```
3515
+
3516
+ if for a value u for which *`rank_`*` - `u` - 2` is the largest value
3517
+ p smaller than *`rank_`*` - 1` for which Sₚ is a unit-stride slice for
3518
+ `mapping`, the following conditions are met:
3519
+ - for k equal to *`rank_`*` - 1`, Sₖ is a unit-stride slice for
3520
+ `mapping`; and
3521
+ - for each k in the range
3522
+ \[*`rank_`*` - SubExtents::rank() - `u` + 1`,
3523
+ *`rank_`*` - `u` - 1)`), `is_convertible_v<`Sₖ`, full_extent_t>` is
3524
+ `true`; and
3525
+ - for k equal to *`rank_`*` - SubExtents::rank() - `u, Sₖ is a
3526
+ unit-stride slice for `mapping`;
3527
+
3528
+ and where `S_static` is:
3529
+ - `dynamic_extent` if *static-padding-stride* is `dynamic_extent` or
3530
+ for any k in the range \[*`rank_`*` - `u` - 1`, *`rank_`*` - 1`)
3531
+ `static_extent(`k`)` is `dynamic_extent`,
3532
+ - otherwise, the product of *static-padding-stride* and all values
3533
+ `static_extent(`k`)` with k in the range \[*`rank_`*` - `u` - 1`,
3534
+ *`rank_`*` - 1`);
3535
+ - otherwise,
3536
+ ``` cpp
3537
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3538
+ ```
3539
+
3540
+ ##### `submdspan` function template <a id="mdspan.sub.sub">[[mdspan.sub.sub]]</a>
3541
+
3542
+ ``` cpp
3543
+ template<class ElementType, class Extents, class LayoutPolicy,
3544
+ class AccessorPolicy, class... SliceSpecifiers>
3545
+ constexpr auto submdspan(
3546
+ const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
3547
+ SliceSpecifiers... slices) -> see below;
3548
+ ```
3549
+
3550
+ Let `index_type` be `typename Extents::index_type`.
3551
+
3552
+ Let `sub_map_offset` be the result of
3553
+ `submdspan_mapping(src.mapping(), slices...)`.
3554
+
3555
+ [*Note 1*: This invocation of `submdspan_mapping` selects a function
3556
+ call via overload resolution on a candidate set that includes the lookup
3557
+ set found by argument-dependent
3558
+ lookup [[basic.lookup.argdep]]. — *end note*]
3559
+
3560
+ *Constraints:*
3561
+
3562
+ - `sizeof...(slices)` equals `Extents::rank()`, and
3563
+ - the expression `submdspan_mapping(src.mapping(), slices...)` is
3564
+ well-formed when treated as an unevaluated operand.
3565
+
3566
+ *Mandates:*
3567
+
3568
+ - `decltype(submdspan_mapping(src.mapping(), slices...))` is a
3569
+ specialization of `submd-span_mapping_result`.
3570
+ - `is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>,`
3571
+ `decltype(submdspan_extents(src.mapping(), slices...))>` is `true`.
3572
+ - For each rank index k of `src.extents()`, exactly one of the following
3573
+ is true:
3574
+ - Sₖ models `convertible_to<index_type>`,
3575
+ - Sₖ models `index-pair-like<index_type>`,
3576
+ - `is_convertible_v<`Sₖ`, full_extent_t>` is `true`, or
3577
+ - Sₖ is a specialization of `strided_slice`.
3578
+
3579
+ *Preconditions:*
3580
+
3581
+ - For each rank index k of `src.extents()`, all of the following are
3582
+ `true`:
3583
+ - if Sₖ is a specialization of `strided_slice`
3584
+ - `$s_k$.extent` = 0, or
3585
+ - `$s_k$.stride` > 0
3586
+ - $0 \le \texttt{\textit{first_}<index_type, $k$>(slices...)}$
3587
+ $\le \texttt{\textit{last_}<$k$>(src.extents(), slices...)}$
3588
+ ≤ `{}src.extent($k$)`
3589
+ - `sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...)`
3590
+ is `true`; and
3591
+ - for each integer pack `I` which is a multidimensional index in
3592
+ `sub_map_offset.mapping.extents()`,
3593
+ ``` cpp
3594
+ sub_map_offset.mapping(I...) + sub_map_offset.offset ==
3595
+ src.mapping()(src-indices(array{I...}, slices...))
3596
+ ```
3597
+
3598
+ is `true`.
3599
+
3600
+ [*Note 2*: These conditions ensure that the mapping returned by
3601
+ `submdspan_mapping` matches the algorithmically expected index-mapping
3602
+ given the slice specifiers. — *end note*]
3603
+
3604
+ *Effects:* Equivalent to:
3605
+
3606
+ ``` cpp
3607
+ auto sub_map_result = submdspan_mapping(src.mapping(), slices...);
3608
+ return mdspan(src.accessor().offset(src.data_handle(), sub_map_result.offset),
3609
+ sub_map_result.mapping,
3610
+ typename AccessorPolicy::offset_policy(src.accessor()));
3611
+ ```
3612
+
3613
+ [*Example 1*:
3614
+
3615
+ Given a rank-3 `mdspan grid3d` representing a three-dimensional grid of
3616
+ regularly spaced points in a rectangular prism, the function
3617
+ `zero_surface` sets all elements on the surface of the 3-dimensional
3618
+ shape to zero. It does so by reusing a function `zero_2d` that takes a
3619
+ rank-2 `mdspan`.
3620
+
3621
+ ``` cpp
3622
+ // zero out all elements in an mdspan
3623
+ template<class T, class E, class L, class A>
3624
+ void zero_2d(mdspan<T, E, L, A> a) {
3625
+ static_assert(a.rank() == 2);
3626
+ for (int i = 0; i < a.extent(0); i++)
3627
+ for (int j = 0; j < a.extent(1); j++)
3628
+ a[i, j] = 0;
3629
+ }
3630
+
3631
+ // zero out just the surface
3632
+ template<class T, class E, class L, class A>
3633
+ void zero_surface(mdspan<T, E, L, A> grid3d) {
3634
+ static_assert(grid3d.rank() == 3);
3635
+ zero_2d(submdspan(grid3d, 0, full_extent, full_extent));
3636
+ zero_2d(submdspan(grid3d, full_extent, 0, full_extent));
3637
+ zero_2d(submdspan(grid3d, full_extent, full_extent, 0));
3638
+ zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent));
3639
+ zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent));
3640
+ zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1));
3641
+ }
3642
+ ```
3643
+
3644
+ — *end example*]
3645
+
3646
  <!-- Link reference definitions -->
3647
  [alg.equal]: algorithms.md#alg.equal
3648
  [alg.sorting]: algorithms.md#alg.sorting
3649
  [algorithm.stable]: library.md#algorithm.stable
3650
  [algorithms]: algorithms.md#algorithms
 
3668
  [associative.reqmts]: #associative.reqmts
3669
  [associative.reqmts.except]: #associative.reqmts.except
3670
  [associative.reqmts.general]: #associative.reqmts.general
3671
  [associative.set.syn]: #associative.set.syn
3672
  [basic.fundamental]: basic.md#basic.fundamental
3673
+ [basic.lookup.argdep]: basic.md#basic.lookup.argdep
3674
  [basic.string]: strings.md#basic.string
3675
  [class.copy.ctor]: class.md#class.copy.ctor
3676
  [class.default.ctor]: class.md#class.default.ctor
3677
  [class.dtor]: class.md#class.dtor
3678
  [container.adaptors]: #container.adaptors
3679
  [container.adaptors.format]: #container.adaptors.format
3680
  [container.adaptors.general]: #container.adaptors.general
3681
  [container.alloc.reqmts]: #container.alloc.reqmts
 
3682
  [container.insert.return]: #container.insert.return
3683
+ [container.intro.reqmts]: #container.intro.reqmts
3684
  [container.node]: #container.node
3685
  [container.node.compat]: #container.node.compat
3686
  [container.node.cons]: #container.node.cons
3687
  [container.node.dtor]: #container.node.dtor
3688
  [container.node.modifiers]: #container.node.modifiers
 
3710
  [expr.const]: expr.md#expr.const
3711
  [flat.map]: #flat.map
3712
  [flat.map.access]: #flat.map.access
3713
  [flat.map.capacity]: #flat.map.capacity
3714
  [flat.map.cons]: #flat.map.cons
3715
+ [flat.map.cons.alloc]: #flat.map.cons.alloc
3716
  [flat.map.defn]: #flat.map.defn
3717
  [flat.map.erasure]: #flat.map.erasure
3718
  [flat.map.modifiers]: #flat.map.modifiers
3719
  [flat.map.overview]: #flat.map.overview
3720
  [flat.map.syn]: #flat.map.syn
3721
  [flat.multimap]: #flat.multimap
3722
  [flat.multimap.cons]: #flat.multimap.cons
3723
+ [flat.multimap.cons.alloc]: #flat.multimap.cons.alloc
3724
  [flat.multimap.defn]: #flat.multimap.defn
3725
  [flat.multimap.erasure]: #flat.multimap.erasure
3726
  [flat.multimap.overview]: #flat.multimap.overview
3727
  [flat.multiset]: #flat.multiset
3728
  [flat.multiset.cons]: #flat.multiset.cons
3729
+ [flat.multiset.cons.alloc]: #flat.multiset.cons.alloc
3730
  [flat.multiset.defn]: #flat.multiset.defn
3731
  [flat.multiset.erasure]: #flat.multiset.erasure
3732
  [flat.multiset.modifiers]: #flat.multiset.modifiers
3733
  [flat.multiset.overview]: #flat.multiset.overview
3734
  [flat.set]: #flat.set
3735
  [flat.set.cons]: #flat.set.cons
3736
+ [flat.set.cons.alloc]: #flat.set.cons.alloc
3737
  [flat.set.defn]: #flat.set.defn
3738
  [flat.set.erasure]: #flat.set.erasure
3739
  [flat.set.modifiers]: #flat.set.modifiers
3740
  [flat.set.overview]: #flat.set.overview
3741
  [flat.set.syn]: #flat.set.syn
 
3748
  [forward.list.modifiers]: #forward.list.modifiers
3749
  [forward.list.ops]: #forward.list.ops
3750
  [forward.list.overview]: #forward.list.overview
3751
  [forward.list.syn]: #forward.list.syn
3752
  [hash.requirements]: library.md#hash.requirements
3753
+ [hive]: #hive
3754
+ [hive.capacity]: #hive.capacity
3755
+ [hive.cons]: #hive.cons
3756
+ [hive.erasure]: #hive.erasure
3757
+ [hive.modifiers]: #hive.modifiers
3758
+ [hive.operations]: #hive.operations
3759
+ [hive.overview]: #hive.overview
3760
+ [hive.syn]: #hive.syn
3761
+ [inplace.vector]: #inplace.vector
3762
+ [inplace.vector.capacity]: #inplace.vector.capacity
3763
+ [inplace.vector.cons]: #inplace.vector.cons
3764
+ [inplace.vector.data]: #inplace.vector.data
3765
+ [inplace.vector.erasure]: #inplace.vector.erasure
3766
+ [inplace.vector.modifiers]: #inplace.vector.modifiers
3767
+ [inplace.vector.overview]: #inplace.vector.overview
3768
+ [inplace.vector.syn]: #inplace.vector.syn
3769
  [iterator.concept.contiguous]: iterators.md#iterator.concept.contiguous
3770
  [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
3771
  [iterator.requirements]: iterators.md#iterator.requirements
3772
  [iterator.requirements.general]: iterators.md#iterator.requirements.general
3773
  [list]: #list
 
3783
  [map.cons]: #map.cons
3784
  [map.erasure]: #map.erasure
3785
  [map.modifiers]: #map.modifiers
3786
  [map.overview]: #map.overview
3787
  [mdspan.accessor]: #mdspan.accessor
3788
+ [mdspan.accessor.aligned]: #mdspan.accessor.aligned
3789
+ [mdspan.accessor.aligned.members]: #mdspan.accessor.aligned.members
3790
+ [mdspan.accessor.aligned.overview]: #mdspan.accessor.aligned.overview
3791
  [mdspan.accessor.default]: #mdspan.accessor.default
3792
  [mdspan.accessor.default.members]: #mdspan.accessor.default.members
3793
  [mdspan.accessor.default.overview]: #mdspan.accessor.default.overview
3794
  [mdspan.accessor.general]: #mdspan.accessor.general
3795
  [mdspan.accessor.reqmts]: #mdspan.accessor.reqmts
3796
  [mdspan.extents]: #mdspan.extents
3797
  [mdspan.extents.cmp]: #mdspan.extents.cmp
3798
  [mdspan.extents.cons]: #mdspan.extents.cons
3799
  [mdspan.extents.dextents]: #mdspan.extents.dextents
3800
+ [mdspan.extents.dims]: #mdspan.extents.dims
3801
  [mdspan.extents.expo]: #mdspan.extents.expo
3802
  [mdspan.extents.obs]: #mdspan.extents.obs
3803
  [mdspan.extents.overview]: #mdspan.extents.overview
3804
  [mdspan.layout]: #mdspan.layout
3805
  [mdspan.layout.general]: #mdspan.layout.general
3806
  [mdspan.layout.left]: #mdspan.layout.left
3807
  [mdspan.layout.left.cons]: #mdspan.layout.left.cons
3808
  [mdspan.layout.left.obs]: #mdspan.layout.left.obs
3809
  [mdspan.layout.left.overview]: #mdspan.layout.left.overview
3810
+ [mdspan.layout.leftpad]: #mdspan.layout.leftpad
3811
+ [mdspan.layout.leftpad.cons]: #mdspan.layout.leftpad.cons
3812
+ [mdspan.layout.leftpad.expo]: #mdspan.layout.leftpad.expo
3813
+ [mdspan.layout.leftpad.obs]: #mdspan.layout.leftpad.obs
3814
+ [mdspan.layout.leftpad.overview]: #mdspan.layout.leftpad.overview
3815
  [mdspan.layout.policy.overview]: #mdspan.layout.policy.overview
3816
  [mdspan.layout.policy.reqmts]: #mdspan.layout.policy.reqmts
3817
  [mdspan.layout.reqmts]: #mdspan.layout.reqmts
3818
  [mdspan.layout.right]: #mdspan.layout.right
3819
  [mdspan.layout.right.cons]: #mdspan.layout.right.cons
3820
  [mdspan.layout.right.obs]: #mdspan.layout.right.obs
3821
  [mdspan.layout.right.overview]: #mdspan.layout.right.overview
3822
+ [mdspan.layout.rightpad]: #mdspan.layout.rightpad
3823
+ [mdspan.layout.rightpad.cons]: #mdspan.layout.rightpad.cons
3824
+ [mdspan.layout.rightpad.expo]: #mdspan.layout.rightpad.expo
3825
+ [mdspan.layout.rightpad.obs]: #mdspan.layout.rightpad.obs
3826
+ [mdspan.layout.rightpad.overview]: #mdspan.layout.rightpad.overview
3827
  [mdspan.layout.stride]: #mdspan.layout.stride
3828
  [mdspan.layout.stride.cons]: #mdspan.layout.stride.cons
3829
  [mdspan.layout.stride.expo]: #mdspan.layout.stride.expo
3830
  [mdspan.layout.stride.obs]: #mdspan.layout.stride.obs
3831
  [mdspan.layout.stride.overview]: #mdspan.layout.stride.overview
3832
  [mdspan.mdspan]: #mdspan.mdspan
3833
  [mdspan.mdspan.cons]: #mdspan.mdspan.cons
3834
  [mdspan.mdspan.members]: #mdspan.mdspan.members
3835
  [mdspan.mdspan.overview]: #mdspan.mdspan.overview
3836
  [mdspan.overview]: #mdspan.overview
3837
+ [mdspan.sub]: #mdspan.sub
3838
+ [mdspan.sub.extents]: #mdspan.sub.extents
3839
+ [mdspan.sub.helpers]: #mdspan.sub.helpers
3840
+ [mdspan.sub.map]: #mdspan.sub.map
3841
+ [mdspan.sub.map.common]: #mdspan.sub.map.common
3842
+ [mdspan.sub.map.left]: #mdspan.sub.map.left
3843
+ [mdspan.sub.map.leftpad]: #mdspan.sub.map.leftpad
3844
+ [mdspan.sub.map.result]: #mdspan.sub.map.result
3845
+ [mdspan.sub.map.right]: #mdspan.sub.map.right
3846
+ [mdspan.sub.map.rightpad]: #mdspan.sub.map.rightpad
3847
+ [mdspan.sub.map.stride]: #mdspan.sub.map.stride
3848
+ [mdspan.sub.overview]: #mdspan.sub.overview
3849
+ [mdspan.sub.strided.slice]: #mdspan.sub.strided.slice
3850
+ [mdspan.sub.sub]: #mdspan.sub.sub
3851
  [mdspan.syn]: #mdspan.syn
3852
  [multimap]: #multimap
3853
  [multimap.cons]: #multimap.cons
3854
  [multimap.erasure]: #multimap.erasure
3855
  [multimap.modifiers]: #multimap.modifiers
 
3871
  [queue.mod]: #queue.mod
3872
  [queue.ops]: #queue.ops
3873
  [queue.special]: #queue.special
3874
  [queue.syn]: #queue.syn
3875
  [random.access.iterators]: iterators.md#random.access.iterators
3876
+ [re.results]: text.md#re.results
3877
  [res.on.data.races]: library.md#res.on.data.races
3878
  [sequence.reqmts]: #sequence.reqmts
3879
  [sequences]: #sequences
3880
  [sequences.general]: #sequences.general
3881
  [set]: #set
3882
  [set.cons]: #set.cons
3883
  [set.erasure]: #set.erasure
3884
+ [set.modifiers]: #set.modifiers
3885
  [set.overview]: #set.overview
3886
  [span.cons]: #span.cons
3887
  [span.deduct]: #span.deduct
3888
  [span.elem]: #span.elem
3889
  [span.iterators]: #span.iterators
 
3899
  [stack.general]: #stack.general
3900
  [stack.mod]: #stack.mod
3901
  [stack.ops]: #stack.ops
3902
  [stack.special]: #stack.special
3903
  [stack.syn]: #stack.syn
3904
+ [stacktrace.basic]: diagnostics.md#stacktrace.basic
3905
  [strings]: strings.md#strings
3906
  [swappable.requirements]: library.md#swappable.requirements
3907
  [temp.deduct]: temp.md#temp.deduct
 
3908
  [temp.type]: temp.md#temp.type
3909
+ [term.structural.type]: temp.md#term.structural.type
3910
  [term.trivially.copyable.type]: basic.md#term.trivially.copyable.type
3911
  [unord]: #unord
3912
  [unord.general]: #unord.general
3913
  [unord.hash]: utilities.md#unord.hash
3914
  [unord.map]: #unord.map
 
3931
  [unord.req.except]: #unord.req.except
3932
  [unord.req.general]: #unord.req.general
3933
  [unord.set]: #unord.set
3934
  [unord.set.cnstr]: #unord.set.cnstr
3935
  [unord.set.erasure]: #unord.set.erasure
3936
+ [unord.set.modifiers]: #unord.set.modifiers
3937
  [unord.set.overview]: #unord.set.overview
3938
  [unord.set.syn]: #unord.set.syn
3939
  [vector]: #vector
3940
  [vector.bool]: #vector.bool
3941
  [vector.bool.fmt]: #vector.bool.fmt