From Jason Turner

[views]

Large diff (109.6 KB) - rendering may be slow on some devices

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmprwbgoq8b/{from.md → to.md} +2080 -95
tmp/tmprwbgoq8b/{from.md → to.md} RENAMED
@@ -9,22 +9,39 @@ with these multidimensional views.
9
  ### Contiguous access <a id="views.contiguous">[[views.contiguous]]</a>
10
 
11
  #### Header `<span>` synopsis <a id="span.syn">[[span.syn]]</a>
12
 
13
  ``` cpp
 
 
 
14
  namespace std {
15
  // constants
16
  inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  // [views.span], class template span
19
  template<class ElementType, size_t Extent = dynamic_extent>
20
- class span;
21
 
22
  template<class ElementType, size_t Extent>
23
- constexpr bool ranges::enable_view<span<ElementType, Extent>> = true;
24
  template<class ElementType, size_t Extent>
25
- constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true;
26
 
27
  // [span.objectrep], views of object representation
28
  template<class ElementType, size_t Extent>
29
  span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
30
  as_bytes(span<ElementType, Extent> s) noexcept;
@@ -76,16 +93,15 @@ namespace std {
76
  constexpr span(array<T, N>& arr) noexcept;
77
  template<class T, size_t N>
78
  constexpr span(const array<T, N>& arr) noexcept;
79
  template<class R>
80
  constexpr explicit(extent != dynamic_extent) span(R&& r);
 
81
  constexpr span(const span& other) noexcept = default;
82
  template<class OtherElementType, size_t OtherExtent>
83
  constexpr explicit(see below) span(const span<OtherElementType, OtherExtent>& s) noexcept;
84
 
85
- ~span() noexcept = default;
86
-
87
  constexpr span& operator=(const span& other) noexcept = default;
88
 
89
  // [span.sub], subviews
90
  template<size_t Count>
91
  constexpr span<element_type, Count> first() const;
@@ -100,14 +116,15 @@ namespace std {
100
  size_type offset, size_type count = dynamic_extent) const;
101
 
102
  // [span.obs], observers
103
  constexpr size_type size() const noexcept;
104
  constexpr size_type size_bytes() const noexcept;
105
- [[nodiscard]] constexpr bool empty() const noexcept;
106
 
107
  // [span.elem], element access
108
  constexpr reference operator[](size_type idx) const;
 
109
  constexpr reference front() const;
110
  constexpr reference back() const;
111
  constexpr pointer data() const noexcept;
112
 
113
  // [span.iterators], iterator support
@@ -124,11 +141,12 @@ namespace std {
124
  pointer data_; // exposition only
125
  size_type size_; // exposition only
126
  };
127
 
128
  template<class It, class EndOrSize>
129
- span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>>;
 
130
  template<class T, size_t N>
131
  span(T (&)[N]) -> span<T, N>;
132
  template<class T, size_t N>
133
  span(array<T, N>&) -> span<T, N>;
134
  template<class T, size_t N>
@@ -142,10 +160,14 @@ namespace std {
142
  [[term.trivially.copyable.type]].
143
 
144
  `ElementType` is required to be a complete object type that is not an
145
  abstract class type.
146
 
 
 
 
 
147
  ##### Constructors, copy, and assignment <a id="span.cons">[[span.cons]]</a>
148
 
149
  ``` cpp
150
  constexpr span() noexcept;
151
  ```
@@ -168,14 +190,15 @@ template<class It>
168
 
169
  *Preconditions:*
170
 
171
  - \[`first`, `first + count`) is a valid range.
172
  - `It` models `contiguous_iterator`.
173
- - If `extent` is not equal to `dynamic_extent`, then `count` is equal to
174
- `extent`.
175
 
176
- *Effects:* Initializes *`data_`* with `to_address(first)` and *`size_`*
 
 
 
177
  with `count`.
178
 
179
  *Throws:* Nothing.
180
 
181
  ``` cpp
@@ -192,28 +215,29 @@ template<class It, class End>
192
  - `End` satisfies `sized_sentinel_for<It>`.
193
  - `is_convertible_v<End, size_t>` is `false`.
194
 
195
  *Preconditions:*
196
 
197
- - If `extent` is not equal to `dynamic_extent`, then `last - first` is
198
- equal to `extent`.
199
  - \[`first`, `last`) is a valid range.
200
  - `It` models `contiguous_iterator`.
201
  - `End` models `sized_sentinel_for<It>`.
202
 
203
- *Effects:* Initializes *`data_`* with `to_address(first)` and *`size_`*
 
 
 
204
  with `last - first`.
205
 
206
  *Throws:* When and what `last - first` throws.
207
 
208
  ``` cpp
209
  template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;
210
  template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept;
211
  template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;
212
  ```
213
 
214
- *Constraints:* Let `U` be `remove_pointer_t<decltype(data(arr))>`.
215
 
216
  - `extent == dynamic_extent || N == extent` is `true`, and
217
  - `is_convertible_v<U(*)[], element_type(*)[]>` is `true`.
218
  \[*Note 3*: The intent is to allow only qualification conversions of
219
  the array element type to `element_type`. — *end note*]
@@ -221,11 +245,11 @@ template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;
221
  *Effects:* Constructs a `span` that is a view over the supplied array.
222
 
223
  [*Note 1*: `type_identity_t` affects class template argument
224
  deduction. — *end note*]
225
 
226
- *Ensures:* `size() == N && data() == data(arr)` is `true`.
227
 
228
  ``` cpp
229
  template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);
230
  ```
231
 
@@ -242,21 +266,34 @@ template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);
242
  \[*Note 4*: The intent is to allow only qualification conversions of
243
  the range reference type to `element_type`. — *end note*]
244
 
245
  *Preconditions:*
246
 
247
- - If `extent` is not equal to `dynamic_extent`, then `ranges::size(r)`
248
- is equal to `extent`.
249
  - `R` models `ranges::contiguous_range` and `ranges::sized_range`.
250
  - If `is_const_v<element_type>` is `false`, `R` models
251
  `ranges::borrowed_range`.
252
 
253
- *Effects:* Initializes *`data_`* with `ranges::data(r)` and *`size_`*
254
- with `ranges::size(r)`.
 
 
 
255
 
256
  *Throws:* What and when `ranges::data(r)` and `ranges::size(r)` throw.
257
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  ``` cpp
259
  constexpr span(const span& other) noexcept = default;
260
  ```
261
 
262
  *Ensures:* `other.size() == size() && other.data() == data()`.
@@ -273,12 +310,12 @@ template<class OtherElementType, size_t OtherExtent>
273
  - `is_convertible_v<OtherElementType(*)[], element_type(*)[]>` is
274
  `true`. \[*Note 5*: The intent is to allow only qualification
275
  conversions of the `OtherElementType` to
276
  `element_type`. — *end note*]
277
 
278
- *Preconditions:* If `extent` is not equal to `dynamic_extent`, then
279
- `s.size()` is equal to `extent`.
280
 
281
  *Effects:* Constructs a `span` that is a view over the range
282
  \[`s.data()`, `s.data() + s.size()`).
283
 
284
  *Ensures:* `size() == s.size() && data() == s.data()`.
@@ -297,11 +334,12 @@ constexpr span& operator=(const span& other) noexcept = default;
297
 
298
  ##### Deduction guides <a id="span.deduct">[[span.deduct]]</a>
299
 
300
  ``` cpp
301
  template<class It, class EndOrSize>
302
- span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>>;
 
303
  ```
304
 
305
  *Constraints:* `It` satisfies `contiguous_iterator`.
306
 
307
  ``` cpp
@@ -317,22 +355,22 @@ template<class R>
317
  template<size_t Count> constexpr span<element_type, Count> first() const;
318
  ```
319
 
320
  *Mandates:* `Count <= Extent` is `true`.
321
 
322
- *Preconditions:* `Count <= size()` is `true`.
323
 
324
  *Effects:* Equivalent to: `return R{data(), Count};` where `R` is the
325
  return type.
326
 
327
  ``` cpp
328
  template<size_t Count> constexpr span<element_type, Count> last() const;
329
  ```
330
 
331
  *Mandates:* `Count <= Extent` is `true`.
332
 
333
- *Preconditions:* `Count <= size()` is `true`.
334
 
335
  *Effects:* Equivalent to: `return R{data() + (size() - Count), Count};`
336
  where `R` is the return type.
337
 
338
  ``` cpp
@@ -346,12 +384,10 @@ template<size_t Offset, size_t Count = dynamic_extent>
346
  Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset)
347
  ```
348
 
349
  is `true`.
350
 
351
- *Preconditions:*
352
-
353
  ``` cpp
354
  Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset)
355
  ```
356
 
357
  is `true`.
@@ -373,29 +409,27 @@ Count != dynamic_extent ? Count
373
 
374
  ``` cpp
375
  constexpr span<element_type, dynamic_extent> first(size_type count) const;
376
  ```
377
 
378
- *Preconditions:* `count <= size()` is `true`.
379
 
380
  *Effects:* Equivalent to: `return {data(), count};`
381
 
382
  ``` cpp
383
  constexpr span<element_type, dynamic_extent> last(size_type count) const;
384
  ```
385
 
386
- *Preconditions:* `count <= size()` is `true`.
387
 
388
  *Effects:* Equivalent to: `return {data() + (size() - count), count};`
389
 
390
  ``` cpp
391
  constexpr span<element_type, dynamic_extent> subspan(
392
  size_type offset, size_type count = dynamic_extent) const;
393
  ```
394
 
395
- *Preconditions:*
396
-
397
  ``` cpp
398
  offset <= size() && (count == dynamic_extent || count <= size() - offset)
399
  ```
400
 
401
  is `true`.
@@ -419,46 +453,60 @@ constexpr size_type size_bytes() const noexcept;
419
  ```
420
 
421
  *Effects:* Equivalent to: `return size() * sizeof(element_type);`
422
 
423
  ``` cpp
424
- [[nodiscard]] constexpr bool empty() const noexcept;
425
  ```
426
 
427
  *Effects:* Equivalent to: `return size() == 0;`
428
 
429
  ##### Element access <a id="span.elem">[[span.elem]]</a>
430
 
431
  ``` cpp
432
  constexpr reference operator[](size_type idx) const;
433
  ```
434
 
435
- *Preconditions:* `idx < size()` is `true`.
436
 
437
- *Effects:* Equivalent to: `return *(data() + idx);`
 
 
 
 
 
 
 
 
 
 
438
 
439
  ``` cpp
440
  constexpr reference front() const;
441
  ```
442
 
443
- *Preconditions:* `empty()` is `false`.
444
 
445
- *Effects:* Equivalent to: `return *data();`
 
 
446
 
447
  ``` cpp
448
  constexpr reference back() const;
449
  ```
450
 
451
- *Preconditions:* `empty()` is `false`.
452
 
453
- *Effects:* Equivalent to: `return *(data() + (size() - 1));`
 
 
454
 
455
  ``` cpp
456
  constexpr pointer data() const noexcept;
457
  ```
458
 
459
- *Effects:* Equivalent to: `return `*`data_`*`;`
460
 
461
  ##### Iterator support <a id="span.iterators">[[span.iterators]]</a>
462
 
463
  ``` cpp
464
  using iterator = implementation-defined // type of span::iterator;
@@ -546,42 +594,81 @@ the following are true:
546
  the interval [Lᵢ, Uᵢ) of S.
547
 
548
  #### Header `<mdspan>` synopsis <a id="mdspan.syn">[[mdspan.syn]]</a>
549
 
550
  ``` cpp
 
551
  namespace std {
552
  // [mdspan.extents], class template extents
553
  template<class IndexType, size_t... Extents>
554
  class extents;
555
 
556
  // [mdspan.extents.dextents], alias template dextents
557
  template<class IndexType, size_t Rank>
558
  using dextents = see below;
559
 
 
 
 
 
560
  // [mdspan.layout], layout mapping
561
  struct layout_left;
562
  struct layout_right;
563
  struct layout_stride;
 
 
 
 
564
 
565
  // [mdspan.accessor.default], class template default_accessor
566
  template<class ElementType>
567
  class default_accessor;
568
 
 
 
 
 
569
  // [mdspan.mdspan], class template mdspan
570
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
571
  class AccessorPolicy = default_accessor<ElementType>>
572
- class mdspan;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  }
574
  ```
575
 
576
  #### Class template `extents` <a id="mdspan.extents">[[mdspan.extents]]</a>
577
 
578
  ##### Overview <a id="mdspan.extents.overview">[[mdspan.extents.overview]]</a>
579
 
580
  The class template `extents` represents a multidimensional index space
581
- of rank equal to `sizeof...(Extents)`. In subclause [[views]], `extents`
582
- is used synonymously with multidimensional index space.
583
 
584
  ``` cpp
585
  namespace std {
586
  template<class IndexType, size_t... Extents>
587
  class extents {
@@ -761,12 +848,12 @@ Let `N` be `sizeof...(OtherIndexTypes)`, and let `exts_arr` be
761
 
762
  - If `N != rank_dynamic()` is `true`, `exts_arr[`r`]` equals Eᵣ for each
763
  r for which Eᵣ is a static extent, and
764
  - either
765
  - `sizeof...(exts) == 0` is `true`, or
766
- - each element of `exts` is nonnegative and is representable as a
767
- value of type `index_type`.
768
 
769
  *Ensures:* `*this == extents(exts_arr)` is `true`.
770
 
771
  ``` cpp
772
  template<class OtherIndexType, size_t N>
@@ -788,16 +875,16 @@ template<class OtherIndexType, size_t N>
788
 
789
  - If `N != rank_dynamic()` is `true`, `exts[`r`]` equals Eᵣ for each r
790
  for which Eᵣ is a static extent, and
791
  - either
792
  - `N` is zero, or
793
- - `exts[`r`]` is nonnegative and is representable as a value of type
794
  `index_type` for every rank index r.
795
 
796
  *Effects:*
797
 
798
- - If `N` equals `dynamic_rank()`, for all d in the range
799
  [0, `rank_dynamic()`), direct-non-list-initializes
800
  *`dynamic-extents`*`[`d`]` with `as_const(exts[`d`])`.
801
  - Otherwise, for all d in the range [0, `rank_dynamic()`),
802
  direct-non-list-initializes *`dynamic-extents`*`[`d`]` with
803
  `as_const(exts[`*`dynamic-index-inv`*`(`d`)])`.
@@ -807,11 +894,12 @@ template<class... Integrals>
807
  explicit extents(Integrals...) -> see below;
808
  ```
809
 
810
  *Constraints:* `(is_convertible_v<Integrals, size_t> && ...)` is `true`.
811
 
812
- *Remarks:* The deduced type is `dextents<size_t, sizeof...(Integrals)>`.
 
813
 
814
  ##### Observers of the multidimensional index space <a id="mdspan.extents.obs">[[mdspan.extents.obs]]</a>
815
 
816
  ``` cpp
817
  static constexpr size_t static_extent(rank_type i) noexcept;
@@ -850,16 +938,26 @@ template<class IndexType, size_t Rank>
850
 
851
  *Result:* A type `E` that is a specialization of `extents` such that
852
  `E::rank() == Rank && E::rank() == E::rank_dynamic()` is `true`, and
853
  `E::index_type` denotes `IndexType`.
854
 
 
 
 
 
 
 
 
 
 
 
 
855
  #### Layout mapping <a id="mdspan.layout">[[mdspan.layout]]</a>
856
 
857
  ##### General <a id="mdspan.layout.general">[[mdspan.layout.general]]</a>
858
 
859
- In subclauses [[mdspan.layout.reqmts]] and
860
- [[mdspan.layout.policy.reqmts]]:
861
 
862
  - `M` denotes a layout mapping class.
863
  - `m` denotes a (possibly const) value of type `M`.
864
  - `i` and `j` are packs of (possibly const) integers that are
865
  multidimensional indices in `m.extents()` [[mdspan.overview]].
@@ -868,19 +966,44 @@ In subclauses [[mdspan.layout.reqmts]] and
868
  - `r` is a (possibly const) rank index of `typename M::extents_type`.
869
  - `dᵣ` is a pack of (possibly const) integers for which
870
  `sizeof...(dᵣ) == M::extents_type::rank()` is `true`, the rᵗʰ element
871
  is equal to 1, and all other elements are equal to 0.
872
 
873
- In subclauses [[mdspan.layout.reqmts]] through [[mdspan.layout.stride]],
874
- let *`is-mapping-of`* be the exposition-only variable template defined
 
875
  as follows:
876
-
877
  ``` cpp
878
  template<class Layout, class Mapping>
879
  constexpr bool is-mapping-of = // exposition only
880
  is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
881
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
882
 
883
  ##### Requirements <a id="mdspan.layout.reqmts">[[mdspan.layout.reqmts]]</a>
884
 
885
  A type `M` meets the *layout mapping* requirements if
886
 
@@ -1004,20 +1127,24 @@ m.stride(r)
1004
 
1005
  *Result:* `typename M::index_type`
1006
 
1007
  *Returns:* sᵣ as defined in `m.is_strided()` above.
1008
 
 
 
 
 
1009
  ``` cpp
1010
  M::is_always_unique()
1011
  ```
1012
 
1013
  *Result:* A constant expression [[expr.const]] of type `bool`.
1014
 
1015
  *Returns:* `true` only if `m.is_unique()` is `true` for all possible
1016
  objects `m` of type `M`.
1017
 
1018
- [*Note 5*: A mapping can return `false` even if the above condition is
1019
  met. For certain layout mappings, it is possibly not feasible to
1020
  determine whether every instance is unique. — *end note*]
1021
 
1022
  ``` cpp
1023
  M::is_always_exhaustive()
@@ -1026,11 +1153,11 @@ M::is_always_exhaustive()
1026
  *Result:* A constant expression [[expr.const]] of type `bool`.
1027
 
1028
  *Returns:* `true` only if `m.is_exhaustive()` is `true` for all possible
1029
  objects `m` of type `M`.
1030
 
1031
- [*Note 6*: A mapping can return `false` even if the above condition is
1032
  met. For certain layout mappings, it is possibly not feasible to
1033
  determine whether every instance is exhaustive. — *end note*]
1034
 
1035
  ``` cpp
1036
  M::is_always_strided()
@@ -1039,11 +1166,11 @@ M::is_always_strided()
1039
  *Result:* A constant expression [[expr.const]] of type `bool`.
1040
 
1041
  *Returns:* `true` only if `m.is_strided()` is `true` for all possible
1042
  objects `m` of type `M`.
1043
 
1044
- [*Note 7*: A mapping can return `false` even if the above condition is
1045
  met. For certain layout mappings, it is possibly not feasible to
1046
  determine whether every instance is strided. — *end note*]
1047
 
1048
  ##### Layout mapping policy requirements <a id="mdspan.layout.policy.reqmts">[[mdspan.layout.policy.reqmts]]</a>
1049
 
@@ -1068,15 +1195,27 @@ namespace std {
1068
  };
1069
  struct layout_stride {
1070
  template<class Extents>
1071
  class mapping;
1072
  };
 
 
 
 
 
 
 
 
 
1073
  }
1074
  ```
1075
 
1076
- Each of `layout_left`, `layout_right`, and `layout_stride` meets the
1077
- layout mapping policy requirements and is a trivial type.
 
 
 
1078
 
1079
  ##### Class template `layout_left::mapping` <a id="mdspan.layout.left">[[mdspan.layout.left]]</a>
1080
 
1081
  ###### Overview <a id="mdspan.layout.left.overview">[[mdspan.layout.left.overview]]</a>
1082
 
@@ -1087,13 +1226,13 @@ stride 1, and strides increase left-to-right as the product of extents.
1087
  namespace std {
1088
  template<class Extents>
1089
  class layout_left::mapping {
1090
  public:
1091
  using extents_type = Extents;
1092
- using index_type = typename extents_type::index_type;
1093
- using size_type = typename extents_type::size_type;
1094
- using rank_type = typename extents_type::rank_type;
1095
  using layout_type = layout_left;
1096
 
1097
  // [mdspan.layout.left.cons], constructors
1098
  constexpr mapping() noexcept = default;
1099
  constexpr mapping(const mapping&) noexcept = default;
@@ -1102,10 +1241,14 @@ namespace std {
1102
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1103
  mapping(const mapping<OtherExtents>&) noexcept;
1104
  template<class OtherExtents>
1105
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1106
  mapping(const layout_right::mapping<OtherExtents>&) noexcept;
 
 
 
 
1107
  template<class OtherExtents>
1108
  constexpr explicit(extents_type::rank() > 0)
1109
  mapping(const layout_stride::mapping<OtherExtents>&);
1110
 
1111
  constexpr mapping& operator=(const mapping&) noexcept = default;
@@ -1131,10 +1274,21 @@ namespace std {
1131
  template<class OtherExtents>
1132
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
1133
 
1134
  private:
1135
  extents_type extents_{}; // exposition only
 
 
 
 
 
 
 
 
 
 
 
1136
  };
1137
  }
1138
  ```
1139
 
1140
  If `Extents` is not a specialization of `extents`, then the program is
@@ -1172,11 +1326,11 @@ value of type `index_type` [[basic.fundamental]].
1172
 
1173
  *Effects:* Direct-non-list-initializes *extents\_* with
1174
  `other.extents()`.
1175
 
1176
  ``` cpp
1177
- template<class OtherExents>
1178
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1179
  mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
1180
  ```
1181
 
1182
  *Constraints:*
@@ -1188,10 +1342,44 @@ template<class OtherExents>
1188
  value of type `index_type` [[basic.fundamental]].
1189
 
1190
  *Effects:* Direct-non-list-initializes *extents\_* with
1191
  `other.extents()`.
1192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1193
  ``` cpp
1194
  template<class OtherExtents>
1195
  constexpr explicit(extents_type::rank() > 0)
1196
  mapping(const layout_stride::mapping<OtherExtents>& other);
1197
  ```
@@ -1243,11 +1431,11 @@ is `true`. Equivalent to:
1243
  ``` cpp
1244
  return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
1245
  ```
1246
 
1247
  ``` cpp
1248
- constexpr index_type stride(rank_type i) const;
1249
  ```
1250
 
1251
  *Constraints:* `extents_type::rank() > 0` is `true`.
1252
 
1253
  *Preconditions:* `i < extents_type::rank()` is `true`.
@@ -1274,13 +1462,13 @@ stride 1, and strides increase right-to-left as the product of extents.
1274
  namespace std {
1275
  template<class Extents>
1276
  class layout_right::mapping {
1277
  public:
1278
  using extents_type = Extents;
1279
- using index_type = typename extents_type::index_type;
1280
- using size_type = typename extents_type::size_type;
1281
- using rank_type = typename extents_type::rank_type;
1282
  using layout_type = layout_right;
1283
 
1284
  // [mdspan.layout.right.cons], constructors
1285
  constexpr mapping() noexcept = default;
1286
  constexpr mapping(const mapping&) noexcept = default;
@@ -1289,10 +1477,14 @@ namespace std {
1289
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1290
  mapping(const mapping<OtherExtents>&) noexcept;
1291
  template<class OtherExtents>
1292
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1293
  mapping(const layout_left::mapping<OtherExtents>&) noexcept;
 
 
 
 
1294
  template<class OtherExtents>
1295
  constexpr explicit(extents_type::rank() > 0)
1296
  mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
1297
 
1298
  constexpr mapping& operator=(const mapping&) noexcept = default;
@@ -1318,10 +1510,21 @@ namespace std {
1318
  template<class OtherExtents>
1319
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
1320
 
1321
  private:
1322
  extents_type extents_{}; // exposition only
 
 
 
 
 
 
 
 
 
 
 
1323
  };
1324
  }
1325
  ```
1326
 
1327
  If `Extents` is not a specialization of `extents`, then the program is
@@ -1375,10 +1578,46 @@ template<class OtherExtents>
1375
  value of type `index_type` [[basic.fundamental]].
1376
 
1377
  *Effects:* Direct-non-list-initializes *extents\_* with
1378
  `other.extents()`.
1379
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1380
  ``` cpp
1381
  template<class OtherExtents>
1382
  constexpr explicit(extents_type::rank() > 0)
1383
  mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
1384
  ```
@@ -1398,11 +1637,11 @@ template<class OtherExtents>
1398
  `other.extents()`.
1399
 
1400
  ###### Observers <a id="mdspan.layout.right.obs">[[mdspan.layout.right.obs]]</a>
1401
 
1402
  ``` cpp
1403
- index_type required_span_size() const noexcept;
1404
  ```
1405
 
1406
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
1407
 
1408
  ``` cpp
@@ -1461,13 +1700,13 @@ user-defined.
1461
  namespace std {
1462
  template<class Extents>
1463
  class layout_stride::mapping {
1464
  public:
1465
  using extents_type = Extents;
1466
- using index_type = typename extents_type::index_type;
1467
- using size_type = typename extents_type::size_type;
1468
- using rank_type = typename extents_type::rank_type;
1469
  using layout_type = layout_stride;
1470
 
1471
  private:
1472
  static constexpr rank_type rank_ = extents_type::rank(); // exposition only
1473
 
@@ -1508,10 +1747,21 @@ namespace std {
1508
  friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
1509
 
1510
  private:
1511
  extents_type extents_{}; // exposition only
1512
  array<index_type, rank_> strides_{}; // exposition only
 
 
 
 
 
 
 
 
 
 
 
1513
  };
1514
  }
1515
  ```
1516
 
1517
  If `Extents` is not a specialization of `extents`, then the program is
@@ -1530,11 +1780,15 @@ Let `REQUIRED-SPAN-SIZE(e, strides)` be:
1530
 
1531
  - `1`, if `e.rank() == 0` is `true`,
1532
  - otherwise `0`, if the size of the multidimensional index space `e` is
1533
  0,
1534
  - otherwise `1` plus the sum of products of `(e.extent(r) - 1)` and
1535
- `strides[r]` for all r in the range [0, `e.rank()`).
 
 
 
 
1536
 
1537
  Let `OFFSET(m)` be:
1538
 
1539
  - `m()`, if `e.rank() == 0` is `true`,
1540
  - otherwise `0`, if the size of the multidimensional index space `e` is
@@ -1602,11 +1856,12 @@ template<class OtherIndexType>
1602
  - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
1603
  `true`.
1604
 
1605
  *Preconditions:*
1606
 
1607
- - `s[`i`] > 0` is `true` for all i in the range [0, rank_).
 
1608
  - *`REQUIRED-SPAN-SIZE`*`(e, s)` is representable as a value of type
1609
  `index_type` [[basic.fundamental]].
1610
  - If *rank\_* is greater than 0, then there exists a permutation P of
1611
  the integers in the range [0, rank_), such that
1612
  `s[`pᵢ`] >= s[`pᵢ₋₁`] * e.extent(p`ᵢ₋₁`)` is `true` for all i in the
@@ -1634,11 +1889,11 @@ template<class StridedLayoutMapping>
1634
  - `StridedLayoutMapping::is_always_strided()` is `true`.
1635
 
1636
  *Preconditions:*
1637
 
1638
  - `StridedLayoutMapping` meets the layout mapping
1639
- requirements [[mdspan.layout.policy.reqmts]],
1640
  - `other.stride(`r`) > 0` is `true` for every rank index r of
1641
  `extents()`,
1642
  - `other.required_span_size()` is representable as a value of type
1643
  `index_type` [[basic.fundamental]], and
1644
  - *`OFFSET`*`(other) == 0` is `true`.
@@ -1650,13 +1905,15 @@ direct-non-list-initializes *`strides_`*`[`d`]` with
1650
 
1651
  Remarks: The expression inside `explicit` is equivalent to:
1652
 
1653
  ``` cpp
1654
  !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
1655
- (is-mapping-of<layout_left, LayoutStrideMapping> ||
1656
- is-mapping-of<layout_right, LayoutStrideMapping> ||
1657
- is-mapping-of<layout_stride, LayoutStrideMapping>))
 
 
1658
  ```
1659
 
1660
  ###### Observers <a id="mdspan.layout.stride.obs">[[mdspan.layout.stride.obs]]</a>
1661
 
1662
  ``` cpp
@@ -1721,10 +1978,898 @@ requirements [[mdspan.layout.policy.reqmts]].
1721
  *Returns:* `true` if `x.extents() == y.extents()` is `true`,
1722
  *`OFFSET`*`(y) == 0` is `true`, and each of
1723
  `x.stride(`r`) == y.stride(`r`)` is `true` for r in the range
1724
  [0, `x.extents().rank()`). Otherwise, `false`.
1725
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1726
  #### Accessor policy <a id="mdspan.accessor">[[mdspan.accessor]]</a>
1727
 
1728
  ##### General <a id="mdspan.accessor.general">[[mdspan.accessor.general]]</a>
1729
 
1730
  An *accessor policy* defines types and operations by which a reference
@@ -1733,11 +2878,11 @@ of such objects and an index.
1733
 
1734
  A range of indices [0, N) is an *accessible range* of a given data
1735
  handle and an accessor if, for each i in the range, the accessor
1736
  policy’s `access` function produces a valid reference to an object.
1737
 
1738
- In subclause [[mdspan.accessor.reqmts]],
1739
 
1740
  - `A` denotes an accessor policy.
1741
  - `a` denotes a value of type `A` or `const A`.
1742
  - `p` denotes a value of type `A::data_handle_type` or
1743
  `const A::data_handle_type`. \[*Note 1*: The type
@@ -1877,10 +3022,155 @@ constexpr reference access(data_handle_type p, size_t i) const noexcept;
1877
  constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
1878
  ```
1879
 
1880
  *Effects:* Equivalent to: `return p + i;`
1881
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1882
  #### Class template `mdspan` <a id="mdspan.mdspan">[[mdspan.mdspan]]</a>
1883
 
1884
  ##### Overview <a id="mdspan.mdspan.overview">[[mdspan.mdspan.overview]]</a>
1885
 
1886
  `mdspan` is a view of a multidimensional array of elements.
@@ -1892,18 +3182,18 @@ namespace std {
1892
  class mdspan {
1893
  public:
1894
  using extents_type = Extents;
1895
  using layout_type = LayoutPolicy;
1896
  using accessor_type = AccessorPolicy;
1897
- using mapping_type = typename layout_type::template mapping<extents_type>;
1898
  using element_type = ElementType;
1899
  using value_type = remove_cv_t<element_type>;
1900
- using index_type = typename extents_type::index_type;
1901
- using size_type = typename extents_type::size_type;
1902
- using rank_type = typename extents_type::rank_type;
1903
- using data_handle_type = typename accessor_type::data_handle_type;
1904
- using reference = typename accessor_type::reference;
1905
 
1906
  static constexpr rank_type rank() noexcept { return extents_type::rank(); }
1907
  static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
1908
  static constexpr size_t static_extent(rank_type r) noexcept
1909
  { return extents_type::static_extent(r); }
@@ -1941,12 +3231,22 @@ namespace std {
1941
  template<class OtherIndexType>
1942
  constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
1943
  template<class OtherIndexType>
1944
  constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
1945
 
 
 
 
 
 
 
 
 
 
 
1946
  constexpr size_type size() const noexcept;
1947
- [[nodiscard]] constexpr bool empty() const noexcept;
1948
 
1949
  friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
1950
 
1951
  constexpr const extents_type& extents() const noexcept { return map_.extents(); }
1952
  constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
@@ -1986,11 +3286,11 @@ namespace std {
1986
  -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
1987
 
1988
  template<class ElementType, class... Integrals>
1989
  requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
1990
  explicit mdspan(ElementType*, Integrals...)
1991
- -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
1992
 
1993
  template<class ElementType, class OtherIndexType, size_t N>
1994
  mdspan(ElementType*, span<OtherIndexType, N>)
1995
  -> mdspan<ElementType, dextents<size_t, N>>;
1996
 
@@ -2093,12 +3393,12 @@ template<class OtherIndexType, size_t N>
2093
  ```
2094
 
2095
  *Constraints:*
2096
 
2097
  - `is_convertible_v<const OtherIndexType&, index_type>` is `true`,
2098
- - `(is_nothrow_constructible<index_type, const OtherIndexType&> && ...)`
2099
- is `true`,
2100
  - `N == rank() || N == rank_dynamic()` is `true`,
2101
  - `is_constructible_v<mapping_type, extents_type>` is `true`, and
2102
  - `is_default_constructible_v<accessor_type>` is `true`.
2103
 
2104
  *Preconditions:* $[0, \texttt{\textit{map_}.required_span_size()})$ is
@@ -2177,18 +3477,17 @@ template<class OtherElementType, class OtherExtents,
2177
 
2178
  - `is_constructible_v<data_handle_type, const OtherAccessor::data_handle_type&>`
2179
  is `true`, and
2180
  - `is_constructible_v<extents_type, OtherExtents>` is `true`.
2181
 
2182
- *Preconditions:*
 
 
2183
 
2184
- - For each rank index `r` of `extents_type`,
2185
  `static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)`
2186
  is `true`.
2187
- - $[0, \texttt{\textit{map_}.required_span_size()})$ is an accessible
2188
- range of *ptr\_* and *acc\_* for values of *ptr\_*, *map\_*, and
2189
- *acc\_* after the invocation of this constructor.
2190
 
2191
  *Effects:*
2192
 
2193
  - Direct-non-list-initializes *ptr\_* with `other.`*`ptr_`*,
2194
  - direct-non-list-initializes *map\_* with `other.`*`map_`*, and
@@ -2215,11 +3514,11 @@ template<class... OtherIndexTypes>
2215
  `true`, and
2216
  - `sizeof...(OtherIndexTypes) == rank()` is `true`.
2217
 
2218
  Let `I` be `extents_type::`*`index-cast`*`(std::move(indices))`.
2219
 
2220
- *Preconditions:* `I` is a multidimensional index in `extents()`.
2221
 
2222
  [*Note 1*: This implies that
2223
  *`map_`*`(I) < `*`map_`*`.required_span_size()` is
2224
  `true`. — *end note*]
2225
 
@@ -2249,11 +3548,55 @@ is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
2249
  ```
2250
 
2251
  is `true`. Equivalent to:
2252
 
2253
  ``` cpp
2254
- return operator[](as_const(indices[P])...);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2255
  ```
2256
 
2257
  ``` cpp
2258
  constexpr size_type size() const noexcept;
2259
  ```
@@ -2263,11 +3606,11 @@ constexpr size_type size() const noexcept;
2263
  [[basic.fundamental]].
2264
 
2265
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(rank())`.
2266
 
2267
  ``` cpp
2268
- [[nodiscard]] constexpr bool empty() const noexcept;
2269
  ```
2270
 
2271
  *Returns:* `true` if the size of the multidimensional index space
2272
  `extents()` is 0, otherwise `false`.
2273
 
@@ -2281,10 +3624,599 @@ friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
2281
  swap(x.ptr_, y.ptr_);
2282
  swap(x.map_, y.map_);
2283
  swap(x.acc_, y.acc_);
2284
  ```
2285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2286
  <!-- Link reference definitions -->
2287
  [alg.equal]: algorithms.md#alg.equal
2288
  [alg.sorting]: algorithms.md#alg.sorting
2289
  [algorithm.stable]: library.md#algorithm.stable
2290
  [algorithms]: algorithms.md#algorithms
@@ -2308,20 +4240,21 @@ swap(x.acc_, y.acc_);
2308
  [associative.reqmts]: #associative.reqmts
2309
  [associative.reqmts.except]: #associative.reqmts.except
2310
  [associative.reqmts.general]: #associative.reqmts.general
2311
  [associative.set.syn]: #associative.set.syn
2312
  [basic.fundamental]: basic.md#basic.fundamental
 
2313
  [basic.string]: strings.md#basic.string
2314
  [class.copy.ctor]: class.md#class.copy.ctor
2315
  [class.default.ctor]: class.md#class.default.ctor
2316
  [class.dtor]: class.md#class.dtor
2317
  [container.adaptors]: #container.adaptors
2318
  [container.adaptors.format]: #container.adaptors.format
2319
  [container.adaptors.general]: #container.adaptors.general
2320
  [container.alloc.reqmts]: #container.alloc.reqmts
2321
- [container.gen.reqmts]: #container.gen.reqmts
2322
  [container.insert.return]: #container.insert.return
 
2323
  [container.node]: #container.node
2324
  [container.node.compat]: #container.node.compat
2325
  [container.node.cons]: #container.node.cons
2326
  [container.node.dtor]: #container.node.dtor
2327
  [container.node.modifiers]: #container.node.modifiers
@@ -2349,28 +4282,32 @@ swap(x.acc_, y.acc_);
2349
  [expr.const]: expr.md#expr.const
2350
  [flat.map]: #flat.map
2351
  [flat.map.access]: #flat.map.access
2352
  [flat.map.capacity]: #flat.map.capacity
2353
  [flat.map.cons]: #flat.map.cons
 
2354
  [flat.map.defn]: #flat.map.defn
2355
  [flat.map.erasure]: #flat.map.erasure
2356
  [flat.map.modifiers]: #flat.map.modifiers
2357
  [flat.map.overview]: #flat.map.overview
2358
  [flat.map.syn]: #flat.map.syn
2359
  [flat.multimap]: #flat.multimap
2360
  [flat.multimap.cons]: #flat.multimap.cons
 
2361
  [flat.multimap.defn]: #flat.multimap.defn
2362
  [flat.multimap.erasure]: #flat.multimap.erasure
2363
  [flat.multimap.overview]: #flat.multimap.overview
2364
  [flat.multiset]: #flat.multiset
2365
  [flat.multiset.cons]: #flat.multiset.cons
 
2366
  [flat.multiset.defn]: #flat.multiset.defn
2367
  [flat.multiset.erasure]: #flat.multiset.erasure
2368
  [flat.multiset.modifiers]: #flat.multiset.modifiers
2369
  [flat.multiset.overview]: #flat.multiset.overview
2370
  [flat.set]: #flat.set
2371
  [flat.set.cons]: #flat.set.cons
 
2372
  [flat.set.defn]: #flat.set.defn
2373
  [flat.set.erasure]: #flat.set.erasure
2374
  [flat.set.modifiers]: #flat.set.modifiers
2375
  [flat.set.overview]: #flat.set.overview
2376
  [flat.set.syn]: #flat.set.syn
@@ -2383,10 +4320,26 @@ swap(x.acc_, y.acc_);
2383
  [forward.list.modifiers]: #forward.list.modifiers
2384
  [forward.list.ops]: #forward.list.ops
2385
  [forward.list.overview]: #forward.list.overview
2386
  [forward.list.syn]: #forward.list.syn
2387
  [hash.requirements]: library.md#hash.requirements
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2388
  [iterator.concept.contiguous]: iterators.md#iterator.concept.contiguous
2389
  [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
2390
  [iterator.requirements]: iterators.md#iterator.requirements
2391
  [iterator.requirements.general]: iterators.md#iterator.requirements.general
2392
  [list]: #list
@@ -2402,45 +4355,73 @@ swap(x.acc_, y.acc_);
2402
  [map.cons]: #map.cons
2403
  [map.erasure]: #map.erasure
2404
  [map.modifiers]: #map.modifiers
2405
  [map.overview]: #map.overview
2406
  [mdspan.accessor]: #mdspan.accessor
 
 
 
2407
  [mdspan.accessor.default]: #mdspan.accessor.default
2408
  [mdspan.accessor.default.members]: #mdspan.accessor.default.members
2409
  [mdspan.accessor.default.overview]: #mdspan.accessor.default.overview
2410
  [mdspan.accessor.general]: #mdspan.accessor.general
2411
  [mdspan.accessor.reqmts]: #mdspan.accessor.reqmts
2412
  [mdspan.extents]: #mdspan.extents
2413
  [mdspan.extents.cmp]: #mdspan.extents.cmp
2414
  [mdspan.extents.cons]: #mdspan.extents.cons
2415
  [mdspan.extents.dextents]: #mdspan.extents.dextents
 
2416
  [mdspan.extents.expo]: #mdspan.extents.expo
2417
  [mdspan.extents.obs]: #mdspan.extents.obs
2418
  [mdspan.extents.overview]: #mdspan.extents.overview
2419
  [mdspan.layout]: #mdspan.layout
2420
  [mdspan.layout.general]: #mdspan.layout.general
2421
  [mdspan.layout.left]: #mdspan.layout.left
2422
  [mdspan.layout.left.cons]: #mdspan.layout.left.cons
2423
  [mdspan.layout.left.obs]: #mdspan.layout.left.obs
2424
  [mdspan.layout.left.overview]: #mdspan.layout.left.overview
 
 
 
 
 
2425
  [mdspan.layout.policy.overview]: #mdspan.layout.policy.overview
2426
  [mdspan.layout.policy.reqmts]: #mdspan.layout.policy.reqmts
2427
  [mdspan.layout.reqmts]: #mdspan.layout.reqmts
2428
  [mdspan.layout.right]: #mdspan.layout.right
2429
  [mdspan.layout.right.cons]: #mdspan.layout.right.cons
2430
  [mdspan.layout.right.obs]: #mdspan.layout.right.obs
2431
  [mdspan.layout.right.overview]: #mdspan.layout.right.overview
 
 
 
 
 
2432
  [mdspan.layout.stride]: #mdspan.layout.stride
2433
  [mdspan.layout.stride.cons]: #mdspan.layout.stride.cons
2434
  [mdspan.layout.stride.expo]: #mdspan.layout.stride.expo
2435
  [mdspan.layout.stride.obs]: #mdspan.layout.stride.obs
2436
  [mdspan.layout.stride.overview]: #mdspan.layout.stride.overview
2437
  [mdspan.mdspan]: #mdspan.mdspan
2438
  [mdspan.mdspan.cons]: #mdspan.mdspan.cons
2439
  [mdspan.mdspan.members]: #mdspan.mdspan.members
2440
  [mdspan.mdspan.overview]: #mdspan.mdspan.overview
2441
  [mdspan.overview]: #mdspan.overview
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2442
  [mdspan.syn]: #mdspan.syn
2443
  [multimap]: #multimap
2444
  [multimap.cons]: #multimap.cons
2445
  [multimap.erasure]: #multimap.erasure
2446
  [multimap.modifiers]: #multimap.modifiers
@@ -2462,17 +4443,19 @@ swap(x.acc_, y.acc_);
2462
  [queue.mod]: #queue.mod
2463
  [queue.ops]: #queue.ops
2464
  [queue.special]: #queue.special
2465
  [queue.syn]: #queue.syn
2466
  [random.access.iterators]: iterators.md#random.access.iterators
 
2467
  [res.on.data.races]: library.md#res.on.data.races
2468
  [sequence.reqmts]: #sequence.reqmts
2469
  [sequences]: #sequences
2470
  [sequences.general]: #sequences.general
2471
  [set]: #set
2472
  [set.cons]: #set.cons
2473
  [set.erasure]: #set.erasure
 
2474
  [set.overview]: #set.overview
2475
  [span.cons]: #span.cons
2476
  [span.deduct]: #span.deduct
2477
  [span.elem]: #span.elem
2478
  [span.iterators]: #span.iterators
@@ -2488,15 +4471,16 @@ swap(x.acc_, y.acc_);
2488
  [stack.general]: #stack.general
2489
  [stack.mod]: #stack.mod
2490
  [stack.ops]: #stack.ops
2491
  [stack.special]: #stack.special
2492
  [stack.syn]: #stack.syn
 
2493
  [strings]: strings.md#strings
2494
  [swappable.requirements]: library.md#swappable.requirements
2495
  [temp.deduct]: temp.md#temp.deduct
2496
- [temp.param]: temp.md#temp.param
2497
  [temp.type]: temp.md#temp.type
 
2498
  [term.trivially.copyable.type]: basic.md#term.trivially.copyable.type
2499
  [unord]: #unord
2500
  [unord.general]: #unord.general
2501
  [unord.hash]: utilities.md#unord.hash
2502
  [unord.map]: #unord.map
@@ -2519,10 +4503,11 @@ swap(x.acc_, y.acc_);
2519
  [unord.req.except]: #unord.req.except
2520
  [unord.req.general]: #unord.req.general
2521
  [unord.set]: #unord.set
2522
  [unord.set.cnstr]: #unord.set.cnstr
2523
  [unord.set.erasure]: #unord.set.erasure
 
2524
  [unord.set.overview]: #unord.set.overview
2525
  [unord.set.syn]: #unord.set.syn
2526
  [vector]: #vector
2527
  [vector.bool]: #vector.bool
2528
  [vector.bool.fmt]: #vector.bool.fmt
 
9
  ### Contiguous access <a id="views.contiguous">[[views.contiguous]]</a>
10
 
11
  #### Header `<span>` synopsis <a id="span.syn">[[span.syn]]</a>
12
 
13
  ``` cpp
14
+ #include <initializer_list> // see [initializer.list.syn]
15
+
16
+ // mostly freestanding
17
  namespace std {
18
  // constants
19
  inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
20
 
21
+ template<class T>
22
+ concept integral-constant-like = // exposition only
23
+ is_integral_v<remove_cvref_t<decltype(T::value)>> &&
24
+ !is_same_v<bool, remove_const_t<decltype(T::value)>> &&
25
+ convertible_to<T, decltype(T::value)> &&
26
+ equality_comparable_with<T, decltype(T::value)> &&
27
+ bool_constant<T() == T::value>::value &&
28
+ bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
29
+
30
+ template<class T>
31
+ constexpr size_t maybe-static-ext = dynamic_extent; // exposition only
32
+ template<integral-constant-like T>
33
+ constexpr size_t maybe-static-ext<T> = {T::value};
34
+
35
  // [views.span], class template span
36
  template<class ElementType, size_t Extent = dynamic_extent>
37
+ class span; // partially freestanding
38
 
39
  template<class ElementType, size_t Extent>
40
+ constexpr bool ranges::\libspec{enable_view}{span}<span<ElementType, Extent>> = true;
41
  template<class ElementType, size_t Extent>
42
+ constexpr bool ranges::\libspec{enable_borrowed_range}{span}<span<ElementType, Extent>> = true;
43
 
44
  // [span.objectrep], views of object representation
45
  template<class ElementType, size_t Extent>
46
  span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
47
  as_bytes(span<ElementType, Extent> s) noexcept;
 
93
  constexpr span(array<T, N>& arr) noexcept;
94
  template<class T, size_t N>
95
  constexpr span(const array<T, N>& arr) noexcept;
96
  template<class R>
97
  constexpr explicit(extent != dynamic_extent) span(R&& r);
98
+ constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);
99
  constexpr span(const span& other) noexcept = default;
100
  template<class OtherElementType, size_t OtherExtent>
101
  constexpr explicit(see below) span(const span<OtherElementType, OtherExtent>& s) noexcept;
102
 
 
 
103
  constexpr span& operator=(const span& other) noexcept = default;
104
 
105
  // [span.sub], subviews
106
  template<size_t Count>
107
  constexpr span<element_type, Count> first() const;
 
116
  size_type offset, size_type count = dynamic_extent) const;
117
 
118
  // [span.obs], observers
119
  constexpr size_type size() const noexcept;
120
  constexpr size_type size_bytes() const noexcept;
121
+ constexpr bool empty() const noexcept;
122
 
123
  // [span.elem], element access
124
  constexpr reference operator[](size_type idx) const;
125
+ constexpr reference at(size_type idx) const; // freestanding-deleted
126
  constexpr reference front() const;
127
  constexpr reference back() const;
128
  constexpr pointer data() const noexcept;
129
 
130
  // [span.iterators], iterator support
 
141
  pointer data_; // exposition only
142
  size_type size_; // exposition only
143
  };
144
 
145
  template<class It, class EndOrSize>
146
+ span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,
147
+ maybe-static-ext<EndOrSize>>;
148
  template<class T, size_t N>
149
  span(T (&)[N]) -> span<T, N>;
150
  template<class T, size_t N>
151
  span(array<T, N>&) -> span<T, N>;
152
  template<class T, size_t N>
 
160
  [[term.trivially.copyable.type]].
161
 
162
  `ElementType` is required to be a complete object type that is not an
163
  abstract class type.
164
 
165
+ For a `span` `s`, any operation that invalidates a pointer in the range
166
+ \[`s.data()`, `s.data() + s.size()`) invalidates pointers, iterators,
167
+ and references to elements of `s`.
168
+
169
  ##### Constructors, copy, and assignment <a id="span.cons">[[span.cons]]</a>
170
 
171
  ``` cpp
172
  constexpr span() noexcept;
173
  ```
 
190
 
191
  *Preconditions:*
192
 
193
  - \[`first`, `first + count`) is a valid range.
194
  - `It` models `contiguous_iterator`.
 
 
195
 
196
+ If `extent` is not equal to `dynamic_extent`, then `count == extent` is
197
+ `true`.
198
+
199
+ *Effects:* Initializes *data\_* with `to_address(first)` and *size\_*
200
  with `count`.
201
 
202
  *Throws:* Nothing.
203
 
204
  ``` cpp
 
215
  - `End` satisfies `sized_sentinel_for<It>`.
216
  - `is_convertible_v<End, size_t>` is `false`.
217
 
218
  *Preconditions:*
219
 
 
 
220
  - \[`first`, `last`) is a valid range.
221
  - `It` models `contiguous_iterator`.
222
  - `End` models `sized_sentinel_for<It>`.
223
 
224
+ If `extent` is not equal to `dynamic_extent`, then
225
+ `(last - first) == extent` is `true`.
226
+
227
+ *Effects:* Initializes *data\_* with `to_address(first)` and *size\_*
228
  with `last - first`.
229
 
230
  *Throws:* When and what `last - first` throws.
231
 
232
  ``` cpp
233
  template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;
234
  template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept;
235
  template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;
236
  ```
237
 
238
+ *Constraints:* Let `U` be `remove_pointer_t<decltype(std::data(arr))>`.
239
 
240
  - `extent == dynamic_extent || N == extent` is `true`, and
241
  - `is_convertible_v<U(*)[], element_type(*)[]>` is `true`.
242
  \[*Note 3*: The intent is to allow only qualification conversions of
243
  the array element type to `element_type`. — *end note*]
 
245
  *Effects:* Constructs a `span` that is a view over the supplied array.
246
 
247
  [*Note 1*: `type_identity_t` affects class template argument
248
  deduction. — *end note*]
249
 
250
+ *Ensures:* `size() == N && data() == std::data(arr)` is `true`.
251
 
252
  ``` cpp
253
  template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);
254
  ```
255
 
 
266
  \[*Note 4*: The intent is to allow only qualification conversions of
267
  the range reference type to `element_type`. — *end note*]
268
 
269
  *Preconditions:*
270
 
 
 
271
  - `R` models `ranges::contiguous_range` and `ranges::sized_range`.
272
  - If `is_const_v<element_type>` is `false`, `R` models
273
  `ranges::borrowed_range`.
274
 
275
+ If `extent` is not equal to `dynamic_extent`, then
276
+ `ranges::size(r) == extent` is `true`.
277
+
278
+ *Effects:* Initializes *data\_* with `ranges::data(r)` and *size\_* with
279
+ `ranges::size(r)`.
280
 
281
  *Throws:* What and when `ranges::data(r)` and `ranges::size(r)` throw.
282
 
283
+ ``` cpp
284
+ constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);
285
+ ```
286
+
287
+ *Constraints:* `is_const_v<element_type>` is `true`.
288
+
289
+ If `extent` is not equal to `dynamic_extent`, then `il.size() == extent`
290
+ is `true`.
291
+
292
+ *Effects:* Initializes *data\_* with `il.begin()` and *size\_* with
293
+ `il.size()`.
294
+
295
  ``` cpp
296
  constexpr span(const span& other) noexcept = default;
297
  ```
298
 
299
  *Ensures:* `other.size() == size() && other.data() == data()`.
 
310
  - `is_convertible_v<OtherElementType(*)[], element_type(*)[]>` is
311
  `true`. \[*Note 5*: The intent is to allow only qualification
312
  conversions of the `OtherElementType` to
313
  `element_type`. — *end note*]
314
 
315
+ If `extent` is not equal to `dynamic_extent`, then `s.size() == extent`
316
+ is `true`.
317
 
318
  *Effects:* Constructs a `span` that is a view over the range
319
  \[`s.data()`, `s.data() + s.size()`).
320
 
321
  *Ensures:* `size() == s.size() && data() == s.data()`.
 
334
 
335
  ##### Deduction guides <a id="span.deduct">[[span.deduct]]</a>
336
 
337
  ``` cpp
338
  template<class It, class EndOrSize>
339
+ span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,
340
+ maybe-static-ext<EndOrSize>>;
341
  ```
342
 
343
  *Constraints:* `It` satisfies `contiguous_iterator`.
344
 
345
  ``` cpp
 
355
  template<size_t Count> constexpr span<element_type, Count> first() const;
356
  ```
357
 
358
  *Mandates:* `Count <= Extent` is `true`.
359
 
360
+ `Count <= size()` is `true`.
361
 
362
  *Effects:* Equivalent to: `return R{data(), Count};` where `R` is the
363
  return type.
364
 
365
  ``` cpp
366
  template<size_t Count> constexpr span<element_type, Count> last() const;
367
  ```
368
 
369
  *Mandates:* `Count <= Extent` is `true`.
370
 
371
+ `Count <= size()` is `true`.
372
 
373
  *Effects:* Equivalent to: `return R{data() + (size() - Count), Count};`
374
  where `R` is the return type.
375
 
376
  ``` cpp
 
384
  Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset)
385
  ```
386
 
387
  is `true`.
388
 
 
 
389
  ``` cpp
390
  Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset)
391
  ```
392
 
393
  is `true`.
 
409
 
410
  ``` cpp
411
  constexpr span<element_type, dynamic_extent> first(size_type count) const;
412
  ```
413
 
414
+ `count <= size()` is `true`.
415
 
416
  *Effects:* Equivalent to: `return {data(), count};`
417
 
418
  ``` cpp
419
  constexpr span<element_type, dynamic_extent> last(size_type count) const;
420
  ```
421
 
422
+ `count <= size()` is `true`.
423
 
424
  *Effects:* Equivalent to: `return {data() + (size() - count), count};`
425
 
426
  ``` cpp
427
  constexpr span<element_type, dynamic_extent> subspan(
428
  size_type offset, size_type count = dynamic_extent) const;
429
  ```
430
 
 
 
431
  ``` cpp
432
  offset <= size() && (count == dynamic_extent || count <= size() - offset)
433
  ```
434
 
435
  is `true`.
 
453
  ```
454
 
455
  *Effects:* Equivalent to: `return size() * sizeof(element_type);`
456
 
457
  ``` cpp
458
+ constexpr bool empty() const noexcept;
459
  ```
460
 
461
  *Effects:* Equivalent to: `return size() == 0;`
462
 
463
  ##### Element access <a id="span.elem">[[span.elem]]</a>
464
 
465
  ``` cpp
466
  constexpr reference operator[](size_type idx) const;
467
  ```
468
 
469
+ `idx < size()` is `true`.
470
 
471
+ *Returns:* `*(data() + idx)`.
472
+
473
+ *Throws:* Nothing.
474
+
475
+ ``` cpp
476
+ constexpr reference at(size_type idx) const;
477
+ ```
478
+
479
+ *Returns:* `*(data() + idx)`.
480
+
481
+ *Throws:* `out_of_range` if `idx >= size()` is `true`.
482
 
483
  ``` cpp
484
  constexpr reference front() const;
485
  ```
486
 
487
+ `empty()` is `false`.
488
 
489
+ *Returns:* `*data()`.
490
+
491
+ *Throws:* Nothing.
492
 
493
  ``` cpp
494
  constexpr reference back() const;
495
  ```
496
 
497
+ `empty()` is `false`.
498
 
499
+ *Returns:* `*(data() + (size() - 1))`.
500
+
501
+ *Throws:* Nothing.
502
 
503
  ``` cpp
504
  constexpr pointer data() const noexcept;
505
  ```
506
 
507
+ *Returns:* *data\_*.
508
 
509
  ##### Iterator support <a id="span.iterators">[[span.iterators]]</a>
510
 
511
  ``` cpp
512
  using iterator = implementation-defined // type of span::iterator;
 
594
  the interval [Lᵢ, Uᵢ) of S.
595
 
596
  #### Header `<mdspan>` synopsis <a id="mdspan.syn">[[mdspan.syn]]</a>
597
 
598
  ``` cpp
599
+ // mostly freestanding
600
  namespace std {
601
  // [mdspan.extents], class template extents
602
  template<class IndexType, size_t... Extents>
603
  class extents;
604
 
605
  // [mdspan.extents.dextents], alias template dextents
606
  template<class IndexType, size_t Rank>
607
  using dextents = see below;
608
 
609
+ // [mdspan.extents.dims], alias template dims
610
+ template<size_t Rank, class IndexType = size_t>
611
+ using dims = see below;
612
+
613
  // [mdspan.layout], layout mapping
614
  struct layout_left;
615
  struct layout_right;
616
  struct layout_stride;
617
+ template<size_t PaddingValue = dynamic_extent>
618
+ struct layout_left_padded;
619
+ template<size_t PaddingValue = dynamic_extent>
620
+ struct layout_right_padded;
621
 
622
  // [mdspan.accessor.default], class template default_accessor
623
  template<class ElementType>
624
  class default_accessor;
625
 
626
+ // [mdspan.accessor.aligned], class template aligned_accessor
627
+ template<class ElementType, size_t ByteAlignment>
628
+ class aligned_accessor;
629
+
630
  // [mdspan.mdspan], class template mdspan
631
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
632
  class AccessorPolicy = default_accessor<ElementType>>
633
+ class mdspan; // partially freestanding
634
+
635
+ // [mdspan.sub], submdspan creation
636
+ template<class OffsetType, class LengthType, class StrideType>
637
+ struct strided_slice;
638
+
639
+ template<class LayoutMapping>
640
+ struct submdspan_mapping_result;
641
+
642
+ struct full_extent_t { explicit full_extent_t() = default; };
643
+ inline constexpr full_extent_t full_extent{};
644
+
645
+ template<class IndexType, size_t... Extents, class... SliceSpecifiers>
646
+ constexpr auto submdspan_extents(const extents<IndexType, Extents...>&, SliceSpecifiers...);
647
+
648
+ // [mdspan.sub.sub], submdspan function template
649
+ template<class ElementType, class Extents, class LayoutPolicy,
650
+ class AccessorPolicy, class... SliceSpecifiers>
651
+ constexpr auto submdspan(
652
+ const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
653
+ SliceSpecifiers... slices) -> see below;
654
+
655
+ template<class T, class IndexType>
656
+ concept index-pair-like = // exposition only
657
+ pair-like<T> &&
658
+ convertible_to<tuple_element_t<0, T>, IndexType> &&
659
+ convertible_to<tuple_element_t<1, T>, IndexType>;
660
  }
661
  ```
662
 
663
  #### Class template `extents` <a id="mdspan.extents">[[mdspan.extents]]</a>
664
 
665
  ##### Overview <a id="mdspan.extents.overview">[[mdspan.extents.overview]]</a>
666
 
667
  The class template `extents` represents a multidimensional index space
668
+ of rank equal to `sizeof...(Extents)`. In  [[views]], `extents` is used
669
+ synonymously with multidimensional index space.
670
 
671
  ``` cpp
672
  namespace std {
673
  template<class IndexType, size_t... Extents>
674
  class extents {
 
848
 
849
  - If `N != rank_dynamic()` is `true`, `exts_arr[`r`]` equals Eᵣ for each
850
  r for which Eᵣ is a static extent, and
851
  - either
852
  - `sizeof...(exts) == 0` is `true`, or
853
+ - each element of `exts` is representable as a nonnegative value of
854
+ type `index_type`.
855
 
856
  *Ensures:* `*this == extents(exts_arr)` is `true`.
857
 
858
  ``` cpp
859
  template<class OtherIndexType, size_t N>
 
875
 
876
  - If `N != rank_dynamic()` is `true`, `exts[`r`]` equals Eᵣ for each r
877
  for which Eᵣ is a static extent, and
878
  - either
879
  - `N` is zero, or
880
+ - `exts[`r`]` is representable as a nonnegative value of type
881
  `index_type` for every rank index r.
882
 
883
  *Effects:*
884
 
885
+ - If `N` equals `rank_dynamic()`, for all d in the range
886
  [0, `rank_dynamic()`), direct-non-list-initializes
887
  *`dynamic-extents`*`[`d`]` with `as_const(exts[`d`])`.
888
  - Otherwise, for all d in the range [0, `rank_dynamic()`),
889
  direct-non-list-initializes *`dynamic-extents`*`[`d`]` with
890
  `as_const(exts[`*`dynamic-index-inv`*`(`d`)])`.
 
894
  explicit extents(Integrals...) -> see below;
895
  ```
896
 
897
  *Constraints:* `(is_convertible_v<Integrals, size_t> && ...)` is `true`.
898
 
899
+ *Remarks:* The deduced type is
900
+ `extents<size_t, maybe-static-ext<Integrals>...>`.
901
 
902
  ##### Observers of the multidimensional index space <a id="mdspan.extents.obs">[[mdspan.extents.obs]]</a>
903
 
904
  ``` cpp
905
  static constexpr size_t static_extent(rank_type i) noexcept;
 
938
 
939
  *Result:* A type `E` that is a specialization of `extents` such that
940
  `E::rank() == Rank && E::rank() == E::rank_dynamic()` is `true`, and
941
  `E::index_type` denotes `IndexType`.
942
 
943
+ ##### Alias template `dims` <a id="mdspan.extents.dims">[[mdspan.extents.dims]]</a>
944
+
945
+ ``` cpp
946
+ template<size_t Rank, class IndexType = size_t>
947
+ using dims = see below;
948
+ ```
949
+
950
+ *Result:* A type `E` that is a specialization of `extents` such that
951
+ `E::rank() == Rank && E::rank() == E::rank_dynamic()` is `true`, and
952
+ `E::index_type` denotes `IndexType`.
953
+
954
  #### Layout mapping <a id="mdspan.layout">[[mdspan.layout]]</a>
955
 
956
  ##### General <a id="mdspan.layout.general">[[mdspan.layout.general]]</a>
957
 
958
+ In [[mdspan.layout.reqmts]] and [[mdspan.layout.policy.reqmts]]:
 
959
 
960
  - `M` denotes a layout mapping class.
961
  - `m` denotes a (possibly const) value of type `M`.
962
  - `i` and `j` are packs of (possibly const) integers that are
963
  multidimensional indices in `m.extents()` [[mdspan.overview]].
 
966
  - `r` is a (possibly const) rank index of `typename M::extents_type`.
967
  - `dᵣ` is a pack of (possibly const) integers for which
968
  `sizeof...(dᵣ) == M::extents_type::rank()` is `true`, the rᵗʰ element
969
  is equal to 1, and all other elements are equal to 0.
970
 
971
+ In [[mdspan.layout.reqmts]] through [[mdspan.layout.stride]]:
972
+
973
+ - Let *`is-mapping-of`* be the exposition-only variable template defined
974
  as follows:
 
975
  ``` cpp
976
  template<class Layout, class Mapping>
977
  constexpr bool is-mapping-of = // exposition only
978
  is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
979
  ```
980
+ - Let *`is-layout-left-padded-mapping-of`* be the exposition-only
981
+ variable template defined as follows:
982
+ ``` cpp
983
+ template<class Mapping>
984
+ constexpr bool is-layout-left-padded-mapping-of = see below; // exposition only
985
+ ```
986
+
987
+ where `is-layout-left-padded-mapping-of<Mapping>` is `true` if and
988
+ only if `Mapping` denotes a specialization of
989
+ `layout_left_padded<S>::mapping` for some value `S` of type `size_t`.
990
+ - Let *`is-layout-right-padded-mapping-of`* be the exposition-only
991
+ variable template defined as follows:
992
+ ``` cpp
993
+ template<class Mapping>
994
+ constexpr bool is-layout-right-padded-mapping-of = see below; // exposition only
995
+ ```
996
+
997
+ where `is-layout-right-padded-mapping-of<Mapping>` is `true` if and
998
+ only if `Mapping` denotes a specialization of
999
+ `layout_right_padded<S>::mapping` for some value `S` of type `size_t`.
1000
+ - For nonnegative integers x and y, let LEAST-MULTIPLE-AT-LEAST(x, y)
1001
+ denote
1002
+ - y if x is zero,
1003
+ - otherwise, the least multiple of x that is greater than or equal to
1004
+ y.
1005
 
1006
  ##### Requirements <a id="mdspan.layout.reqmts">[[mdspan.layout.reqmts]]</a>
1007
 
1008
  A type `M` meets the *layout mapping* requirements if
1009
 
 
1127
 
1128
  *Result:* `typename M::index_type`
1129
 
1130
  *Returns:* sᵣ as defined in `m.is_strided()` above.
1131
 
1132
+ [*Note 5*: It is not required for `m.stride(r)` to be well-formed if
1133
+ `m.extents().rank()` is zero, even if `m.is_always_strided()` is
1134
+ `true`. — *end note*]
1135
+
1136
  ``` cpp
1137
  M::is_always_unique()
1138
  ```
1139
 
1140
  *Result:* A constant expression [[expr.const]] of type `bool`.
1141
 
1142
  *Returns:* `true` only if `m.is_unique()` is `true` for all possible
1143
  objects `m` of type `M`.
1144
 
1145
+ [*Note 6*: A mapping can return `false` even if the above condition is
1146
  met. For certain layout mappings, it is possibly not feasible to
1147
  determine whether every instance is unique. — *end note*]
1148
 
1149
  ``` cpp
1150
  M::is_always_exhaustive()
 
1153
  *Result:* A constant expression [[expr.const]] of type `bool`.
1154
 
1155
  *Returns:* `true` only if `m.is_exhaustive()` is `true` for all possible
1156
  objects `m` of type `M`.
1157
 
1158
+ [*Note 7*: A mapping can return `false` even if the above condition is
1159
  met. For certain layout mappings, it is possibly not feasible to
1160
  determine whether every instance is exhaustive. — *end note*]
1161
 
1162
  ``` cpp
1163
  M::is_always_strided()
 
1166
  *Result:* A constant expression [[expr.const]] of type `bool`.
1167
 
1168
  *Returns:* `true` only if `m.is_strided()` is `true` for all possible
1169
  objects `m` of type `M`.
1170
 
1171
+ [*Note 8*: A mapping can return `false` even if the above condition is
1172
  met. For certain layout mappings, it is possibly not feasible to
1173
  determine whether every instance is strided. — *end note*]
1174
 
1175
  ##### Layout mapping policy requirements <a id="mdspan.layout.policy.reqmts">[[mdspan.layout.policy.reqmts]]</a>
1176
 
 
1195
  };
1196
  struct layout_stride {
1197
  template<class Extents>
1198
  class mapping;
1199
  };
1200
+
1201
+ template<size_t PaddingValue>
1202
+ struct layout_left_padded {
1203
+ template<class Extents> class mapping;
1204
+ };
1205
+ template<size_t PaddingValue>
1206
+ struct layout_right_padded {
1207
+ template<class Extents> class mapping;
1208
+ };
1209
  }
1210
  ```
1211
 
1212
+ Each of `layout_left`, `layout_right`, and `layout_stride`, as well as
1213
+ each specialization of `layout_left_padded` and `layout_right_padded`,
1214
+ meets the layout mapping policy requirements and is a trivially copyable
1215
+ type. Furthermore, `is_trivially_default_constructible_v<T>` is `true`
1216
+ for any such type `T`.
1217
 
1218
  ##### Class template `layout_left::mapping` <a id="mdspan.layout.left">[[mdspan.layout.left]]</a>
1219
 
1220
  ###### Overview <a id="mdspan.layout.left.overview">[[mdspan.layout.left.overview]]</a>
1221
 
 
1226
  namespace std {
1227
  template<class Extents>
1228
  class layout_left::mapping {
1229
  public:
1230
  using extents_type = Extents;
1231
+ using index_type = extents_type::index_type;
1232
+ using size_type = extents_type::size_type;
1233
+ using rank_type = extents_type::rank_type;
1234
  using layout_type = layout_left;
1235
 
1236
  // [mdspan.layout.left.cons], constructors
1237
  constexpr mapping() noexcept = default;
1238
  constexpr mapping(const mapping&) noexcept = default;
 
1241
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1242
  mapping(const mapping<OtherExtents>&) noexcept;
1243
  template<class OtherExtents>
1244
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1245
  mapping(const layout_right::mapping<OtherExtents>&) noexcept;
1246
+ template<class LayoutLeftPaddedMapping>
1247
+ constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
1248
+ extents_type>)
1249
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
1250
  template<class OtherExtents>
1251
  constexpr explicit(extents_type::rank() > 0)
1252
  mapping(const layout_stride::mapping<OtherExtents>&);
1253
 
1254
  constexpr mapping& operator=(const mapping&) noexcept = default;
 
1274
  template<class OtherExtents>
1275
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
1276
 
1277
  private:
1278
  extents_type extents_{}; // exposition only
1279
+
1280
+ // [mdspan.sub.map], submdspan mapping specialization
1281
+ template<class... SliceSpecifiers>
1282
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1283
+ -> see below;
1284
+
1285
+ template<class... SliceSpecifiers>
1286
+ friend constexpr auto submdspan_mapping(
1287
+ const mapping& src, SliceSpecifiers... slices) {
1288
+ return src.submdspan-mapping-impl(slices...);
1289
+ }
1290
  };
1291
  }
1292
  ```
1293
 
1294
  If `Extents` is not a specialization of `extents`, then the program is
 
1326
 
1327
  *Effects:* Direct-non-list-initializes *extents\_* with
1328
  `other.extents()`.
1329
 
1330
  ``` cpp
1331
+ template<class OtherExtents>
1332
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1333
  mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
1334
  ```
1335
 
1336
  *Constraints:*
 
1342
  value of type `index_type` [[basic.fundamental]].
1343
 
1344
  *Effects:* Direct-non-list-initializes *extents\_* with
1345
  `other.extents()`.
1346
 
1347
+ ``` cpp
1348
+ template<class LayoutLeftPaddedMapping>
1349
+ constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
1350
+ extents_type>)
1351
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
1352
+ ```
1353
+
1354
+ *Constraints:*
1355
+
1356
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
1357
+ `true`.
1358
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
1359
+ is `true`.
1360
+
1361
+ *Mandates:* If
1362
+
1363
+ - `Extents::rank()` is greater than one,
1364
+ - `Extents::static_extent(0)` does not equal `dynamic_extent`, and
1365
+ - `LayoutLeftPaddedMapping::`*`static-padding-stride`* does not equal
1366
+ `dynamic_extent`,
1367
+
1368
+ then `Extents::static_extent(0)` equals
1369
+ `LayoutLeftPaddedMapping::`*`static-padding-stride`*.
1370
+
1371
+ *Preconditions:*
1372
+
1373
+ - If `extents_type::rank() > 1` is `true`, then `other.stride(1)` equals
1374
+ `other.extents().extent(0)`.
1375
+ - `other.required_span_size()` is representable as a value of type
1376
+ `index_type`.
1377
+
1378
+ *Effects:* Direct-non-list-initializes `extents_` with
1379
+ `other.extents()`.
1380
+
1381
  ``` cpp
1382
  template<class OtherExtents>
1383
  constexpr explicit(extents_type::rank() > 0)
1384
  mapping(const layout_stride::mapping<OtherExtents>& other);
1385
  ```
 
1431
  ``` cpp
1432
  return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
1433
  ```
1434
 
1435
  ``` cpp
1436
+ constexpr index_type stride(rank_type i) const noexcept;
1437
  ```
1438
 
1439
  *Constraints:* `extents_type::rank() > 0` is `true`.
1440
 
1441
  *Preconditions:* `i < extents_type::rank()` is `true`.
 
1462
  namespace std {
1463
  template<class Extents>
1464
  class layout_right::mapping {
1465
  public:
1466
  using extents_type = Extents;
1467
+ using index_type = extents_type::index_type;
1468
+ using size_type = extents_type::size_type;
1469
+ using rank_type = extents_type::rank_type;
1470
  using layout_type = layout_right;
1471
 
1472
  // [mdspan.layout.right.cons], constructors
1473
  constexpr mapping() noexcept = default;
1474
  constexpr mapping(const mapping&) noexcept = default;
 
1477
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1478
  mapping(const mapping<OtherExtents>&) noexcept;
1479
  template<class OtherExtents>
1480
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
1481
  mapping(const layout_left::mapping<OtherExtents>&) noexcept;
1482
+ template<class LayoutRightPaddedMapping>
1483
+ constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
1484
+ extents_type>)
1485
+ mapping(const LayoutRightPaddedMapping&) noexcept;
1486
  template<class OtherExtents>
1487
  constexpr explicit(extents_type::rank() > 0)
1488
  mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
1489
 
1490
  constexpr mapping& operator=(const mapping&) noexcept = default;
 
1510
  template<class OtherExtents>
1511
  friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
1512
 
1513
  private:
1514
  extents_type extents_{}; // exposition only
1515
+
1516
+ // [mdspan.sub.map], submdspan mapping specialization
1517
+ template<class... SliceSpecifiers>
1518
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1519
+ -> see below;
1520
+
1521
+ template<class... SliceSpecifiers>
1522
+ friend constexpr auto submdspan_mapping(
1523
+ const mapping& src, SliceSpecifiers... slices) {
1524
+ return src.submdspan-mapping-impl(slices...);
1525
+ }
1526
  };
1527
  }
1528
  ```
1529
 
1530
  If `Extents` is not a specialization of `extents`, then the program is
 
1578
  value of type `index_type` [[basic.fundamental]].
1579
 
1580
  *Effects:* Direct-non-list-initializes *extents\_* with
1581
  `other.extents()`.
1582
 
1583
+ ``` cpp
1584
+ template<class LayoutRightPaddedMapping>
1585
+ constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
1586
+ extents_type>)
1587
+ mapping(const LayoutRightPaddedMapping&) noexcept;
1588
+ ```
1589
+
1590
+ *Constraints:*
1591
+
1592
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
1593
+ `true`.
1594
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
1595
+ is `true`.
1596
+
1597
+ *Mandates:* If
1598
+
1599
+ - `Extents::rank()` is greater than one,
1600
+ - `Extents::static_extent(Extents::rank() - 1)` does not equal
1601
+ `dynamic_extent`, and
1602
+ - `LayoutRightPaddedMapping::`*`static-padding-stride`* does not equal
1603
+ `dynamic_extent`,
1604
+
1605
+ then `Extents::static_extent(Extents::rank() - 1)` equals
1606
+ `LayoutRightPaddedMapping::`*`static-padding-stride`*.
1607
+
1608
+ *Preconditions:*
1609
+
1610
+ - If `extents_type::rank() > 1` is `true`, then
1611
+ `other.stride(extents_type::rank() - 2)` equals
1612
+ `other.extents().extent(extents_type::rank() - 1)`.
1613
+ - `other.required_span_size()` is representable as a value of type
1614
+ `index_type`.
1615
+
1616
+ *Effects:* Direct-non-list-initializes `extents_` with
1617
+ `other.extents()`.
1618
+
1619
  ``` cpp
1620
  template<class OtherExtents>
1621
  constexpr explicit(extents_type::rank() > 0)
1622
  mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
1623
  ```
 
1637
  `other.extents()`.
1638
 
1639
  ###### Observers <a id="mdspan.layout.right.obs">[[mdspan.layout.right.obs]]</a>
1640
 
1641
  ``` cpp
1642
+ constexpr index_type required_span_size() const noexcept;
1643
  ```
1644
 
1645
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(extents_type::rank())`.
1646
 
1647
  ``` cpp
 
1700
  namespace std {
1701
  template<class Extents>
1702
  class layout_stride::mapping {
1703
  public:
1704
  using extents_type = Extents;
1705
+ using index_type = extents_type::index_type;
1706
+ using size_type = extents_type::size_type;
1707
+ using rank_type = extents_type::rank_type;
1708
  using layout_type = layout_stride;
1709
 
1710
  private:
1711
  static constexpr rank_type rank_ = extents_type::rank(); // exposition only
1712
 
 
1747
  friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
1748
 
1749
  private:
1750
  extents_type extents_{}; // exposition only
1751
  array<index_type, rank_> strides_{}; // exposition only
1752
+
1753
+ // [mdspan.sub.map], submdspan mapping specialization
1754
+ template<class... SliceSpecifiers>
1755
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
1756
+ -> see below;
1757
+
1758
+ template<class... SliceSpecifiers>
1759
+ friend constexpr auto submdspan_mapping(
1760
+ const mapping& src, SliceSpecifiers... slices) {
1761
+ return src.submdspan-mapping-impl(slices...);
1762
+ }
1763
  };
1764
  }
1765
  ```
1766
 
1767
  If `Extents` is not a specialization of `extents`, then the program is
 
1780
 
1781
  - `1`, if `e.rank() == 0` is `true`,
1782
  - otherwise `0`, if the size of the multidimensional index space `e` is
1783
  0,
1784
  - otherwise `1` plus the sum of products of `(e.extent(r) - 1)` and
1785
+ ``` cpp
1786
+ extents_type::index-cast(strides[r])
1787
+ ```
1788
+
1789
+ for all r in the range [0, `e.rank()`).
1790
 
1791
  Let `OFFSET(m)` be:
1792
 
1793
  - `m()`, if `e.rank() == 0` is `true`,
1794
  - otherwise `0`, if the size of the multidimensional index space `e` is
 
1856
  - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
1857
  `true`.
1858
 
1859
  *Preconditions:*
1860
 
1861
+ - The result of converting `s[`i`]` to `index_type` is greater than `0`
1862
+ for all i in the range [0, rank_).
1863
  - *`REQUIRED-SPAN-SIZE`*`(e, s)` is representable as a value of type
1864
  `index_type` [[basic.fundamental]].
1865
  - If *rank\_* is greater than 0, then there exists a permutation P of
1866
  the integers in the range [0, rank_), such that
1867
  `s[`pᵢ`] >= s[`pᵢ₋₁`] * e.extent(p`ᵢ₋₁`)` is `true` for all i in the
 
1889
  - `StridedLayoutMapping::is_always_strided()` is `true`.
1890
 
1891
  *Preconditions:*
1892
 
1893
  - `StridedLayoutMapping` meets the layout mapping
1894
+ requirements [[mdspan.layout.reqmts]],
1895
  - `other.stride(`r`) > 0` is `true` for every rank index r of
1896
  `extents()`,
1897
  - `other.required_span_size()` is representable as a value of type
1898
  `index_type` [[basic.fundamental]], and
1899
  - *`OFFSET`*`(other) == 0` is `true`.
 
1905
 
1906
  Remarks: The expression inside `explicit` is equivalent to:
1907
 
1908
  ``` cpp
1909
  !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
1910
+ (is-mapping-of<layout_left, StridedLayoutMapping> ||
1911
+ is-mapping-of<layout_right, StridedLayoutMapping> ||
1912
+ is-layout-left-padded-mapping-of<StridedLayoutMapping> ||
1913
+ is-layout-right-padded-mapping-of<StridedLayoutMapping> ||
1914
+ is-mapping-of<layout_stride, StridedLayoutMapping>))
1915
  ```
1916
 
1917
  ###### Observers <a id="mdspan.layout.stride.obs">[[mdspan.layout.stride.obs]]</a>
1918
 
1919
  ``` cpp
 
1978
  *Returns:* `true` if `x.extents() == y.extents()` is `true`,
1979
  *`OFFSET`*`(y) == 0` is `true`, and each of
1980
  `x.stride(`r`) == y.stride(`r`)` is `true` for r in the range
1981
  [0, `x.extents().rank()`). Otherwise, `false`.
1982
 
1983
+ ##### Class template `layout_left_padded::mapping` <a id="mdspan.layout.leftpad">[[mdspan.layout.leftpad]]</a>
1984
+
1985
+ ###### Overview <a id="mdspan.layout.leftpad.overview">[[mdspan.layout.leftpad.overview]]</a>
1986
+
1987
+ `layout_left_padded` provides a layout mapping that behaves like
1988
+ `layout_left::mapping`, except that the padding stride `stride(1)` can
1989
+ be greater than or equal to `extent(0)`.
1990
+
1991
+ ``` cpp
1992
+ namespace std {
1993
+ template<size_t PaddingValue>
1994
+ template<class Extents>
1995
+ class layout_left_padded<PaddingValue>::mapping {
1996
+ public:
1997
+ static constexpr size_t padding_value = PaddingValue;
1998
+
1999
+ using extents_type = Extents;
2000
+ using index_type = extents_type::index_type;
2001
+ using size_type = extents_type::size_type;
2002
+ using rank_type = extents_type::rank_type;
2003
+ using layout_type = layout_left_padded<PaddingValue>;
2004
+
2005
+ private:
2006
+ static constexpr size_t rank_ = extents_type::rank(); // exposition only
2007
+ static constexpr size_t first-static-extent = // exposition only
2008
+ extents_type::static_extent(0);
2009
+
2010
+ // [mdspan.layout.leftpad.expo], exposition-only members
2011
+ static constexpr size_t static-padding-stride = see below; // exposition only
2012
+
2013
+ public:
2014
+ // [mdspan.layout.leftpad.cons], constructors
2015
+ constexpr mapping() noexcept : mapping(extents_type{}) {}
2016
+ constexpr mapping(const mapping&) noexcept = default;
2017
+ constexpr mapping(const extents_type&);
2018
+ template<class OtherIndexType>
2019
+ constexpr mapping(const extents_type&, OtherIndexType);
2020
+ template<class OtherExtents>
2021
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
2022
+ mapping(const layout_left::mapping<OtherExtents>&);
2023
+ template<class OtherExtents>
2024
+ constexpr explicit(extents_type::rank() > 0)
2025
+ mapping(const layout_stride::mapping<OtherExtents>&);
2026
+ template<class LayoutLeftPaddedMapping>
2027
+ constexpr explicit(see below)
2028
+ mapping(const LayoutLeftPaddedMapping&);
2029
+ template<class LayoutRightPaddedMapping>
2030
+ constexpr explicit(see below)
2031
+ mapping(const LayoutRightPaddedMapping&) noexcept;
2032
+
2033
+ constexpr mapping& operator=(const mapping&) noexcept = default;
2034
+
2035
+ // [mdspan.layout.leftpad.obs], observers
2036
+ constexpr const extents_type& extents() const noexcept { return extents_; }
2037
+ constexpr array<index_type, rank_> strides() const noexcept;
2038
+
2039
+ constexpr index_type required_span_size() const noexcept;
2040
+ template<class... Indices>
2041
+ constexpr index_type operator()(Indices...) const noexcept;
2042
+
2043
+ static constexpr bool is_always_unique() noexcept { return true; }
2044
+ static constexpr bool is_always_exhaustive() noexcept;
2045
+ static constexpr bool is_always_strided() noexcept { return true; }
2046
+
2047
+ static constexpr bool is_unique() noexcept { return true; }
2048
+ constexpr bool is_exhaustive() const noexcept;
2049
+ static constexpr bool is_strided() noexcept { return true; }
2050
+
2051
+ constexpr index_type stride(rank_type) const noexcept;
2052
+
2053
+ template<class LayoutLeftPaddedMapping>
2054
+ friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;
2055
+
2056
+ private:
2057
+ // [mdspan.layout.leftpad.expo], exposition-only members
2058
+ index_type stride-1 = static-padding-stride; // exposition only
2059
+ extents_type extents_{}; // exposition only
2060
+ // [mdspan.sub.map], submdspan mapping specialization
2061
+ template<class... SliceSpecifiers>
2062
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
2063
+ -> see below;
2064
+
2065
+ template<class... SliceSpecifiers>
2066
+ friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
2067
+ return src.submdspan-mapping-impl(slices...);
2068
+ }
2069
+ };
2070
+ }
2071
+ ```
2072
+
2073
+ If `Extents` is not a specialization of `extents`, then the program is
2074
+ ill-formed.
2075
+
2076
+ `layout_left_padded::mapping<E>` is a trivially copyable type that
2077
+ models `regular` for each `E`.
2078
+
2079
+ Throughout [[mdspan.layout.leftpad]], let `P_rank` be the following size
2080
+ *`rank_`* parameter pack of `size_`t values:
2081
+
2082
+ - the empty parameter pack, if *`rank_`* equals zero;
2083
+ - otherwise, `0zu`, if *`rank_`* equals one;
2084
+ - otherwise, the parameter pack `0zu`, `1zu`, …, `rank_- 1`.
2085
+
2086
+ *Mandates:*
2087
+
2088
+ - If `rank_dynamic() == 0` is `true`, then the size of the
2089
+ multidimensional index space `Extents()` is representable as a value
2090
+ of type `index_type`.
2091
+ - `padding_value` is representable as a value of type `index_type`.
2092
+ - If
2093
+ - *`rank_`* is greater than one,
2094
+ - `padding_value` does not equal `dynamic_extent`, and
2095
+ - *`first-static-extent`* does not equal `dynamic_extent`,
2096
+
2097
+ then `LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent)` is
2098
+ representable as a value of type `size_t`, and is representable as a
2099
+ value of type `index_type`.
2100
+ - If
2101
+ - *`rank_`* is greater than one,
2102
+ - `padding_value` does not equal `dynamic_extent`, and
2103
+ - `extents_type::static_extent(k)` does not equal `dynamic_extent` for
2104
+ all k in the range \[`0`, `extents_type::rank()`),
2105
+
2106
+ then the product of
2107
+ `LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(0))` and all
2108
+ values `ext.static_extent(k)` with k in the range of \[`1`, *`rank_`*)
2109
+ is representable as a value of type `size_t`, and is representable as
2110
+ a value of type `index_type`.
2111
+
2112
+ ###### Exposition-only members <a id="mdspan.layout.leftpad.expo">[[mdspan.layout.leftpad.expo]]</a>
2113
+
2114
+ ``` cpp
2115
+ static constexpr size_t static-padding-stride = see below;
2116
+ ```
2117
+
2118
+ The value is
2119
+
2120
+ - `0`, if *rank\_* equals zero or one;
2121
+ - otherwise, `dynamic_extent`, if `padding_value` or
2122
+ *first-static-extent* equals `dynamic_extent`;
2123
+ - otherwise, the `size_t` value which is
2124
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, `*`first-static-extent`*`)`.
2125
+
2126
+ ``` cpp
2127
+ index_type stride-1 = static-padding-stride;
2128
+ ```
2129
+
2130
+ *Recommended practice:* Implementations should not store this value if
2131
+ *static-padding-stride* is not `dynamic_extent`.
2132
+
2133
+ [*Note 9*: Using `extents<index_type, `*`static-padding-stride`*`>`
2134
+ instead of `index_type` as the type of *stride-1* would achieve
2135
+ this. — *end note*]
2136
+
2137
+ ###### Constructors <a id="mdspan.layout.leftpad.cons">[[mdspan.layout.leftpad.cons]]</a>
2138
+
2139
+ ``` cpp
2140
+ constexpr mapping(const extents_type& ext);
2141
+ ```
2142
+
2143
+ *Preconditions:*
2144
+
2145
+ - The size of the multidimensional index space `ext` is representable as
2146
+ a value of type `index_type`.
2147
+ - If *rank\_* is greater than one and `padding_value` does not equal
2148
+ `dynamic_extent`, then
2149
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))` is
2150
+ representable as a value of type *index_type*.
2151
+ - If *rank\_* is greater than one and `padding_value` does not equal
2152
+ `dynamic_extent`, then the product of
2153
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))` and all
2154
+ values `ext.extent(`k`)` with k in the range of \[`1`, *`rank_`*) is
2155
+ representable as a value of type `index_type`.
2156
+
2157
+ *Effects:*
2158
+
2159
+ - Direct-non-list-initializes *extents\_* with `ext`; and
2160
+ - if *rank\_* is greater than one, direct-non-list-initializes
2161
+ *stride-1*
2162
+ - with `ext.extent(0)` if padding_value is `dynamic_extent`,
2163
+ - otherwise with
2164
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(0))`.
2165
+
2166
+ ``` cpp
2167
+ template<class OtherIndexType>
2168
+ constexpr mapping(const extents_type& ext, OtherIndexType pad);
2169
+ ```
2170
+
2171
+ *Constraints:*
2172
+
2173
+ - `is_convertible_v<OtherIndexType, index_type>` is `true`.
2174
+ - `is_nothrow_constructible_v<index_type, OtherIndexType>` is `true`.
2175
+
2176
+ *Preconditions:*
2177
+
2178
+ - `pad` is representable as a value of type `index_type`.
2179
+ - `extents_type::`*`index-cast`*`(pad)` is greater than zero.
2180
+ - If *rank\_* is greater than one, then
2181
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))` is representable as
2182
+ a value of type `index_type.`
2183
+ - If *rank\_* is greater than one, then the product of
2184
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))` and all values
2185
+ `ext.extent(`k`)` with k in the range of \[`1`, *`rank_`*) is
2186
+ representable as a value of type `index_type`.
2187
+ - If `padding_value` is not equal to `dynamic_extent`, `padding_value`
2188
+ equals `extents_type::`*`index-cast`*`(pad)`.
2189
+
2190
+ *Effects:* Direct-non-list-initializes *extents\_* with `ext`, and if
2191
+ *rank\_* is greater than one, direct-non-list-initializes *stride-1*
2192
+ with *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(0))`.
2193
+
2194
+ ``` cpp
2195
+ template<class OtherExtents>
2196
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
2197
+ mapping(const layout_left::mapping<OtherExtents>& other);
2198
+ ```
2199
+
2200
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
2201
+ `true`.
2202
+
2203
+ *Mandates:* If `OtherExtents::rank()` is greater than `1`, then
2204
+
2205
+ ``` cpp
2206
+ (static-padding-stride == dynamic_extent) ||
2207
+ (OtherExtents::static_extent(0) == dynamic_extent) ||
2208
+ (static-padding-stride == OtherExtents::static_extent(0))
2209
+ ```
2210
+
2211
+ is `true`.
2212
+
2213
+ *Preconditions:*
2214
+
2215
+ - If `extents_type::rank() > 1` is `true` and `padding_value` ==
2216
+ `dynamic_extent` is `false`, then `other.stride(1)` equals
2217
+ ``` cpp
2218
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2219
+ extents_type::index-cast(other.extents().extent(0)))
2220
+ ```
2221
+
2222
+ and
2223
+ - `other.required_span_size()` is representable as a value of type
2224
+ `index_type`.
2225
+
2226
+ *Effects:* Equivalent to `mapping(other.extents())`.
2227
+
2228
+ ``` cpp
2229
+ template<class OtherExtents>
2230
+ constexpr explicit(rank_ > 0)
2231
+ mapping(const layout_stride::mapping<OtherExtents>& other);
2232
+ ```
2233
+
2234
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
2235
+ `true`.
2236
+
2237
+ *Preconditions:*
2238
+
2239
+ - If *rank\_* is greater than `1` and `padding_value` does not equal
2240
+ `dynamic_extent`, then `other.stride(1)` equals
2241
+ ``` cpp
2242
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2243
+ extents_type::index-cast(other.extents().extent(0)))
2244
+ ```
2245
+ - If *rank\_* is greater than 0, then `other.stride(0)` equals 1.
2246
+ - If *rank\_* is greater than 2, then for all r in the range \[`2`,
2247
+ *`rank_`*), `other.stride(r)` equals
2248
+ ``` cpp
2249
+ (other.extents().fwd-prod-of-extents(r) / other.extents().extent(0)) * other.stride(1)
2250
+ ```
2251
+ - `other.required_span_size()` is representable as a value of type
2252
+ *index_type*.
2253
+
2254
+ *Effects:*
2255
+
2256
+ - Direct-non-list-initializes *extents\_* with `other.extents()` and
2257
+ - if *rank\_* is greater than one, direct-non-list-initializes
2258
+ *stride-1* with `other.stride(1)`.
2259
+
2260
+ ``` cpp
2261
+ template<class LayoutLeftPaddedMapping>
2262
+ constexpr explicit(see below)
2263
+ mapping(const LayoutLeftPaddedMapping& other);
2264
+ ```
2265
+
2266
+ *Constraints:*
2267
+
2268
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
2269
+ `true`.
2270
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
2271
+ is `true`.
2272
+
2273
+ *Mandates:* If *rank\_* is greater than 1, then
2274
+
2275
+ ``` cpp
2276
+ padding_value == dynamic_extent ||
2277
+ LayoutLeftPaddedMapping::padding_value == dynamic_extent ||
2278
+ padding_value == LayoutLeftPaddedMapping::padding_value
2279
+ ```
2280
+
2281
+ is `true`.
2282
+
2283
+ *Preconditions:*
2284
+
2285
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
2286
+ `dynamic_extent`, then `other.stride(1)` equals
2287
+ ``` cpp
2288
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2289
+ extents_type::index-cast(other.extent(0)))
2290
+ ```
2291
+ - `other.required_span_size()` is representable as a value of type
2292
+ `index_type`.
2293
+
2294
+ *Effects:*
2295
+
2296
+ - Direct-non-list-initializes *extents\_* with `other.extents()` and
2297
+ - if *rank\_* is greater than one, direct-non-list-initializes
2298
+ *stride-1* with `other.stride(1)`.
2299
+
2300
+ *Remarks:* The expression inside `explicit` is equivalent to:
2301
+
2302
+ ``` cpp
2303
+ rank_> 1 &&
2304
+ (padding_value != dynamic_extent ||
2305
+ LayoutLeftPaddedMapping::padding_value == dynamic_extent)
2306
+ ```
2307
+
2308
+ ``` cpp
2309
+ template<class LayoutRightPaddedMapping>
2310
+ constexpr explicit(see below)
2311
+ mapping(const LayoutRightPaddedMapping& other) noexcept;
2312
+ ```
2313
+
2314
+ *Constraints:*
2315
+
2316
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
2317
+ `true` or *`is-mapping-of`*`<layout_right, LayoutRightPaddedMapping>`
2318
+ is `true`.
2319
+ - *rank\_* equals zero or one.
2320
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
2321
+ is `true`.
2322
+
2323
+ *Preconditions:* `other.required_span_size()` is representable as a
2324
+ value of type `index_type`.
2325
+
2326
+ *Effects:* Direct-non-list-initializes *extents\_* with
2327
+ `other.extents()`.
2328
+
2329
+ *Remarks:* The expression inside `explicit` is equivalent to:
2330
+
2331
+ ``` cpp
2332
+ !is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>
2333
+ ```
2334
+
2335
+ [*Note 10*: Neither the input mapping nor the mapping to be constructed
2336
+ uses the padding stride in the rank-0 or rank-1 case, so the padding
2337
+ stride does not affect either the constraints or the
2338
+ preconditions. — *end note*]
2339
+
2340
+ ###### Observers <a id="mdspan.layout.leftpad.obs">[[mdspan.layout.leftpad.obs]]</a>
2341
+
2342
+ ``` cpp
2343
+ constexpr array<index_type, rank_> strides() const noexcept;
2344
+ ```
2345
+
2346
+ *Returns:* `array<index_type, `*`rank_`*`>({stride(P_rank)...})`.
2347
+
2348
+ ``` cpp
2349
+ constexpr index_type required_span_size() const noexcept;
2350
+ ```
2351
+
2352
+ *Returns:*
2353
+
2354
+ - `0` if the multidimensional index space *extents\_* is empty,
2355
+ - otherwise,
2356
+ `(*this)(`*`extents_`*`.extent(P_rank) - index_type(1)...) + 1`.
2357
+
2358
+ ``` cpp
2359
+ template<class... Indices>
2360
+ constexpr size_t operator()(Indices... idxs) const noexcept;
2361
+ ```
2362
+
2363
+ *Constraints:*
2364
+
2365
+ - `sizeof...(Indices) == `*`rank_`* is `true`.
2366
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`.
2367
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
2368
+
2369
+ *Preconditions:* `extents_type::`*`index-cast`*`(idxs)` is a
2370
+ multidimensional index in `extents()` [[mdspan.overview]].
2371
+
2372
+ *Returns:*
2373
+ `((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)`.
2374
+
2375
+ ``` cpp
2376
+ static constexpr bool is_always_exhaustive() noexcept;
2377
+ ```
2378
+
2379
+ *Returns:*
2380
+
2381
+ - If *rank\_* equals zero or one, then `true`;
2382
+ - otherwise, if neither *static-padding-stride* nor
2383
+ *first-static-extent* equal `dynamic_extent`, then
2384
+ *`static-padding-stride`*` == `*`first-static-extent`*;
2385
+ - otherwise, `false`.
2386
+
2387
+ ``` cpp
2388
+ constexpr bool is_exhaustive() const noexcept;
2389
+ ```
2390
+
2391
+ *Returns:* `true` if *rank\_* equals zero or one; otherwise,
2392
+ `extents_.extent(0) == stride(1)`.
2393
+
2394
+ ``` cpp
2395
+ constexpr index_type stride(rank_type r) const noexcept;
2396
+ ```
2397
+
2398
+ *Preconditions:* `r` is smaller than *rank\_*.
2399
+
2400
+ *Returns:*
2401
+
2402
+ - If `r` equals zero: 1;
2403
+ - otherwise, if `r` equals one: *stride-1*;
2404
+ - otherwise, the product of *stride-1* and all values
2405
+ `extents_.extent(`k`)` with k in the range \[`1`, `r`).
2406
+
2407
+ ``` cpp
2408
+ template<class LayoutLeftPaddedMapping>
2409
+ friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
2410
+ ```
2411
+
2412
+ *Constraints:*
2413
+
2414
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
2415
+ `true`.
2416
+ - `LayoutLeftPaddedMapping::extents_type::rank() == rank_` is `true`.
2417
+
2418
+ *Returns:* `true` if `x.extents() == y.extents()` is `true` and
2419
+ *`rank_`*` < 2 || x.stride(1) == y. stride(1)` is `true`. Otherwise,
2420
+ `false`.
2421
+
2422
+ ##### Class template `layout_right_padded::mapping` <a id="mdspan.layout.rightpad">[[mdspan.layout.rightpad]]</a>
2423
+
2424
+ ###### Overview <a id="mdspan.layout.rightpad.overview">[[mdspan.layout.rightpad.overview]]</a>
2425
+
2426
+ `layout_right_padded` provides a layout mapping that behaves like
2427
+ `layout_right::mapping`, except that the padding stride
2428
+ `stride(extents_type::rank() - 2)` can be greater than or equal to
2429
+ `extents_type::extent(extents_type::rank() - 1)`.
2430
+
2431
+ ``` cpp
2432
+ namespace std {
2433
+ template<size_t PaddingValue>
2434
+ template<class Extents>
2435
+ class layout_right_padded<PaddingValue>::mapping {
2436
+ public:
2437
+ static constexpr size_t padding_value = PaddingValue;
2438
+
2439
+ using extents_type = Extents;
2440
+ using index_type = extents_type::index_type;
2441
+ using size_type = extents_type::size_type;
2442
+ using rank_type = extents_type::rank_type;
2443
+ using layout_type = layout_right_padded<PaddingValue>;
2444
+
2445
+ private:
2446
+ static constexpr size_t rank_ = extents_type::rank(); // exposition only
2447
+ static constexpr size_t last-static-extent = // exposition only
2448
+ extents_type::static_extent(rank_ - 1);
2449
+
2450
+ // [mdspan.layout.rightpad.expo], exposition-only members
2451
+ static constexpr size_t static-padding-stride = see below; // exposition only
2452
+
2453
+ public:
2454
+ // [mdspan.layout.rightpad.cons], constructors
2455
+ constexpr mapping() noexcept : mapping(extents_type{}) {}
2456
+ constexpr mapping(const mapping&) noexcept = default;
2457
+ constexpr mapping(const extents_type&);
2458
+ template<class OtherIndexType>
2459
+ constexpr mapping(const extents_type&, OtherIndexType);
2460
+
2461
+ template<class OtherExtents>
2462
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
2463
+ mapping(const layout_right::mapping<OtherExtents>&);
2464
+ template<class OtherExtents>
2465
+ constexpr explicit(rank_ > 0)
2466
+ mapping(const layout_stride::mapping<OtherExtents>&);
2467
+ template<class LayoutRightPaddedMapping>
2468
+ constexpr explicit(see below)
2469
+ mapping(const LayoutRightPaddedMapping&);
2470
+ template<class LayoutLeftPaddedMapping>
2471
+ constexpr explicit(see below)
2472
+ mapping(const LayoutLeftPaddedMapping&) noexcept;
2473
+
2474
+ constexpr mapping& operator=(const mapping&) noexcept = default;
2475
+
2476
+ // [mdspan.layout.rightpad.obs], observers
2477
+ constexpr const extents_type& extents() const noexcept { return extents_; }
2478
+ constexpr array<index_type, rank_> strides() const noexcept;
2479
+
2480
+ constexpr index_type required_span_size() const noexcept;
2481
+
2482
+ template<class... Indices>
2483
+ constexpr index_type operator()(Indices...) const noexcept;
2484
+
2485
+ static constexpr bool is_always_unique() noexcept { return true; }
2486
+ static constexpr bool is_always_exhaustive() noexcept;
2487
+ static constexpr bool is_always_strided() noexcept { return true; }
2488
+
2489
+ static constexpr bool is_unique() noexcept { return true; }
2490
+ constexpr bool is_exhaustive() const noexcept;
2491
+ static constexpr bool is_strided() noexcept { return true; }
2492
+
2493
+ constexpr index_type stride(rank_type) const noexcept;
2494
+
2495
+ template<class LayoutRightPaddedMapping>
2496
+ friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;
2497
+
2498
+ private:
2499
+ // [mdspan.layout.rightpad.expo], exposition-only members
2500
+ index_type stride-rm2 = static-padding-stride; // exposition only
2501
+ extents_type extents_{}; // exposition only
2502
+
2503
+ // [mdspan.sub.map], submdspan mapping specialization
2504
+ template<class... SliceSpecifiers>
2505
+ constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only
2506
+ -> see below;
2507
+
2508
+ template<class... SliceSpecifiers>
2509
+ friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
2510
+ return src.submdspan-mapping-impl(slices...);
2511
+ }
2512
+ };
2513
+ }
2514
+ ```
2515
+
2516
+ If `Extents` is not a specialization of `extents`, then the program is
2517
+ ill-formed.
2518
+
2519
+ `layout_right_padded::mapping<E>` is a trivially copyable type that
2520
+ models `regular` for each `E`.
2521
+
2522
+ Throughout [[mdspan.layout.rightpad]], let `P_rank` be the following
2523
+ size *`rank_`* parameter pack of `size_`t values:
2524
+
2525
+ - the empty parameter pack, if *`rank_`* equals zero;
2526
+ - otherwise, `0zu`, if *`rank_`* equals one;
2527
+ - otherwise, the parameter pack `0zu`, `1zu`, …, `rank_- 1`.
2528
+
2529
+ *Mandates:*
2530
+
2531
+ - If `rank_dynamic() == 0` is `true`, then the size of the
2532
+ multidimensional index space `Extents()` is representable as a value
2533
+ of type `index_type`.
2534
+ - `padding_value` is representable as a value of type `index_type`.
2535
+ - If
2536
+ - *`rank_`* is greater than one,
2537
+ - `padding_value` does not equal `dynamic_extent`, and
2538
+ - *`last-static-extent`* does not equal `dynamic_extent`,
2539
+
2540
+ then `LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent)` is
2541
+ representable as a value of type `size_t`, and is representable as a
2542
+ value of type `index_type`.
2543
+ - If
2544
+ - *`rank_`* is greater than one,
2545
+ - `padding_value` does not equal `dynamic_extent`, and
2546
+ - `extents_type::static_extent(k)` does not equal `dynamic_extent` for
2547
+ all k in the range \[`0`, *`rank_`*),
2548
+
2549
+ then the product of
2550
+ `LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(rank_ - 1))`
2551
+ and all values `ext.static_extent(k)` with k in the range of \[`0`,
2552
+ *`rank_`*` - 1`) is representable as a value of type `size_t`, and is
2553
+ representable as a value of type `index_type`.
2554
+
2555
+ ###### Exposition-only members <a id="mdspan.layout.rightpad.expo">[[mdspan.layout.rightpad.expo]]</a>
2556
+
2557
+ ``` cpp
2558
+ static constexpr size_t static-padding-stride = see below;
2559
+ ```
2560
+
2561
+ The value is
2562
+
2563
+ - `0`, if *rank\_* equals zero or one;
2564
+ - otherwise, `dynamic_extent`, if `padding_value` or
2565
+ *last-static-extent* equals `dynamic_extent`;
2566
+ - otherwise, the `size_t` value which is
2567
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, `*`last-static-extent`*`)`.
2568
+
2569
+ ``` cpp
2570
+ index_type stride-rm2 = static-padding-stride;
2571
+ ```
2572
+
2573
+ *Recommended practice:* Implementations should not store this value if
2574
+ *static-padding-stride* is not `dynamic_extent`.
2575
+
2576
+ [*Note 11*: Using `extents<index_type, `*`static-padding-stride`*`>`
2577
+ instead of `index_type` as the type of *stride-rm2* would achieve
2578
+ this. — *end note*]
2579
+
2580
+ ###### Constructors <a id="mdspan.layout.rightpad.cons">[[mdspan.layout.rightpad.cons]]</a>
2581
+
2582
+ ``` cpp
2583
+ constexpr mapping(const extents_type& ext);
2584
+ ```
2585
+
2586
+ *Preconditions:*
2587
+
2588
+ - The size of the multidimensional index space `ext` is representable as
2589
+ a value of type `index_type`.
2590
+ - If *rank\_* is greater than one and `padding_value` does not equal
2591
+ `dynamic_extent`, then
2592
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`
2593
+ is representable as a value of type *index_type*.
2594
+ - If *rank\_* is greater than one and `padding_value` does not equal
2595
+ `dynamic_extent`, then the product of
2596
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`
2597
+ and all values `ext.extent(`k`)` with k in the range of \[`0`,
2598
+ *`rank_`*` - 1`) is representable as a value of type `index_type`.
2599
+
2600
+ *Effects:*
2601
+
2602
+ - Direct-non-list-initializes *extents\_* with `ext`; and
2603
+ - if *rank\_* is greater than one, direct-non-list-initializes
2604
+ *stride-rm2*
2605
+ - with `ext.extent(`*`rank_`*` - 1)` if `padding_value` is
2606
+ `dynamic_extent`,
2607
+ - otherwise with
2608
+ *`LEAST-MULTIPLE-AT-LEAST`*`(padding_value, ext.extent(`*`rank_`*` - 1))`.
2609
+
2610
+ ``` cpp
2611
+ template<class OtherIndexType>
2612
+ constexpr mapping(const extents_type& ext, OtherIndexType pad);
2613
+ ```
2614
+
2615
+ *Constraints:*
2616
+
2617
+ - `is_convertible_v<OtherIndexType, index_type>` is `true`.
2618
+ - `is_nothrow_constructible_v<index_type, OtherIndexType>` is `true`.
2619
+
2620
+ *Preconditions:*
2621
+
2622
+ - `pad` is representable as a value of type `index_type`.
2623
+ - `extents_type::`*`index-cast`*`(pad)` is greater than zero.
2624
+ - If *rank\_* is greater than one, then
2625
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))` is
2626
+ representable as a value of type `index_type`.
2627
+ - If *rank\_* is greater than one, then the product of
2628
+ *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))` and
2629
+ all values `ext.extent(`k`)` with k in the range of \[`0`,
2630
+ *`rank_`*` - 1`) is representable as a value of type `index_type`.
2631
+ - If `padding_value` is not equal to `dynamic_extent`, `padding_value`
2632
+ equals `extents_type::`*`index-cast`*`(pad)`.
2633
+
2634
+ *Effects:* Direct-non-list-initializes *extents\_* with `ext`, and if
2635
+ *rank\_* is greater than one, direct-non-list-initializes *stride-rm2*
2636
+ with *`LEAST-MULTIPLE-AT-LEAST`*`(pad, ext.extent(`*`rank_`*` - 1))`.
2637
+
2638
+ ``` cpp
2639
+ template<class OtherExtents>
2640
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
2641
+ mapping(const layout_right::mapping<OtherExtents>& other);
2642
+ ```
2643
+
2644
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
2645
+ `true`.
2646
+
2647
+ *Mandates:* If `OtherExtents::rank()` is greater than 1, then
2648
+
2649
+ ``` cpp
2650
+ (static-padding-stride == dynamic_extent) ||
2651
+ (OtherExtents::static_extent(rank_ - 1) == dynamic_extent) ||
2652
+ (static-padding-stride == OtherExtents::static_extent(rank_ - 1))
2653
+ ```
2654
+
2655
+ is `true`.
2656
+
2657
+ *Preconditions:*
2658
+
2659
+ - If *`rank_`*` > 1` is `true` and `padding_value == dynamic_extent` is
2660
+ `false`, then `other.stride( `*`rank_`*` - 2)` equals
2661
+ ``` cpp
2662
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2663
+ extents_type::index-cast(other.extents().extent(rank_ - 1)))
2664
+ ```
2665
+
2666
+ and
2667
+ - `other.required_span_size()` is representable as a value of type
2668
+ `index_type`.
2669
+
2670
+ *Effects:* Equivalent to `mapping(other.extents())`.
2671
+
2672
+ ``` cpp
2673
+ template<class OtherExtents>
2674
+ constexpr explicit(rank_ > 0)
2675
+ mapping(const layout_stride::mapping<OtherExtents>& other);
2676
+ ```
2677
+
2678
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
2679
+ `true`.
2680
+
2681
+ *Preconditions:*
2682
+
2683
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
2684
+ `dynamic_extent`, then `other.stride(`*`rank_`*` - 2)` equals
2685
+ ``` cpp
2686
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2687
+ extents_type::index-cast(other.extents().extent(rank_ - 1)))
2688
+ ```
2689
+ - If *rank\_* is greater than 0, then other.stride(*rank\_* - 1) equals
2690
+ 1.
2691
+ - If *rank\_* is greater than 2, then for all r in the range \[`0`,
2692
+ *`rank_`*` - 2`), `other.stride(`r`)` equals
2693
+ ``` cpp
2694
+ (other.extents().rev-prod-of-extents(r) / other.extents().extent(rank_ - 1)) *
2695
+ other.stride(rank_ - 2)
2696
+ ```
2697
+ - `other.required_span_size()` is representable as a value of type
2698
+ `index_type`.
2699
+
2700
+ *Effects:*
2701
+
2702
+ - Direct-non-list-initializes *extents\_* with `other.extents()`; and
2703
+ - if *rank\_* is greater than one, direct-non-list-initializes
2704
+ *stride-rm2* with `other.stride(`*`rank_`*` - 2)`.
2705
+
2706
+ ``` cpp
2707
+ template<class LayoutRightPaddedMapping>
2708
+ constexpr explicit(see below)
2709
+ mapping(const LayoutRightPaddedMapping& other);
2710
+ ```
2711
+
2712
+ *Constraints:*
2713
+
2714
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
2715
+ `true`.
2716
+ - `is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_- type>`
2717
+ is `true`.
2718
+
2719
+ *Mandates:* If *rank\_* is greater than 1, then
2720
+
2721
+ ``` cpp
2722
+ padding_value == dynamic_extent ||
2723
+ LayoutRightPaddedMapping::padding_value == dynamic_extent ||
2724
+ padding_value == LayoutRightPaddedMapping::padding_value
2725
+ ```
2726
+
2727
+ is `true`.
2728
+
2729
+ *Preconditions:*
2730
+
2731
+ - If *rank\_* is greater than 1 and `padding_value` does not equal
2732
+ `dynamic_extent`, then `other.stride(`*`rank_`*` - 2)` equals
2733
+ ``` cpp
2734
+ LEAST-MULTIPLE-AT-LEAST(padding_value,
2735
+ extents_type::index-cast(other.extent(rank_ - 1)))
2736
+ ```
2737
+ - `other.required_span_size()` is representable as a value of type
2738
+ `index_type`.
2739
+
2740
+ *Effects:*
2741
+
2742
+ - Direct-non-list-initializes *extents\_* with `other.extents()`; and
2743
+ - if *rank\_* is greater than one, direct-non-list-initializes
2744
+ *stride-rm2* with `other.stride(rank_ - 2)`.
2745
+
2746
+ *Remarks:* The expression inside `explicit` is equivalent to:
2747
+
2748
+ ``` cpp
2749
+ rank_ > 1 &&
2750
+ (padding_value != dynamic_extent ||
2751
+ LayoutRightPaddedMapping::padding_value == dynamic_extent)
2752
+ ```
2753
+
2754
+ ``` cpp
2755
+ template<class LayoutLeftPaddedMapping>
2756
+ constexpr explicit(see below)
2757
+ mapping(const LayoutLeftPaddedMapping& other) noexcept;
2758
+ ```
2759
+
2760
+ *Constraints:*
2761
+
2762
+ - *`is-layout-left-padded-mapping-of`*`<LayoutLeftPaddedMapping>` is
2763
+ `true` or *`is-mapping-of`*`<layout_left, LayoutLeftPaddedMapping>` is
2764
+ `true`.
2765
+ - *rank\_* equals zero or one.
2766
+ - `is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>`
2767
+ is `true`.
2768
+
2769
+ *Preconditions:* `other.required_span_size()` is representable as a
2770
+ value of type `index_type`.
2771
+
2772
+ *Effects:* Direct-non-list-initializes *extents\_* with
2773
+ `other.extents()`.
2774
+
2775
+ *Remarks:* The expression inside `explicit` is equivalent to:
2776
+
2777
+ ``` cpp
2778
+ !is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>
2779
+ ```
2780
+
2781
+ [*Note 12*: Neither the input mapping nor the mapping to be constructed
2782
+ uses the padding stride in the rank-0 or rank-1 case, so the padding
2783
+ stride affects neither the constraints nor the
2784
+ preconditions. — *end note*]
2785
+
2786
+ ###### Observers <a id="mdspan.layout.rightpad.obs">[[mdspan.layout.rightpad.obs]]</a>
2787
+
2788
+ ``` cpp
2789
+ constexpr array<index_type, rank_> strides() const noexcept;
2790
+ ```
2791
+
2792
+ *Returns:* `array<index_type, `*`rank_`*`>(``stride(P_rank)...``)`.
2793
+
2794
+ ``` cpp
2795
+ constexpr index_type required_span_size() const noexcept;
2796
+ ```
2797
+
2798
+ *Returns:* `0` if the multidimensional index space *extents\_* is empty,
2799
+ otherwise
2800
+ `(*this)(`*`extents_`*`.extent(P_rank) - index_type(1)...) + 1`.
2801
+
2802
+ ``` cpp
2803
+ template<class... Indices>
2804
+ constexpr size_t operator()(Indices... idxs) const noexcept;
2805
+ ```
2806
+
2807
+ *Constraints:*
2808
+
2809
+ - `sizeof...(Indices) == `*`rank_`* is `true`.
2810
+ - `(is_convertible_v<Indices, index_type> && ...)` is `true`.
2811
+ - `(is_nothrow_constructible_v<index_type, Indices> && ...)` is `true`.
2812
+
2813
+ *Preconditions:* `extents_type::`*`index-cast`*`(idxs)` is a
2814
+ multidimensional index in `extents()` [[mdspan.overview]].
2815
+
2816
+ *Returns:*
2817
+ `((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0)`.
2818
+
2819
+ ``` cpp
2820
+ static constexpr bool is_always_exhaustive() noexcept;
2821
+ ```
2822
+
2823
+ *Returns:*
2824
+
2825
+ - If *rank\_* equals zero or one, then `true`;
2826
+ - otherwise, if neither *static-padding-stride* nor *last-static-extent*
2827
+ equal `dynamic_extent`, then
2828
+ *`static-padding-stride`*` == `*`last-static-extent`*;
2829
+ - otherwise, `false`.
2830
+
2831
+ ``` cpp
2832
+ constexpr bool is_exhaustive() const noexcept;
2833
+ ```
2834
+
2835
+ *Returns:* `true` if *rank\_* equals zero or one; otherwise,
2836
+
2837
+ ``` cpp
2838
+ extents_.extent(rank_ - 1) == stride(rank_ - 2)
2839
+ ```
2840
+
2841
+ ``` cpp
2842
+ constexpr index_type stride(rank_type r) const noexcept;
2843
+ ```
2844
+
2845
+ *Preconditions:* `r` is smaller than *rank\_*.
2846
+
2847
+ *Returns:*
2848
+
2849
+ - If `r` equals *`rank_`*` - 1`: `1`;
2850
+ - otherwise, if `r` equals *`rank_`*` - 2`: *stride-rm2*;
2851
+ - otherwise, the product of *stride-rm2* and all values
2852
+ `extents_.extent(`k`)` with k in the range of \[`r + 1`,
2853
+ *`rank_`*` - 1`).
2854
+
2855
+ ``` cpp
2856
+ template<class LayoutRightPaddedMapping>
2857
+ friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;
2858
+ ```
2859
+
2860
+ *Constraints:*
2861
+
2862
+ - *`is-layout-right-padded-mapping-of`*`<LayoutRightPaddedMapping>` is
2863
+ `true`.
2864
+ - `LayoutRightPaddedMapping::extents_type::rank() == `*`rank_`* is
2865
+ `true`.
2866
+
2867
+ *Returns:* `true` if `x.extents() == y.extents()` is `true` and
2868
+ *`rank_`*` < 2 || x.stride(`*`rank_`*` - 2) == y.stride(`*`rank_`*` - 2)`
2869
+ is `true`. Otherwise, `false`.
2870
+
2871
  #### Accessor policy <a id="mdspan.accessor">[[mdspan.accessor]]</a>
2872
 
2873
  ##### General <a id="mdspan.accessor.general">[[mdspan.accessor.general]]</a>
2874
 
2875
  An *accessor policy* defines types and operations by which a reference
 
2878
 
2879
  A range of indices [0, N) is an *accessible range* of a given data
2880
  handle and an accessor if, for each i in the range, the accessor
2881
  policy’s `access` function produces a valid reference to an object.
2882
 
2883
+ In [[mdspan.accessor.reqmts]],
2884
 
2885
  - `A` denotes an accessor policy.
2886
  - `a` denotes a value of type `A` or `const A`.
2887
  - `p` denotes a value of type `A::data_handle_type` or
2888
  `const A::data_handle_type`. \[*Note 1*: The type
 
3022
  constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
3023
  ```
3024
 
3025
  *Effects:* Equivalent to: `return p + i;`
3026
 
3027
+ ##### Class template `aligned_accessor` <a id="mdspan.accessor.aligned">[[mdspan.accessor.aligned]]</a>
3028
+
3029
+ ###### Overview <a id="mdspan.accessor.aligned.overview">[[mdspan.accessor.aligned.overview]]</a>
3030
+
3031
+ ``` cpp
3032
+ namespace std {
3033
+ template<class ElementType, size_t ByteAlignment>
3034
+ struct aligned_accessor {
3035
+ using offset_policy = default_accessor<ElementType>;
3036
+ using element_type = ElementType;
3037
+ using reference = ElementType&;
3038
+ using data_handle_type = ElementType*;
3039
+
3040
+ static constexpr size_t byte_alignment = ByteAlignment;
3041
+
3042
+ constexpr aligned_accessor() noexcept = default;
3043
+ template<class OtherElementType, size_t OtherByteAlignment>
3044
+ constexpr aligned_accessor(
3045
+ aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
3046
+ template<class OtherElementType>
3047
+ constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
3048
+
3049
+ template<class OtherElementType>
3050
+ constexpr operator default_accessor<OtherElementType>() const noexcept;
3051
+
3052
+ constexpr reference access(data_handle_type p, size_t i) const noexcept;
3053
+
3054
+ constexpr typename offset_policy::data_handle_type offset(
3055
+ data_handle_type p, size_t i) const noexcept;
3056
+ };
3057
+ }
3058
+ ```
3059
+
3060
+ *Mandates:*
3061
+
3062
+ - `byte_alignment` is a power of two, and
3063
+ - `byte_alignment >= alignof(ElementType)` is `true`.
3064
+
3065
+ `aligned_accessor` meets the accessor policy requirements.
3066
+
3067
+ `ElementType` is required to be a complete object type that is neither
3068
+ an abstract class type nor an array type.
3069
+
3070
+ Each specialization of `aligned_accessor` is a trivially copyable type
3071
+ that models `semiregular`.
3072
+
3073
+ \[`0`, n) is an accessible range for an object `p` of type
3074
+ `data_handle_type` and an object of type `aligned_accessor` if and only
3075
+ if
3076
+
3077
+ - \[`p`, `p + `n) is a valid range, and,
3078
+ - if n is greater than zero, then
3079
+ `is_sufficiently_aligned<byte_alignment>(p)` is `true`.
3080
+
3081
+ [*Example 1*:
3082
+
3083
+ The following function `compute` uses `is_sufficiently_aligned` to check
3084
+ whether a given `mdspan` with `default_accessor` has a data handle with
3085
+ sufficient alignment to be used with
3086
+ `aligned_accessor<float, 4 * sizeof(float)>`. If so, the function
3087
+ dispatches to a function `compute_using_fourfold_overalignment` that
3088
+ requires fourfold over-alignment of arrays, but can therefore use
3089
+ hardware-specific instructions, such as four-wide SIMD (Single
3090
+ Instruction Multiple Data) instructions. Otherwise, `compute` dispatches
3091
+ to a possibly less optimized function
3092
+ `compute_without_requiring_overalignment` that has no over-alignment
3093
+ requirement.
3094
+
3095
+ ``` cpp
3096
+ void compute_using_fourfold_overalignment(
3097
+ mdspan<float, dims<1>, layout_right, aligned_accessor<float, 4 * alignof(float)>> x);
3098
+
3099
+ void compute_without_requiring_overalignment(
3100
+ mdspan<float, dims<1>, layout_right> x);
3101
+
3102
+ void compute(mdspan<float, dims<1>> x) {
3103
+ constexpr auto byte_alignment = 4 * sizeof(float);
3104
+ auto accessor = aligned_accessor<float, byte_alignment>{};
3105
+ auto x_handle = x.data_handle();
3106
+
3107
+ if (is_sufficiently_aligned<byte_alignment>(x_handle)) {
3108
+ compute_using_fourfold_overalignment(mdspan{x_handle, x.mapping(), accessor});
3109
+ } else {
3110
+ compute_without_requiring_overalignment(x);
3111
+ }
3112
+ }
3113
+ ```
3114
+
3115
+ — *end example*]
3116
+
3117
+ ###### Members <a id="mdspan.accessor.aligned.members">[[mdspan.accessor.aligned.members]]</a>
3118
+
3119
+ ``` cpp
3120
+ template<class OtherElementType, size_t OtherByteAlignment>
3121
+ constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
3122
+ ```
3123
+
3124
+ *Constraints:*
3125
+
3126
+ - `is_convertible_v<OtherElementType(*)[], element_type(*)[]>` is
3127
+ `true`.
3128
+ - `OtherByteAlignment >= byte_alignment` is `true`.
3129
+
3130
+ *Effects:* None.
3131
+
3132
+ ``` cpp
3133
+ template<class OtherElementType>
3134
+ constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
3135
+ ```
3136
+
3137
+ *Constraints:*
3138
+ `is_convertible_v<OtherElementType(*)[], element_type(*)[]>` is `true`.
3139
+
3140
+ *Effects:* None.
3141
+
3142
+ ``` cpp
3143
+ constexpr reference access(data_handle_type p, size_t i) const noexcept;
3144
+ ```
3145
+
3146
+ *Preconditions:* \[`0`, `i + 1`) is an accessible range for `p` and
3147
+ `*this`.
3148
+
3149
+ *Effects:* Equivalent to: `return assume_aligned<byte_alignment>(p)[i];`
3150
+
3151
+ ``` cpp
3152
+ template<class OtherElementType>
3153
+ constexpr operator default_accessor<OtherElementType>() const noexcept;
3154
+ ```
3155
+
3156
+ *Constraints:*
3157
+ `is_convertible_v<element_type(*)[], OtherElementType(*)[]>` is `true`.
3158
+
3159
+ *Effects:* Equivalent to: `return {};`
3160
+
3161
+ ``` cpp
3162
+ constexpr typename offset_policy::data_handle_type
3163
+ offset(data_handle_type p, size_t i) const noexcept;
3164
+ ```
3165
+
3166
+ *Preconditions:* \[`0`, `i + 1`) is an accessible range for `p` and
3167
+ `*this`.
3168
+
3169
+ *Effects:* Equivalent to:
3170
+ `return assume_aligned<byte_alignment>(p) + i;`
3171
+
3172
  #### Class template `mdspan` <a id="mdspan.mdspan">[[mdspan.mdspan]]</a>
3173
 
3174
  ##### Overview <a id="mdspan.mdspan.overview">[[mdspan.mdspan.overview]]</a>
3175
 
3176
  `mdspan` is a view of a multidimensional array of elements.
 
3182
  class mdspan {
3183
  public:
3184
  using extents_type = Extents;
3185
  using layout_type = LayoutPolicy;
3186
  using accessor_type = AccessorPolicy;
3187
+ using mapping_type = layout_type::template mapping<extents_type>;
3188
  using element_type = ElementType;
3189
  using value_type = remove_cv_t<element_type>;
3190
+ using index_type = extents_type::index_type;
3191
+ using size_type = extents_type::size_type;
3192
+ using rank_type = extents_type::rank_type;
3193
+ using data_handle_type = accessor_type::data_handle_type;
3194
+ using reference = accessor_type::reference;
3195
 
3196
  static constexpr rank_type rank() noexcept { return extents_type::rank(); }
3197
  static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
3198
  static constexpr size_t static_extent(rank_type r) noexcept
3199
  { return extents_type::static_extent(r); }
 
3231
  template<class OtherIndexType>
3232
  constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
3233
  template<class OtherIndexType>
3234
  constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
3235
 
3236
+ template<class... OtherIndexTypes>
3237
+ constexpr reference
3238
+ at(OtherIndexTypes... indices) const; // freestanding-deleted
3239
+ template<class OtherIndexType>
3240
+ constexpr reference
3241
+ at(span<OtherIndexType, rank()> indices) const; // freestanding-deleted
3242
+ template<class OtherIndexType>
3243
+ constexpr reference
3244
+ at(const array<OtherIndexType, rank()>& indices) const; // freestanding-deleted
3245
+
3246
  constexpr size_type size() const noexcept;
3247
+ constexpr bool empty() const noexcept;
3248
 
3249
  friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
3250
 
3251
  constexpr const extents_type& extents() const noexcept { return map_.extents(); }
3252
  constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
 
3286
  -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
3287
 
3288
  template<class ElementType, class... Integrals>
3289
  requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
3290
  explicit mdspan(ElementType*, Integrals...)
3291
+ -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;
3292
 
3293
  template<class ElementType, class OtherIndexType, size_t N>
3294
  mdspan(ElementType*, span<OtherIndexType, N>)
3295
  -> mdspan<ElementType, dextents<size_t, N>>;
3296
 
 
3393
  ```
3394
 
3395
  *Constraints:*
3396
 
3397
  - `is_convertible_v<const OtherIndexType&, index_type>` is `true`,
3398
+ - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
3399
+ `true`,
3400
  - `N == rank() || N == rank_dynamic()` is `true`,
3401
  - `is_constructible_v<mapping_type, extents_type>` is `true`, and
3402
  - `is_default_constructible_v<accessor_type>` is `true`.
3403
 
3404
  *Preconditions:* $[0, \texttt{\textit{map_}.required_span_size()})$ is
 
3477
 
3478
  - `is_constructible_v<data_handle_type, const OtherAccessor::data_handle_type&>`
3479
  is `true`, and
3480
  - `is_constructible_v<extents_type, OtherExtents>` is `true`.
3481
 
3482
+ *Preconditions:* $[0, \texttt{\textit{map_}.required_span_size()})$ is
3483
+ an accessible range of *ptr\_* and *acc\_* for values of *ptr\_*,
3484
+ *map\_*, and *acc\_* after the invocation of this constructor.
3485
 
3486
+ For each rank index `r` of `extents_type`,
3487
  `static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)`
3488
  is `true`.
 
 
 
3489
 
3490
  *Effects:*
3491
 
3492
  - Direct-non-list-initializes *ptr\_* with `other.`*`ptr_`*,
3493
  - direct-non-list-initializes *map\_* with `other.`*`map_`*, and
 
3514
  `true`, and
3515
  - `sizeof...(OtherIndexTypes) == rank()` is `true`.
3516
 
3517
  Let `I` be `extents_type::`*`index-cast`*`(std::move(indices))`.
3518
 
3519
+ `I` is a multidimensional index in `extents()`.
3520
 
3521
  [*Note 1*: This implies that
3522
  *`map_`*`(I) < `*`map_`*`.required_span_size()` is
3523
  `true`. — *end note*]
3524
 
 
3548
  ```
3549
 
3550
  is `true`. Equivalent to:
3551
 
3552
  ``` cpp
3553
+ return operator[](extents_type::index-cast(as_const(indices[P]))...);
3554
+ ```
3555
+
3556
+ ``` cpp
3557
+ template<class... OtherIndexTypes>
3558
+ constexpr reference at(OtherIndexTypes... indices) const;
3559
+ ```
3560
+
3561
+ *Constraints:*
3562
+
3563
+ - `(is_convertible_v<OtherIndexTypes, index_type> && ...)` is `true`,
3564
+ - `(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...)` is
3565
+ `true`, and
3566
+ - `sizeof...(OtherIndexTypes) == rank()` is `true`.
3567
+
3568
+ Let `I` be `extents_type::`*`index-cast`*`(std::move(indices))`.
3569
+
3570
+ *Returns:* `(*this)[I...]`.
3571
+
3572
+ *Throws:* `out_of_range` if `I` is not a multidimensional index in
3573
+ `extents()`.
3574
+
3575
+ ``` cpp
3576
+ template<class OtherIndexType>
3577
+ constexpr reference at(span<OtherIndexType, rank()> indices) const;
3578
+ template<class OtherIndexType>
3579
+ constexpr reference at(const array<OtherIndexType, rank()>& indices) const;
3580
+ ```
3581
+
3582
+ *Constraints:*
3583
+
3584
+ - `is_convertible_v<const OtherIndexType&, index_type>` is `true`, and
3585
+ - `is_nothrow_constructible_v<index_type, const OtherIndexType&>` is
3586
+ `true`.
3587
+
3588
+ *Effects:* Let `P` be a parameter pack such that
3589
+
3590
+ ``` cpp
3591
+ is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
3592
+ ```
3593
+
3594
+ is `true`. Equivalent to:
3595
+
3596
+ ``` cpp
3597
+ return at(extents_type::index-cast(as_const(indices[P]))...);
3598
  ```
3599
 
3600
  ``` cpp
3601
  constexpr size_type size() const noexcept;
3602
  ```
 
3606
  [[basic.fundamental]].
3607
 
3608
  *Returns:* `extents().`*`fwd-prod-of-extents`*`(rank())`.
3609
 
3610
  ``` cpp
3611
+ constexpr bool empty() const noexcept;
3612
  ```
3613
 
3614
  *Returns:* `true` if the size of the multidimensional index space
3615
  `extents()` is 0, otherwise `false`.
3616
 
 
3624
  swap(x.ptr_, y.ptr_);
3625
  swap(x.map_, y.map_);
3626
  swap(x.acc_, y.acc_);
3627
  ```
3628
 
3629
+ #### `submdspan` <a id="mdspan.sub">[[mdspan.sub]]</a>
3630
+
3631
+ ##### Overview <a id="mdspan.sub.overview">[[mdspan.sub.overview]]</a>
3632
+
3633
+ The `submdspan` facilities create a new `mdspan` viewing a subset of
3634
+ elements of an existing input `mdspan`. The subset viewed by the created
3635
+ `mdspan` is determined by the `SliceSpecifier` arguments.
3636
+
3637
+ For each function defined in [[mdspan.sub]] that takes a parameter pack
3638
+ named `slices` as an argument:
3639
+
3640
+ - let `index_type` be
3641
+ - `M::index_type` if the function is a member of a class `M`,
3642
+ - otherwise, `remove_reference_t<decltype(src)>::index_type` if the
3643
+ function has a parameter named `src`,
3644
+ - otherwise, the same type as the function’s template argument
3645
+ `IndexType`;
3646
+ - let `rank` be the number of elements in `slices`;
3647
+ - let sₖ be the kᵗʰ element of `slices`;
3648
+ - let Sₖ be the type of sₖ; and
3649
+ - let `map-rank` be an `array<size_t, rank>` such that for each k in the
3650
+ range \[`0`, `rank`), `map-rank[k]` equals:
3651
+ - `dynamic_extent` if Sₖ models `convertible_to<index_type>`,
3652
+ - otherwise, the number of types Sⱼ with j < k that do not model
3653
+ `convertible_to<index_type>`.
3654
+
3655
+ ##### `strided_slice` <a id="mdspan.sub.strided.slice">[[mdspan.sub.strided.slice]]</a>
3656
+
3657
+ `strided_slice` represents a set of `extent` regularly spaced integer
3658
+ indices. The indices start at `offset`, and increase by increments of
3659
+ `stride`.
3660
+
3661
+ ``` cpp
3662
+ namespace std {
3663
+ template<class OffsetType, class ExtentType, class StrideType>
3664
+ struct strided_slice {
3665
+ using offset_type = OffsetType;
3666
+ using extent_type = ExtentType;
3667
+ using stride_type = StrideType;
3668
+
3669
+ [[no_unique_address]] offset_type offset{};
3670
+ [[no_unique_address]] extent_type extent{};
3671
+ [[no_unique_address]] stride_type stride{};
3672
+ };
3673
+ }
3674
+ ```
3675
+
3676
+ `strided_slice` has the data members and special members specified
3677
+ above. It has no base classes or members other than those specified.
3678
+
3679
+ *Mandates:* `OffsetType`, `ExtentType`, and `StrideType` are signed or
3680
+ unsigned integer types, or model `integral-constant-like`.
3681
+
3682
+ [*Note 1*:
3683
+
3684
+ `strided_slice{.offset = 1, .extent = 10, .stride = 3}`
3685
+
3686
+ indicates the indices `1`, `4`, `7`, and `10`. Indices are selected from
3687
+ the half-open interval \[`1`, `1 + 10`).
3688
+
3689
+ — *end note*]
3690
+
3691
+ ##### `submdspan_mapping_result` <a id="mdspan.sub.map.result">[[mdspan.sub.map.result]]</a>
3692
+
3693
+ Specializations of `submdspan_mapping_result` are returned by overloads
3694
+ of `submdspan_mapping`.
3695
+
3696
+ ``` cpp
3697
+ namespace std {
3698
+ template<class LayoutMapping>
3699
+ struct submdspan_mapping_result {
3700
+ [[no_unique_address]] LayoutMapping mapping = LayoutMapping();
3701
+ size_t offset{};
3702
+ };
3703
+ }
3704
+ ```
3705
+
3706
+ `submdspan_mapping_result` has the data members and special members
3707
+ specified above. It has no base classes or members other than those
3708
+ specified.
3709
+
3710
+ `LayoutMapping` shall meet the layout mapping requirements
3711
+ [[mdspan.layout.policy.reqmts]].
3712
+
3713
+ ##### Exposition-only helpers <a id="mdspan.sub.helpers">[[mdspan.sub.helpers]]</a>
3714
+
3715
+ ``` cpp
3716
+ template<class T>
3717
+ constexpr T de-ice(T val) { return val; }
3718
+ template<integral-constant-like T>
3719
+ constexpr auto de-ice(T) { return T::value; }
3720
+
3721
+ template<class IndexType, size_t k, class... SliceSpecifiers>
3722
+ constexpr IndexType first_(SliceSpecifiers... slices);
3723
+ ```
3724
+
3725
+ *Mandates:* `IndexType` is a signed or unsigned integer type.
3726
+
3727
+ Let φₖ denote the following value:
3728
+
3729
+ - sₖ if Sₖ models `convertible_to<IndexType>`;
3730
+ - otherwise, `get<0>(`sₖ`)` if Sₖ models `index-pair-like<IndexType>`;
3731
+ - otherwise, *`de-ice`*`(`sₖ`.offset)` if Sₖ is a specialization of
3732
+ `strided_slice`;
3733
+ - otherwise, `0`.
3734
+
3735
+ *Preconditions:* φₖ is representable as a value of type `IndexType`.
3736
+
3737
+ *Returns:* `extents<IndexType>::`*`index-cast`*`(`φₖ`)`.
3738
+
3739
+ ``` cpp
3740
+ template<size_t k, class Extents, class... SliceSpecifiers>
3741
+ constexpr auto last_(const Extents& src, SliceSpecifiers... slices);
3742
+ ```
3743
+
3744
+ *Mandates:* `Extents` is a specialization of `extents`.
3745
+
3746
+ Let `index_type` be `typename Extents::index_type`.
3747
+
3748
+ Let λₖ denote the following value:
3749
+
3750
+ - *`de-ice`*`(`sₖ`) + 1` if Sₖ models `convertible_to<index_type>`;
3751
+ otherwise
3752
+ - `get<1>(`sₖ`)` if Sₖ models `index-pair-like<index_type>`; otherwise
3753
+ - *`de-ice`*`(`sₖ`.offset)` `+` *`de-ice`*`(`sₖ`.extent)` if Sₖ is a
3754
+ specialization of `strided_slice`; otherwise
3755
+ - `src.extent(k)`.
3756
+
3757
+ *Preconditions:* λₖ is representable as a value of type `index_type`.
3758
+
3759
+ *Returns:* `Extents::`*`index-cast`*`(`λₖ`)`.
3760
+
3761
+ ``` cpp
3762
+ template<class IndexType, size_t N, class... SliceSpecifiers>
3763
+ constexpr array<IndexType, sizeof...(SliceSpecifiers)>
3764
+ src-indices(const array<IndexType, N>& indices, SliceSpecifiers... slices);
3765
+ ```
3766
+
3767
+ *Mandates:* `IndexType` is a signed or unsigned integer type.
3768
+
3769
+ *Returns:* An `array<IndexType, sizeof...(SliceSpecifiers)> src_idx`
3770
+ such that for each k in the range \[`0`, `sizeof...(SliceSpecifiers)`),
3771
+ `src_idx[`k`]` equals
3772
+
3773
+ - *`first_`*`<IndexType, `k`>(slices...)` for each k where
3774
+ *`map-rank`*`[`k`]` equals `dynamic_extent`,
3775
+ - otherwise, *`first_`*`<IndexType, `k`>(slices...)` `+`
3776
+ `indices[`*`map-rank`*`[`k`]]`.
3777
+
3778
+ ##### `submdspan_extents` function <a id="mdspan.sub.extents">[[mdspan.sub.extents]]</a>
3779
+
3780
+ ``` cpp
3781
+ template<class IndexType, size_t... Extents, class... SliceSpecifiers>
3782
+ constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src,
3783
+ SliceSpecifiers... slices);
3784
+ ```
3785
+
3786
+ *Constraints:* `sizeof...(slices)` equals `sizeof...(Extents)`.
3787
+
3788
+ *Mandates:* For each rank index k of `src.extents()`, exactly one of the
3789
+ following is true:
3790
+
3791
+ - Sₖ models `convertible_to<IndexType>`,
3792
+ - Sₖ models `index-pair-like<IndexType>`,
3793
+ - `is_convertible_v<`Sₖ`, full_extent_t>` is `true`, or
3794
+ - Sₖ is a specialization of `strided_slice`.
3795
+
3796
+ *Preconditions:* For each rank index k of `src.extents()`, all of the
3797
+ following are `true`:
3798
+
3799
+ - if Sₖ is a specialization of `strided_slice`
3800
+ - `$s_k$.extent` = 0, or
3801
+ - `$s_k$.stride` > 0
3802
+ - $0 \le \texttt{\textit{first_}<IndexType, $k$>(slices...)}$
3803
+ $\le \texttt{\textit{last_}<$k$>(src, slices...)}$ ≤ `src.extent($k$)`
3804
+
3805
+ Let `SubExtents` be a specialization of `extents` such that:
3806
+
3807
+ - `SubExtents::rank()` equals the number of k such that Sₖ does not
3808
+ model `convertible_to<IndexType>`; and
3809
+ - for each rank index k of `Extents` such that
3810
+ *`map-rank`*`[`k`] != dynamic_extent` is `true`,
3811
+ `SubExtents::static_extent(`*`map-rank`*`[`k`])` equals:
3812
+ - `Extents::static_extent(`k`)` if
3813
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; otherwise
3814
+ - *`de-ice`*`(tuple_element_t<1, `Sₖ`>()) -`
3815
+ *`de-ice`*`(tuple_element_t<0, `Sₖ`>())` if Sₖ models
3816
+ `index-pair-like<IndexType>`, and both `tuple_element_t<0, `Sₖ`>`
3817
+ and `tuple_element_t<1, `Sₖ`>` model `integral-constant-like`;
3818
+ otherwise
3819
+ - `0`, if Sₖ is a specialization of `strided_slice`, whose
3820
+ `extent_type` models *`integral-constant-like`*, for which
3821
+ `extent_type()` equals zero; otherwise
3822
+ - `1 + (`*`de-ice`*`(`Sₖ`::extent_type()) - 1) /`
3823
+ *`de-ice`*`(`Sₖ`::stride_type())`, if Sₖ is a specialization of
3824
+ `strided_slice` whose `extent_type` and `stride_type` model
3825
+ *`integral-constant-like`*;
3826
+ - otherwise, `dynamic_extent`.
3827
+
3828
+ *Returns:* A value `ext` of type `SubExtents` such that for each k for
3829
+ which *`map-rank`*`[`k`] != dynamic_extent` is `true`,
3830
+ `ext.extent(`*`map-rank`*`[`k`])` equals:
3831
+
3832
+ - sₖ`.extent == 0 ? 0 : 1 + (`*`de-ice`*`(`sₖ`.extent) - 1) / `*`de-ice`*`(`sₖ`.stride)`
3833
+ if Sₖ is a specialization of `strided_slice`,
3834
+ - otherwise,
3835
+ *`last_`*`<`k`>(src, slices...) - `*`first_`*`<IndexType, `k`>(slices...)`.
3836
+
3837
+ ##### Specializations of `submdspan_mapping` <a id="mdspan.sub.map">[[mdspan.sub.map]]</a>
3838
+
3839
+ ###### Common <a id="mdspan.sub.map.common">[[mdspan.sub.map.common]]</a>
3840
+
3841
+ The following elements apply to all functions in [[mdspan.sub.map]].
3842
+
3843
+ *Constraints:* `sizeof...(slices)` equals `extents_type::rank()`.
3844
+
3845
+ *Mandates:* For each rank index k of `extents()`, exactly one of the
3846
+ following is true:
3847
+
3848
+ - Sₖ models `convertible_to<index_type>`,
3849
+ - Sₖ models `index-pair-like<index_type>`,
3850
+ - `is_convertible_v<Sₖ, full_extent_t>` is `true`, or
3851
+ - Sₖ is a specialization of `strided_slice`.
3852
+
3853
+ *Preconditions:* For each rank index k of `extents()`, all of the
3854
+ following are `true`:
3855
+
3856
+ - if Sₖ is a specialization of `strided_slice`, `sₖ.extent` is equal to
3857
+ zero or `sₖ.stride` is greater than zero; and
3858
+ - $0 \leq \tcode{\exposid{first_}<index_type, $k$>(slices...)} \\
3859
+ \hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\
3860
+ \hphantom{0 } \leq \tcode{extents().extent($k$)}$
3861
+
3862
+ Let `sub_ext` be the result of `submdspan_extents(extents(), slices...)`
3863
+ and let `SubExtents` be `decltype(sub_ext)`.
3864
+
3865
+ Let `sub_strides` be an
3866
+ `array<SubExtents::index_type, SubExtents::rank()>` such that for each
3867
+ rank index k of `extents()` for which `map-rank[k]` is not
3868
+ `dynamic_extent`, `sub_strides[map-rank[k]]` equals:
3869
+
3870
+ - `stride(k) * de-ice(sₖ.stride)` if Sₖ is a specialization of
3871
+ `strided_slice` and `sₖ.stride < sₖ.extent` is `true`;
3872
+ - otherwise, `stride(k)`.
3873
+
3874
+ Let `P` be a parameter pack such that
3875
+ `is_same_v<make_index_sequence<rank()>, index_sequence<P...>>` is
3876
+ `true`.
3877
+
3878
+ If `first_<index_type, k>(slices...)` equals `extents().extent(k)` for
3879
+ any rank index k of `extents()`, then let `offset` be a value of type
3880
+ `size_t` equal to `(*this).required_span_size()`. Otherwise, let
3881
+ `offset` be a value of type `size_t` equal to
3882
+ `(*this)(first_<index_type, P>(slices...)...)`.
3883
+
3884
+ Given a layout mapping type `M`, a type `S` is a *unit-stride slice for
3885
+ `M`* if
3886
+
3887
+ - `S` is a specialization of `strided_slice` where `S::stride_type`
3888
+ models `integral-constant-like` and `S::stride_type::value` equals
3889
+ `1`,
3890
+ - `S` models `index-pair-like<M::index_type>`, or
3891
+ - `is_convertible_v<S, full_extent_t>` is `true`.
3892
+
3893
+ ###### `layout_left` specialization of `submdspan_mapping` <a id="mdspan.sub.map.left">[[mdspan.sub.map.left]]</a>
3894
+
3895
+ ``` cpp
3896
+ template<class Extents>
3897
+ template<class... SliceSpecifiers>
3898
+ constexpr auto layout_left::mapping<Extents>::submdspan-mapping-impl(
3899
+ SliceSpecifiers... slices) const -> see below;
3900
+ ```
3901
+
3902
+ *Returns:*
3903
+
3904
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
3905
+ `true`;
3906
+ - otherwise,
3907
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
3908
+ `SubExtents::rank() == 0` is `true`;
3909
+ - otherwise,
3910
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
3911
+ - for each k in the range \[`0`, `SubExtents::rank() - 1)`),
3912
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3913
+ - for k equal to `SubExtents::rank() - 1`, Sₖ is a unit-stride slice
3914
+ for `mapping`;
3915
+
3916
+ \[*Note 2*: If the above conditions are true, all Sₖ with k larger
3917
+ than `SubExtents::rank() - 1` are convertible to
3918
+ `index_type`. — *end note*]
3919
+ - otherwise,
3920
+ ``` cpp
3921
+ submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
3922
+ offset}
3923
+ ```
3924
+
3925
+ if for a value u for which u+1 is the smallest value p larger than
3926
+ zero for which Sₚ is a unit-stride slice for `mapping`, the following
3927
+ conditions are met:
3928
+ - S₀ is a unit-stride slice for `mapping`; and
3929
+ - for each k in the range \[u` + 1`, u` + SubExtents::rank() - 1`),
3930
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3931
+ - for k equal to u` + SubExtents::rank() - 1`, Sₖ is a unit-stride
3932
+ slice for `mapping`;
3933
+
3934
+ and where `S_static` is:
3935
+ - `dynamic_extent`, if `static_extent(`k`)` is `dynamic_extent` for
3936
+ any k in the range \[`0`, u` + 1`),
3937
+ - otherwise, the product of all values `static_extent(`k`)` for k in
3938
+ the range \[`0`, u` + 1`);
3939
+ - otherwise,
3940
+ ``` cpp
3941
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3942
+ ```
3943
+
3944
+ ###### `layout_right` specialization of `submdspan_mapping` <a id="mdspan.sub.map.right">[[mdspan.sub.map.right]]</a>
3945
+
3946
+ ``` cpp
3947
+ template<class Extents>
3948
+ template<class... SliceSpecifiers>
3949
+ constexpr auto layout_right::mapping<Extents>::submdspan-mapping-impl(
3950
+ SliceSpecifiers... slices) const -> see below;
3951
+ ```
3952
+
3953
+ *Returns:*
3954
+
3955
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
3956
+ `true`;
3957
+ - otherwise,
3958
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
3959
+ `SubExtents::rank() == 0` is `true`;
3960
+ - otherwise,
3961
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
3962
+ - for each k in the range \[*`rank_`*` - SubExtents::rank() + 1`,
3963
+ *`rank_`*), `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
3964
+ - for k equal to *rank\_* - `SubExtents::rank()`, Sₖ is a unit-stride
3965
+ slice for `mapping`;
3966
+
3967
+ \[*Note 3*: If the above conditions are true, all Sₖ with
3968
+ $k < \texttt{\textit{rank_} - SubExtents::rank()}$ are convertible to
3969
+ `index_type`. — *end note*]
3970
+ - otherwise,
3971
+ ``` cpp
3972
+ submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
3973
+ stride(rank_ - u - 2)), offset}
3974
+ ```
3975
+
3976
+ if for a value u for which rank_ - u - 2 is the largest value p
3977
+ smaller than *`rank_`*` - 1` for which Sₚ is a unit-stride slice for
3978
+ `mapping`, the following conditions are met:
3979
+ - for k equal to *`rank_`*` - 1`, Sₖ is a unit-stride slice for
3980
+ `mapping`; and
3981
+ - for each k in the range
3982
+ \[*`rank_`*` - SubExtents::rank() - `u` + 1`,
3983
+ *`rank_`*` - `u` - 1`), `is_convertible_v<`Sₖ`, full_extent_t>` is
3984
+ `true`; and
3985
+ - for k equal to *`rank_`*` - SubExtents::rank() - `u, Sₖ is a
3986
+ unit-stride slice for `mapping`;
3987
+
3988
+ and where `S_static` is:
3989
+ - `dynamic_extent`, if `static_extent(`k`)` is `dynamic_extent` for
3990
+ any k in the range \[*`rank_`*` - `u` - 1`, *`rank_`*),
3991
+ - otherwise, the product of all values `static_extent(`k`)` for k in
3992
+ the range \[*`rank_`*` - `u` - 1`, *`rank_`*);
3993
+ - otherwise,
3994
+ ``` cpp
3995
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
3996
+ ```
3997
+
3998
+ ###### `layout_stride` specialization of `submdspan_mapping` <a id="mdspan.sub.map.stride">[[mdspan.sub.map.stride]]</a>
3999
+
4000
+ ``` cpp
4001
+ template<class Extents>
4002
+ template<class... SliceSpecifiers>
4003
+ constexpr auto layout_stride::mapping<Extents>::submdspan-mapping-impl(
4004
+ SliceSpecifiers... slices) const -> see below;
4005
+ ```
4006
+
4007
+ *Returns:*
4008
+
4009
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
4010
+ `true`;
4011
+ - otherwise,
4012
+ ``` cpp
4013
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
4014
+ ```
4015
+
4016
+ ###### `layout_left_padded` specialization of `submdspan_mapping` <a id="mdspan.sub.map.leftpad">[[mdspan.sub.map.leftpad]]</a>
4017
+
4018
+ ``` cpp
4019
+ template<class Extents>
4020
+ template<class... SliceSpecifiers>
4021
+ constexpr auto layout_left_padded::mapping<Extents>::submdspan-mapping-impl(
4022
+ SliceSpecifiers... slices) const -> see below;
4023
+ ```
4024
+
4025
+ *Returns:*
4026
+
4027
+ - `submdspan_mapping_result{*this, 0}`, if `Extents::rank() == 0` is
4028
+ `true`;
4029
+ - otherwise,
4030
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
4031
+ *`rank_`*` == 1` is `true` or `SubExtents::rank() == 0` is `true`;
4032
+ - otherwise,
4033
+ `submdspan_mapping_result{layout_left::mapping(sub_ext), offset}`, if
4034
+ - `SubExtents::rank() == 1` is `true` and
4035
+ - S₀ is a unit-stride slice for `mapping`;
4036
+ - otherwise,
4037
+ ``` cpp
4038
+ submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
4039
+ offset}
4040
+ ```
4041
+
4042
+ if for a value u for which u` + 1` is the smallest value p larger than
4043
+ zero for which Sₚ is a unit-stride slice for `mapping`, the following
4044
+ conditions are met:
4045
+ - S₀ is a unit-stride slice for `mapping`; and
4046
+ - for each k in the range \[u` + 1`, u` + SubExtents::rank() - 1`),
4047
+ `is_convertible_v<`Sₖ`, full_extent_t>` is `true`; and
4048
+ - for k equal to u` + SubExtents::rank() - 1`, Sₖ is a unit-stride
4049
+ slice for `mapping`;
4050
+
4051
+ where `S_static` is:
4052
+ - `dynamic_extent`, if *static-padding-stride* is `dynamic_extent` or
4053
+ `static_extent(`k`)` is `dynamic_extent` for any k in the range
4054
+ \[`1`, u` + 1`),
4055
+ - otherwise, the product of *static-padding-stride* and all values
4056
+ `static_extent(`k`)` for k in the range \[`1`, u` + 1`);
4057
+ - otherwise,
4058
+ ``` cpp
4059
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
4060
+ ```
4061
+
4062
+ ###### `layout_right_padded` specialization of `submdspan_mapping` <a id="mdspan.sub.map.rightpad">[[mdspan.sub.map.rightpad]]</a>
4063
+
4064
+ ``` cpp
4065
+ template<class Extents>
4066
+ template<class... SliceSpecifiers>
4067
+ constexpr auto layout_right_padded::mapping<Extents>::submdspan-mapping-impl(
4068
+ SliceSpecifiers... slices) const -> see below;
4069
+ ```
4070
+
4071
+ *Returns:*
4072
+
4073
+ - `submdspan_mapping_result{*this, 0}`, if *`rank_`*` == 0` is `true`;
4074
+ - otherwise,
4075
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
4076
+ *`rank_`*` == 1` is `true` or `SubExtents::rank() == 0` is `true`;
4077
+ - otherwise,
4078
+ `submdspan_mapping_result{layout_right::mapping(sub_ext), offset}`, if
4079
+ - `SubExtents::rank() == 1` is `true` and
4080
+ - for k equal to *`rank_`*` - 1`, Sₖ is a unit-stride slice for
4081
+ `mapping`;
4082
+ - otherwise,
4083
+ ``` cpp
4084
+ submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
4085
+ stride(rank_ - u - 2)), offset}
4086
+ ```
4087
+
4088
+ if for a value u for which *`rank_`*` - `u` - 2` is the largest value
4089
+ p smaller than *`rank_`*` - 1` for which Sₚ is a unit-stride slice for
4090
+ `mapping`, the following conditions are met:
4091
+ - for k equal to *`rank_`*` - 1`, Sₖ is a unit-stride slice for
4092
+ `mapping`; and
4093
+ - for each k in the range
4094
+ \[*`rank_`*` - SubExtents::rank() - `u` + 1`,
4095
+ *`rank_`*` - `u` - 1)`), `is_convertible_v<`Sₖ`, full_extent_t>` is
4096
+ `true`; and
4097
+ - for k equal to *`rank_`*` - SubExtents::rank() - `u, Sₖ is a
4098
+ unit-stride slice for `mapping`;
4099
+
4100
+ and where `S_static` is:
4101
+ - `dynamic_extent` if *static-padding-stride* is `dynamic_extent` or
4102
+ for any k in the range \[*`rank_`*` - `u` - 1`, *`rank_`*` - 1`)
4103
+ `static_extent(`k`)` is `dynamic_extent`,
4104
+ - otherwise, the product of *static-padding-stride* and all values
4105
+ `static_extent(`k`)` with k in the range \[*`rank_`*` - `u` - 1`,
4106
+ *`rank_`*` - 1`);
4107
+ - otherwise,
4108
+ ``` cpp
4109
+ submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
4110
+ ```
4111
+
4112
+ ##### `submdspan` function template <a id="mdspan.sub.sub">[[mdspan.sub.sub]]</a>
4113
+
4114
+ ``` cpp
4115
+ template<class ElementType, class Extents, class LayoutPolicy,
4116
+ class AccessorPolicy, class... SliceSpecifiers>
4117
+ constexpr auto submdspan(
4118
+ const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
4119
+ SliceSpecifiers... slices) -> see below;
4120
+ ```
4121
+
4122
+ Let `index_type` be `typename Extents::index_type`.
4123
+
4124
+ Let `sub_map_offset` be the result of
4125
+ `submdspan_mapping(src.mapping(), slices...)`.
4126
+
4127
+ [*Note 1*: This invocation of `submdspan_mapping` selects a function
4128
+ call via overload resolution on a candidate set that includes the lookup
4129
+ set found by argument-dependent
4130
+ lookup [[basic.lookup.argdep]]. — *end note*]
4131
+
4132
+ *Constraints:*
4133
+
4134
+ - `sizeof...(slices)` equals `Extents::rank()`, and
4135
+ - the expression `submdspan_mapping(src.mapping(), slices...)` is
4136
+ well-formed when treated as an unevaluated operand.
4137
+
4138
+ *Mandates:*
4139
+
4140
+ - `decltype(submdspan_mapping(src.mapping(), slices...))` is a
4141
+ specialization of `submd-span_mapping_result`.
4142
+ - `is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>,`
4143
+ `decltype(submdspan_extents(src.mapping(), slices...))>` is `true`.
4144
+ - For each rank index k of `src.extents()`, exactly one of the following
4145
+ is true:
4146
+ - Sₖ models `convertible_to<index_type>`,
4147
+ - Sₖ models `index-pair-like<index_type>`,
4148
+ - `is_convertible_v<`Sₖ`, full_extent_t>` is `true`, or
4149
+ - Sₖ is a specialization of `strided_slice`.
4150
+
4151
+ *Preconditions:*
4152
+
4153
+ - For each rank index k of `src.extents()`, all of the following are
4154
+ `true`:
4155
+ - if Sₖ is a specialization of `strided_slice`
4156
+ - `$s_k$.extent` = 0, or
4157
+ - `$s_k$.stride` > 0
4158
+ - $0 \le \texttt{\textit{first_}<index_type, $k$>(slices...)}$
4159
+ $\le \texttt{\textit{last_}<$k$>(src.extents(), slices...)}$
4160
+ ≤ `{}src.extent($k$)`
4161
+ - `sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...)`
4162
+ is `true`; and
4163
+ - for each integer pack `I` which is a multidimensional index in
4164
+ `sub_map_offset.mapping.extents()`,
4165
+ ``` cpp
4166
+ sub_map_offset.mapping(I...) + sub_map_offset.offset ==
4167
+ src.mapping()(src-indices(array{I...}, slices...))
4168
+ ```
4169
+
4170
+ is `true`.
4171
+
4172
+ [*Note 2*: These conditions ensure that the mapping returned by
4173
+ `submdspan_mapping` matches the algorithmically expected index-mapping
4174
+ given the slice specifiers. — *end note*]
4175
+
4176
+ *Effects:* Equivalent to:
4177
+
4178
+ ``` cpp
4179
+ auto sub_map_result = submdspan_mapping(src.mapping(), slices...);
4180
+ return mdspan(src.accessor().offset(src.data_handle(), sub_map_result.offset),
4181
+ sub_map_result.mapping,
4182
+ typename AccessorPolicy::offset_policy(src.accessor()));
4183
+ ```
4184
+
4185
+ [*Example 1*:
4186
+
4187
+ Given a rank-3 `mdspan grid3d` representing a three-dimensional grid of
4188
+ regularly spaced points in a rectangular prism, the function
4189
+ `zero_surface` sets all elements on the surface of the 3-dimensional
4190
+ shape to zero. It does so by reusing a function `zero_2d` that takes a
4191
+ rank-2 `mdspan`.
4192
+
4193
+ ``` cpp
4194
+ // zero out all elements in an mdspan
4195
+ template<class T, class E, class L, class A>
4196
+ void zero_2d(mdspan<T, E, L, A> a) {
4197
+ static_assert(a.rank() == 2);
4198
+ for (int i = 0; i < a.extent(0); i++)
4199
+ for (int j = 0; j < a.extent(1); j++)
4200
+ a[i, j] = 0;
4201
+ }
4202
+
4203
+ // zero out just the surface
4204
+ template<class T, class E, class L, class A>
4205
+ void zero_surface(mdspan<T, E, L, A> grid3d) {
4206
+ static_assert(grid3d.rank() == 3);
4207
+ zero_2d(submdspan(grid3d, 0, full_extent, full_extent));
4208
+ zero_2d(submdspan(grid3d, full_extent, 0, full_extent));
4209
+ zero_2d(submdspan(grid3d, full_extent, full_extent, 0));
4210
+ zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent));
4211
+ zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent));
4212
+ zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1));
4213
+ }
4214
+ ```
4215
+
4216
+ — *end example*]
4217
+
4218
  <!-- Link reference definitions -->
4219
  [alg.equal]: algorithms.md#alg.equal
4220
  [alg.sorting]: algorithms.md#alg.sorting
4221
  [algorithm.stable]: library.md#algorithm.stable
4222
  [algorithms]: algorithms.md#algorithms
 
4240
  [associative.reqmts]: #associative.reqmts
4241
  [associative.reqmts.except]: #associative.reqmts.except
4242
  [associative.reqmts.general]: #associative.reqmts.general
4243
  [associative.set.syn]: #associative.set.syn
4244
  [basic.fundamental]: basic.md#basic.fundamental
4245
+ [basic.lookup.argdep]: basic.md#basic.lookup.argdep
4246
  [basic.string]: strings.md#basic.string
4247
  [class.copy.ctor]: class.md#class.copy.ctor
4248
  [class.default.ctor]: class.md#class.default.ctor
4249
  [class.dtor]: class.md#class.dtor
4250
  [container.adaptors]: #container.adaptors
4251
  [container.adaptors.format]: #container.adaptors.format
4252
  [container.adaptors.general]: #container.adaptors.general
4253
  [container.alloc.reqmts]: #container.alloc.reqmts
 
4254
  [container.insert.return]: #container.insert.return
4255
+ [container.intro.reqmts]: #container.intro.reqmts
4256
  [container.node]: #container.node
4257
  [container.node.compat]: #container.node.compat
4258
  [container.node.cons]: #container.node.cons
4259
  [container.node.dtor]: #container.node.dtor
4260
  [container.node.modifiers]: #container.node.modifiers
 
4282
  [expr.const]: expr.md#expr.const
4283
  [flat.map]: #flat.map
4284
  [flat.map.access]: #flat.map.access
4285
  [flat.map.capacity]: #flat.map.capacity
4286
  [flat.map.cons]: #flat.map.cons
4287
+ [flat.map.cons.alloc]: #flat.map.cons.alloc
4288
  [flat.map.defn]: #flat.map.defn
4289
  [flat.map.erasure]: #flat.map.erasure
4290
  [flat.map.modifiers]: #flat.map.modifiers
4291
  [flat.map.overview]: #flat.map.overview
4292
  [flat.map.syn]: #flat.map.syn
4293
  [flat.multimap]: #flat.multimap
4294
  [flat.multimap.cons]: #flat.multimap.cons
4295
+ [flat.multimap.cons.alloc]: #flat.multimap.cons.alloc
4296
  [flat.multimap.defn]: #flat.multimap.defn
4297
  [flat.multimap.erasure]: #flat.multimap.erasure
4298
  [flat.multimap.overview]: #flat.multimap.overview
4299
  [flat.multiset]: #flat.multiset
4300
  [flat.multiset.cons]: #flat.multiset.cons
4301
+ [flat.multiset.cons.alloc]: #flat.multiset.cons.alloc
4302
  [flat.multiset.defn]: #flat.multiset.defn
4303
  [flat.multiset.erasure]: #flat.multiset.erasure
4304
  [flat.multiset.modifiers]: #flat.multiset.modifiers
4305
  [flat.multiset.overview]: #flat.multiset.overview
4306
  [flat.set]: #flat.set
4307
  [flat.set.cons]: #flat.set.cons
4308
+ [flat.set.cons.alloc]: #flat.set.cons.alloc
4309
  [flat.set.defn]: #flat.set.defn
4310
  [flat.set.erasure]: #flat.set.erasure
4311
  [flat.set.modifiers]: #flat.set.modifiers
4312
  [flat.set.overview]: #flat.set.overview
4313
  [flat.set.syn]: #flat.set.syn
 
4320
  [forward.list.modifiers]: #forward.list.modifiers
4321
  [forward.list.ops]: #forward.list.ops
4322
  [forward.list.overview]: #forward.list.overview
4323
  [forward.list.syn]: #forward.list.syn
4324
  [hash.requirements]: library.md#hash.requirements
4325
+ [hive]: #hive
4326
+ [hive.capacity]: #hive.capacity
4327
+ [hive.cons]: #hive.cons
4328
+ [hive.erasure]: #hive.erasure
4329
+ [hive.modifiers]: #hive.modifiers
4330
+ [hive.operations]: #hive.operations
4331
+ [hive.overview]: #hive.overview
4332
+ [hive.syn]: #hive.syn
4333
+ [inplace.vector]: #inplace.vector
4334
+ [inplace.vector.capacity]: #inplace.vector.capacity
4335
+ [inplace.vector.cons]: #inplace.vector.cons
4336
+ [inplace.vector.data]: #inplace.vector.data
4337
+ [inplace.vector.erasure]: #inplace.vector.erasure
4338
+ [inplace.vector.modifiers]: #inplace.vector.modifiers
4339
+ [inplace.vector.overview]: #inplace.vector.overview
4340
+ [inplace.vector.syn]: #inplace.vector.syn
4341
  [iterator.concept.contiguous]: iterators.md#iterator.concept.contiguous
4342
  [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
4343
  [iterator.requirements]: iterators.md#iterator.requirements
4344
  [iterator.requirements.general]: iterators.md#iterator.requirements.general
4345
  [list]: #list
 
4355
  [map.cons]: #map.cons
4356
  [map.erasure]: #map.erasure
4357
  [map.modifiers]: #map.modifiers
4358
  [map.overview]: #map.overview
4359
  [mdspan.accessor]: #mdspan.accessor
4360
+ [mdspan.accessor.aligned]: #mdspan.accessor.aligned
4361
+ [mdspan.accessor.aligned.members]: #mdspan.accessor.aligned.members
4362
+ [mdspan.accessor.aligned.overview]: #mdspan.accessor.aligned.overview
4363
  [mdspan.accessor.default]: #mdspan.accessor.default
4364
  [mdspan.accessor.default.members]: #mdspan.accessor.default.members
4365
  [mdspan.accessor.default.overview]: #mdspan.accessor.default.overview
4366
  [mdspan.accessor.general]: #mdspan.accessor.general
4367
  [mdspan.accessor.reqmts]: #mdspan.accessor.reqmts
4368
  [mdspan.extents]: #mdspan.extents
4369
  [mdspan.extents.cmp]: #mdspan.extents.cmp
4370
  [mdspan.extents.cons]: #mdspan.extents.cons
4371
  [mdspan.extents.dextents]: #mdspan.extents.dextents
4372
+ [mdspan.extents.dims]: #mdspan.extents.dims
4373
  [mdspan.extents.expo]: #mdspan.extents.expo
4374
  [mdspan.extents.obs]: #mdspan.extents.obs
4375
  [mdspan.extents.overview]: #mdspan.extents.overview
4376
  [mdspan.layout]: #mdspan.layout
4377
  [mdspan.layout.general]: #mdspan.layout.general
4378
  [mdspan.layout.left]: #mdspan.layout.left
4379
  [mdspan.layout.left.cons]: #mdspan.layout.left.cons
4380
  [mdspan.layout.left.obs]: #mdspan.layout.left.obs
4381
  [mdspan.layout.left.overview]: #mdspan.layout.left.overview
4382
+ [mdspan.layout.leftpad]: #mdspan.layout.leftpad
4383
+ [mdspan.layout.leftpad.cons]: #mdspan.layout.leftpad.cons
4384
+ [mdspan.layout.leftpad.expo]: #mdspan.layout.leftpad.expo
4385
+ [mdspan.layout.leftpad.obs]: #mdspan.layout.leftpad.obs
4386
+ [mdspan.layout.leftpad.overview]: #mdspan.layout.leftpad.overview
4387
  [mdspan.layout.policy.overview]: #mdspan.layout.policy.overview
4388
  [mdspan.layout.policy.reqmts]: #mdspan.layout.policy.reqmts
4389
  [mdspan.layout.reqmts]: #mdspan.layout.reqmts
4390
  [mdspan.layout.right]: #mdspan.layout.right
4391
  [mdspan.layout.right.cons]: #mdspan.layout.right.cons
4392
  [mdspan.layout.right.obs]: #mdspan.layout.right.obs
4393
  [mdspan.layout.right.overview]: #mdspan.layout.right.overview
4394
+ [mdspan.layout.rightpad]: #mdspan.layout.rightpad
4395
+ [mdspan.layout.rightpad.cons]: #mdspan.layout.rightpad.cons
4396
+ [mdspan.layout.rightpad.expo]: #mdspan.layout.rightpad.expo
4397
+ [mdspan.layout.rightpad.obs]: #mdspan.layout.rightpad.obs
4398
+ [mdspan.layout.rightpad.overview]: #mdspan.layout.rightpad.overview
4399
  [mdspan.layout.stride]: #mdspan.layout.stride
4400
  [mdspan.layout.stride.cons]: #mdspan.layout.stride.cons
4401
  [mdspan.layout.stride.expo]: #mdspan.layout.stride.expo
4402
  [mdspan.layout.stride.obs]: #mdspan.layout.stride.obs
4403
  [mdspan.layout.stride.overview]: #mdspan.layout.stride.overview
4404
  [mdspan.mdspan]: #mdspan.mdspan
4405
  [mdspan.mdspan.cons]: #mdspan.mdspan.cons
4406
  [mdspan.mdspan.members]: #mdspan.mdspan.members
4407
  [mdspan.mdspan.overview]: #mdspan.mdspan.overview
4408
  [mdspan.overview]: #mdspan.overview
4409
+ [mdspan.sub]: #mdspan.sub
4410
+ [mdspan.sub.extents]: #mdspan.sub.extents
4411
+ [mdspan.sub.helpers]: #mdspan.sub.helpers
4412
+ [mdspan.sub.map]: #mdspan.sub.map
4413
+ [mdspan.sub.map.common]: #mdspan.sub.map.common
4414
+ [mdspan.sub.map.left]: #mdspan.sub.map.left
4415
+ [mdspan.sub.map.leftpad]: #mdspan.sub.map.leftpad
4416
+ [mdspan.sub.map.result]: #mdspan.sub.map.result
4417
+ [mdspan.sub.map.right]: #mdspan.sub.map.right
4418
+ [mdspan.sub.map.rightpad]: #mdspan.sub.map.rightpad
4419
+ [mdspan.sub.map.stride]: #mdspan.sub.map.stride
4420
+ [mdspan.sub.overview]: #mdspan.sub.overview
4421
+ [mdspan.sub.strided.slice]: #mdspan.sub.strided.slice
4422
+ [mdspan.sub.sub]: #mdspan.sub.sub
4423
  [mdspan.syn]: #mdspan.syn
4424
  [multimap]: #multimap
4425
  [multimap.cons]: #multimap.cons
4426
  [multimap.erasure]: #multimap.erasure
4427
  [multimap.modifiers]: #multimap.modifiers
 
4443
  [queue.mod]: #queue.mod
4444
  [queue.ops]: #queue.ops
4445
  [queue.special]: #queue.special
4446
  [queue.syn]: #queue.syn
4447
  [random.access.iterators]: iterators.md#random.access.iterators
4448
+ [re.results]: text.md#re.results
4449
  [res.on.data.races]: library.md#res.on.data.races
4450
  [sequence.reqmts]: #sequence.reqmts
4451
  [sequences]: #sequences
4452
  [sequences.general]: #sequences.general
4453
  [set]: #set
4454
  [set.cons]: #set.cons
4455
  [set.erasure]: #set.erasure
4456
+ [set.modifiers]: #set.modifiers
4457
  [set.overview]: #set.overview
4458
  [span.cons]: #span.cons
4459
  [span.deduct]: #span.deduct
4460
  [span.elem]: #span.elem
4461
  [span.iterators]: #span.iterators
 
4471
  [stack.general]: #stack.general
4472
  [stack.mod]: #stack.mod
4473
  [stack.ops]: #stack.ops
4474
  [stack.special]: #stack.special
4475
  [stack.syn]: #stack.syn
4476
+ [stacktrace.basic]: diagnostics.md#stacktrace.basic
4477
  [strings]: strings.md#strings
4478
  [swappable.requirements]: library.md#swappable.requirements
4479
  [temp.deduct]: temp.md#temp.deduct
 
4480
  [temp.type]: temp.md#temp.type
4481
+ [term.structural.type]: temp.md#term.structural.type
4482
  [term.trivially.copyable.type]: basic.md#term.trivially.copyable.type
4483
  [unord]: #unord
4484
  [unord.general]: #unord.general
4485
  [unord.hash]: utilities.md#unord.hash
4486
  [unord.map]: #unord.map
 
4503
  [unord.req.except]: #unord.req.except
4504
  [unord.req.general]: #unord.req.general
4505
  [unord.set]: #unord.set
4506
  [unord.set.cnstr]: #unord.set.cnstr
4507
  [unord.set.erasure]: #unord.set.erasure
4508
+ [unord.set.modifiers]: #unord.set.modifiers
4509
  [unord.set.overview]: #unord.set.overview
4510
  [unord.set.syn]: #unord.set.syn
4511
  [vector]: #vector
4512
  [vector.bool]: #vector.bool
4513
  [vector.bool.fmt]: #vector.bool.fmt