1. Revision History
1.1. P0009r8: Pre 2018-11-SanDiego Mailing
- 
     Refinement based upon updated prototype / reference implementation 
1.2. P0009r7: Post 2018-06-Rapperswil Mailing
- 
     wording reworked based on guidance: LWG review at 2018-06-Rapperswil 
- 
     usage of span 
- 
     namespace for library TS std :: experimental :: fundamentals_v3 
1.3. P0009r6 : Pre 2018-06-Rapperswil Mailing
P0009r5 was not taken up at 2018-03-Jacksonville meeting. Related LEWG review of P0900 at 2018-03-Jacksonville meeting
LEWG Poll: We want the ability to customize the access to elements of span (ability to restrict, etc):
span < T , N , Accessor = ... > 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 1 | 1 | 1 | 2 | 8 | 
LEWG Poll: We want the customization of 
basic_mdspan < T , Extents , Mapper , Accessor > mdspan < T , N ... > 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 3 | 4 | 5 | 1 | 0 | 
LEWG Poll: We want the customization of 
basic_mdspan < T , Extents , Properties ... > 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 1 | 2 | 2 | 6 | 2 | 
Changes from P0009r5 due to related LEWG reviews:
- 
     Replaced variadic property list with extents, layout mapping, and accessor properties. 
- 
     Incorporated P0454r1. - 
       Added accessor policy concept. 
- 
       Renamed mdspan basic_mdspan 
- 
       Added a mdspan basic_mdspan 
 
- 
       
1.4. P0009r5 : Pre 2018-03-Jacksonville Mailing
LEWG review of P0009r4 at 2017-11-Albuquerque meeting
LEWG Poll: We should be able to index with 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 2 | 11 | 1 | 1 | 0 | 
Against comment - there is not a proven needs for this feature.
LEWG Poll: We should be able to index with 1d 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 0 | 8 | 7 | 0 | 0 | 
LEWG Poll: We should put the requirement on "rank() <= N" back to "rank()==N".
Unanimous consent
LEWG Poll: With the editorial changes from small group, plus the above polls, forward this to LWG for Fundamentals v3.
Unanimous consent
Changes from P0009r4:
- 
     Removed nullptr constructor. 
- 
     Added constexpr to indexing operator. 
- 
     Indexing operator requires that rank () == sizeof ...( indices ) 
- 
     Fixed typos in examples and moved them to appendix. 
- 
     Converted note on how extentions to access properties may cause reference to be a proxy type to an "see below" to make it normative. 
1.5. P0009r4 : Pre 2017-11-Albuquerque Mailing
LEWG review at 2017-03-Kona meeting
LEWG review of P0546r1 at 2017-03-Kona meeting
LEWG Poll: Should we have a single template that covers both single and multi-dimensional spans?
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 1 | 6 | 2 | 6 | 3 | 
Changes from P0009r3:
- 
     Align with P0122r5 span proposal. 
- 
     Rename to mdspan span 
- 
     Move preferred array extents mechanism to appendix. 
- 
     Expose codomain as a span 
- 
     Add layout mapping concept. 
1.6. P0009r3 : Post 2016-06-Oulu Mailing
LEWG did not like the name 
LEWG Poll: Are member 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 0 | 2 | 4 | 3 | 1 | 
LEWG Poll: Want this proposal to provide range-producing functions
outside 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 0 | 1 | 3 | 2 | 3 | 
LEWG Poll: Want a separate proposal to explore iteration design space?
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 9 | 1 | 0 | 0 | 0 | 
Changes from P0009r2:
- 
     Removed iterator support; a future paper will be written on the subject. 
- 
     Noted difference between multidimensional array versus language’s array-of-array-of-array... 
- 
     Clearly describe requirements for the embedded type aliases ( element_type reference 
- 
     Expanded description of how the variadic properties list would work. 
- 
     Stopped allowing array_ref < T [ N ] > array_ref < extents < N >> 
- 
     Clarified domain, codomain, and domain -> codomain mapping specifications. 
- 
     Consistently use extent and extents for the multidimensional index space. 
1.7. P0009r2 : Pre 2016-06-Oulu Mailing
LEWG review at 2016-02-Jacksonville.
Changes from P0009r1:
- 
     Adding details for extensibility of layout mapping. 
- 
     Move motivation, examples, and relaxed incomplete array type proposal to separate papers. 
1.8. P0009r1 : Pre 2016-02-Jacksonville Mailing
LEWG Poll: What should this feature be called?
| Name | # | 
|---|---|
|  | 5 | 
|  | 9 | 
|  | 6 | 
|  | 6 | 
|  | 6 | 
|  | 0 | 
|  | 7 | 
|  | 1 | 
|  | 3 | 
|  | 0 | 
LEWG Poll: Do we want 0-length static extents?
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 3 | 4 | 2 | 3 | 0 | 
LEWG POLL: Do we want the language to support syntaxes like 
| Syntax | # | 
|---|---|
|  | 12 | 
|  | 4 | 
|  | 5 | 
|  | 4 | 
|  | 2 | 
|  | 4 | 
|  | 9 | 
LEWG POLL: Do we want the variadic property list in template args
(either raw or in 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 3 | 6 | 3 | 0 | 0 | 
LEWG POLL: Do we want the per-view bounds-checking knob?
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 3 | 4 | 1 | 2 | 1 | 
Changes from P0009r0:
- 
     Renamed view array_ref 
- 
     How are users allowed to add properties? Needs elaboration in paper. 
- 
     view < int [][][] >:: layout 
- 
     Rename is_regular is_affine Regular 
- 
     Make static span(), operator(), constructor, etc variadic. 
- 
     Demonstrate the need for improper access in the paper. 
- 
     In operator () 
1.9. P0009r0 : Pre 2015-10-Kona Mailing
Original non-owning multidimensional array reference (
1.10. Related Activity
Related LEWG review of P0546r1 at 2017-11-Albuquerque meeting
LEWG Poll: 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 5 | 3 | 2 | 2 | 0 | 
LEWG Poll: 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 0 | 10 | 1 | 5 | 0 | 
Authors agreed to bring a separate paper ([P0900r0]) discussing how the variadic properties will work.
2. Description
    The proposed polymorphic multidimensional array reference (
A multidimensional array is not an array-of-array-of-array-of...
The multidimensional array abstraction has been fundamental to numerical computations for over five decades. However, the C/C++ language provides only a one-dimensional array abstraction which can be composed into array-of-array-of-array-of... types. While such types have some similarity to multidimensional arrays, they do not provide adequate multidimensional array functionality of this proposal. Two critical functionality differences are (1) multiple dynamic extents and (2) polymorphic mapping of multi-indices to element objects.
Optimized Implementation of Layout Mapping
We intend the layout mapping of a multi-index to be a constant-time 
3. Editing Notes
The proposed changes are relative to the working draft of the standard as of N4750.
The � character is used to denote a placeholder section number, table number, or paragraph number which the editor shall determine.
Add the header 
Add the header 
4. Wording
Text in blockquotes is not proposed wording.The � character is used to denote a placeholder section number which the editor shall determine.
 Copy the entire [views] subclause from the current draft, since it is
needed for basic_mdspan 
   
 Add the following paragraphs to [views.general]:
    �. The header 
�. The 
 Add the following subclauses to the end of the [views] subclause in the current draft:
 26.7.� Header 
namespace std { namespace experimental { namespace fundamentals_v3 { // [mdspan.extents], class template extents template < ptrdiff_t ... StaticExtents > class extents ; // [mdspan.layout], Layout mapping policies class layout_left ; class layout_right ; class layout_stride ; // [mdspan.accessor.basic] template < class ElementType > class accessor_basic ; // [mdspan.basic], class template mdspan template < class ElementType , class Extents , class LayoutPolicy = layout_right , class AccessorPolicy = accessor_basic < ElementType > > class basic_mdspan ; template < class T , ptrdiff_t ... Extents > using mdspan = basic_mdspan < T , extents < Extents ... >> ; // [mdspan.extents.compare], extents comparison operators template < ptrdiff_t ... LHS , ptrdiff_t ... RHS > constexpr bool operator == ( const extents < LHS ... >& lhs , const extents < RHS ... >& rhs ) noexcept ; template < ptrdiff_t ... LHS , ptrdiff_t ... RHS > constexpr bool operator != ( const extents < LHS ... >& lhs , const extents < RHS ... >& rhs ) noexcept ; // [mdspan.subspan], subspan creation template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy , class ... SliceSpecifiers > struct mdspan_subspan { // exposition only using extents_t = see below ; using layout_t = see below ; using type = basic_mdspan < ElementType , extents_t , layout_t , typename AccessorPolicy :: offset_policy > ; }; template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy , class ... SliceSpecifiers > using mdspan_subspan_t = // exposition only typename mdspan_subspan < ElementType , Extents , LayoutPolicy , AccessorPolicy , SliceSpecifiers ... >:: type ; template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy , class ... SliceSpecifiers > mdspan_subspan_t < ElementType , Extents , LayoutPolicy , AccessorPolicy , SliceSpecifiers ... > subspan ( const basic_mdspan < ElementType , Extents , LayoutPolicy , AccessorPolicy >& src , SliceSpecifiers ... slices ) noexcept ; // tag supporting subspan struct all_type { explicit all_type () = default ; }; inline constexpr all_type all = all_type {}; }}} 
26.7.� Class template 
26.7.�.1 Overview [mdspan.extents.overview]
- 
     An extents 
- 
     A multidimensional index space of rank is the Cartesian product 0) ⨯ [0, N1) ⨯ ... ⨯ [0, NR-1) of half-open integer intervals. 
- 
     The dynamic extents of an extents Extents dynamic_extent Extents Extents 
- 
     An extents 
- 
     If any template arguments in Extents dynamic_extent 
namespace std { namespace experimental { namespace fundamentals_v3 { template < ptrdiff_t ... Extents > class extents { public : // types using index_type = ptrdiff_t ; // [mdspan.extents.cons], Constructors and assignment constexpr extents () noexcept ; constexpr extents ( const extents & ) noexcept ; constexpr extents ( extents && ) noexcept ; template < class ... IndexType > constexpr extents ( IndexType ... dynamic_extents ) noexcept ; template < class IndexType , size_t rank_dynamic > constexpr extents ( const array < IndexType , rank_dynamic >& ) noexcept ; template < ptrdiff_t ... OtherExtents > constexpr extents ( const extents < OtherExtents ... >& other ); ~ extents () = default ; constexpr extents & operator = ( const extents & ) noexcept = default ; constexpr extents & operator = ( extents && ) noexcept = default ; template < ptrdiff_t ... OtherExtents > constexpr extents & operator = ( const extents < OtherExtents ... >& other ); // [mdspan.extents.obs], Observers of the domain multidimensional index space static constexpr size_t rank () noexcept ; static constexpr size_t rank_dynamic () noexcept ; static constexpr index_type static_extent ( size_t ) noexcept ; constexpr index_type extent ( size_t ) const noexcept ; private : array < index_type , rank_dynamic () > dynamic_extents_ ; // exposition only }; }}} 
26.7.�.2 Constructors and assignment [mdspan.extents.cons]
constexpr extents () noexcept ; 
- 
     Effects: Aggregate-initializes dynamic_extents_ { } 
- 
     Ensures: Let equal rank () r static_extent ( r ) dynamic_extent extent ( r ) 0 
constexpr extents ( const extents & other ); constexpr extents ( extents && other ); 
- 
     Effects: Initializes dynamic_extents_ other . dynamic_extents_ 
- 
     Ensures: Let equal rank () r extent ( r ) other . extent ( r ) 
template < ptrdiff_t ... OtherExtents > constexpr extents ( const extents < OtherExtents ... >& other ); 
- 
     Requires: Let equal rank () r static_extent ( r ) dynamic_extent static_extent ( r ) other . extent ( r ) 
- 
     Constraints: sizeof ...( Extents ) sizeof ...( OtherExtents ) 
- 
     Effects: Let equal rank () r static_extent ( r ) dynamic_extent dynamic_extents_ [ r ] other . extent ( r ) 
- 
     Ensures: * this == other true.
- 
     Throws: Nothing. 
template < class ... IndexType > constexpr extents ( IndexType ... dynamic_extents ) noexcept ; 
- 
     Requires: ( dynamic_extents >= 0 ) && ... true.
- 
     Constraints: - 
       is_convertible_v < IndexType , index_type > && ... true, and
- 
       sizeof ...( dynamic_extents ) == rank_dynamic () true.
 
- 
       
- 
     Effects: Aggregate-initializes dynamic_extents_ { dynamic_extents ...} 
- 
     Ensures: extent ( ) dynamic_extents 
template < class IndexType , size_t rank_dynamic > constexpr extents ( const array < IndexType , rank_dynamic > & dynamic_extents ) noexcept ; 
- 
     Requires: Let equal rank_dynamic () i dynamic_extents [ i ] >= 0 true.
- 
     Constraints: is_convertible_v < IndexType , index_type > true.
- 
     Effects: Initializes dynamic_extents_ dynamic_extents 
- 
     Ensures: extent ( ) dynamic_extents [ i ] 
template < ptrdiff_t ... OtherExtents > constexpr extents & operator = ( const extents < OtherExtents ... >& other ); 
- 
     Requires: Let equal rank () r static_extent ( r ) != dynamic_extent || static_extent ( r ) == other . extent ( r ) true.
- 
     Constraints: sizeof ...( Extents ) == sizeof ...( OtherExtents ) true.
- 
     Effects: Let equal rank () r static_extent ( r ) dynamic_extent dynamic_extents_ [ r ] other . extent ( r ) 
- 
     Ensures: * this == other true.
- 
     Returns: * this 
- 
     Throws: Nothing. 
 26.7.�.3 Observers of the domain multidimensional index space [mdspan.extents.obs]
static constexpr size_t rank () const noexcept ; 
- 
     Returns: sizeof ...( Extents ) 
static constexpr size_t rank_dynamic () const noexcept ; 
- 
     Returns: - 
       If sizeof ...( Extents ) == 0 true, then zero;
- 
       Otherwise, (( Extents == dynamic_extent ) + ...) 
 
- 
       
[Note: This is the number of dynamic extents. —end note]
static constexpr index_type static_extent ( size_t r ) const noexcept ; 
- 
     Returns: - 
       If 0 <= r rank () r Extents 
- 
       Otherwise, 1. 
 
- 
       
constexpr index_type extent ( size_t r ) const noexcept ; 
- 
     Returns: - 
       If static_extent ( r ) == dynamic_extent dynamic_extents_ [ r ] 
- 
       Otherwise, static_extent ( r ) 
 
- 
       
 26.7.�.4 
template < ptrdiff_t ... LHS , ptrdiff_t ... RHS > constexpr bool operator == ( const extents < LHS ... >& lhs , const extents < RHS ... >& rhs ) noexcept ; 
- 
     Returns: - 
       If lhs . rank () == rhs . rank () && lhs . extents ( r ) == rhs . extents ( r ) truefor allr [ 0 , lhs . rank ()) true;
- 
       Otherwise, false.
 
- 
       
template < ptrdiff_t ... LHS , ptrdiff_t ... RHS > constexpr bool operator != ( const extents < LHS ... >& lhs , const extents < RHS ... >& rhs ) noexcept ; 
- 
     Returns: ! ( lhs == rhs ) 
 
 26.7.� Layout mapping policy [mdspan.layout]
26.7.�.1 Layout mapping requirements [mdspan.layout.reqs]
- 
     A layout mapping policy is a class that contains a layout mapping, a nested class template. 
- 
     A layout mapping policy meets the requirements in Table �. 
- 
     A layout mapping meets the requirements of Cpp17DefaultConstructible, Cpp17CopyAssignable, Cpp17EqualityComparable, and the requirements in Table �. 
- 
     In Table �: - 
       MP 
- 
       E extents 
- 
       e E 
- 
       r r e . rank () 
- 
       If k ... k ... e k ... e i ... j ... e i ... j ... r sizeof ...( i ) == E :: rank () true, 0 <= r <e . extent ( r ) sizeof ...( j ) == E :: rank () e . extent ( r ) 
- 
       M 
- 
       m M i ... 
 
- 
       
Table � — Layout mapping policy and layout mapping requirements
| Expression | Return Type | Returns | Requires | 
|---|---|---|---|
|  |  | ||
|  |  | Returns:  | |
|  |  | Returns: Mapping of a multi-index . | Requires: 0 <= . | 
|  |  | Returns: If the multidimensional index space that defines is empty, then zero,
      else 1 plus the maximum value offor allin. | |
|  |  | Returns: trueif for every,istrue. | |
|  |  | Returns: trueif the set defined byequals the set {0, ...,}. | |
|  |  | Returns: trueif there exists an integer 
       
       r such that, for allandin,
       if all members ofandare equal
       except for exactly one r-th member where 
       
       r equals 
       
       r + 1, 
       thenequals 
       
       r. | |
|  |  | Returns: trueifistruefor any object of type. | |
|  |  | Returns: trueifistruefor any object of type. | |
|  |  | Returns: true if istruefor any object of type. | |
|  |  | Returns: 
       
       r, as defined for above.
      We say that 
       
       r is the stride of ordinate. | Requires: istrue. | 
 
 26.7.�.2 Class layout_left [mdspan.layout.left]
- 
     layout_left layout_left :: template mapping 
- 
     layout_left 
- 
     If Extents extents 
namespace std { namespace experimental { namespace fundamentals_v3 { struct layout_left { template < class Extents > class mapping { public : // [mdspan.layout.left.cons], layout_left::mapping constructors constexpr mapping () noexcept ; constexpr mapping ( const mapping & other ) noexcept ; constexpr mapping ( mapping && other ) noexcept ; constexpr mapping ( const Extents & e ) noexcept ; template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other ); mapping & operator = () noexcept = default ; mapping & operator = ( const mapping & other ) noexcept = default ; template < class OtherExtents > constexpr mapping & operator = ( const mapping < OtherExtents >& other ); // [mdspan.layout.left.ops], layout_left::mapping operations Extents extents () const noexcept ; constexpr typename Extents :: index_type required_span_size () const noexcept ; template < class ... Indices > typename Extents :: index_type operator ()( Indices ... is ) const ; static constexpr bool is_always_unique (); static constexpr bool is_always_contiguous (); static constexpr bool is_always_strided (); constexpr bool is_unique () const ; constexpr bool is_contiguous () const ; constexpr bool is_strided () const ; template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ; template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ; typename Extents :: index_type stride ( size_t rank ) const noexcept ; private : Extents extents_ ; // exposition only }; }; }}} 
26.7.�.2.1 
constexpr mapping () noexcept ; 
- 
     Effects: Default-initializes extents_ 
- 
     Ensures: extents () == Extents () true.
constexpr mapping ( const mapping & other ) noexcept ; 
- 
     Effects: Initializes extents_ other . extents_ 
- 
     Ensures: extents () == other . extents () true.
constexpr mapping ( mapping && other ) noexcept ; 
- 
     Effects: Initializes extents_ move ( other . extents_ ) 
- 
     Ensures: extents () other . extents () 
constexpr mapping ( const Extents & e ) noexcept ; 
- 
     Effects: Initializes extents_ e 
- 
     Ensures: extents () == e true.
template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other ); 
- 
     Requires: other . extents () extents_ 
- 
     Effects: Initializes extents_ other . extents () 
- 
     Ensures: extents () == other . extents () true.
- 
     Throws: Nothing. 
26.7.�.2.2 
Extents extents () const noexcept ; 
- 
     Returns: extents_ 
typename Extents :: index_type required_span_size () const noexcept ; 
- 
     Returns: The product of extents (). extent ( r ) r r extents (). rank () 
template < class ... Indices > typename Extents :: index_type operator ()( Indices ... i ) const ; 
- 
     Constraints: - 
       sizeof ...( Indices ) == extents (). rank () true, and
- 
       is_convertible_v < Indices , typename Extents :: index_type > && ... true.
 
- 
       
- 
     Requires: 0 <= array { i ...}[ r ] extents (). extent ( r ) r [ 0 , extents (). rank ()) 
- 
     Returns: Let k denote the k-th member of i ... extents (). rank () - 
       If R is zero, then zero; 
- 
       Otherwise, the sum of k stride ( k ) k 
 
- 
       
static constexpr bool is_always_unique (); static constexpr bool is_always_contiguous (); static constexpr bool is_always_strided (); constexpr bool is_unique () const ; constexpr bool is_contiguous () const ; constexpr bool is_strided () const ; 
- 
     Returns: true.
typename Extents :: index_type stride ( size_t r ) const ; 
- 
     Returns: - 
       If r 
- 
       Otherwise, the product of extents (). extent ( k ) k r k k i ... 
 
- 
       
template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ; 
- 
     Returns: extents () == other . extents () true.
template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ; 
- 
     Returns: extents () != other . extents () true.
 
 26.7.�.3 Class layout_right [mdspan.layout.right]
- 
     layout_right layout_right :: template mapping 
- 
     The layout mapping property layout_right 
- 
     If Extents extents 
namespace std { namespace experimental { namespace fundamentals_v3 { struct layout_right { template < class Extents > class mapping { public : // [mdspan.layout.right.cons], layout_left::mapping constructors constexpr mapping () noexcept ; constexpr mapping ( const mapping & other ) noexcept ; constexpr mapping ( mapping && other ) noexcept ; constexpr mapping ( Extents e ) noexcept ; template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other ); mapping & operator = () noexcept = default ; mapping & operator = ( const mapping & other ) noexcept = default ; template < class OtherExtents > constexpr mapping & operator = ( const mapping < OtherExtents >& other ); // [mdspan.layout.right.ops], layout_right::mapping operations Extents extents () const noexcept ; constexpr typename Extents :: index_type required_span_size () const noexcept ; template < class ... Indices > typename Extents :: index_type operator ()( Indices ... is ) const ; static constexpr bool is_always_unique () noexcept ; static constexpr bool is_always_contiguous () noexcept ; static constexpr bool is_always_strided () noexcept ; constexpr bool is_unique () const noexcept ; constexpr bool is_contiguous () const noexcept ; constexpr bool is_strided () const noexcept ; typename Extents :: index_type stride ( size_t rank ) const noexcept ; template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ; template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ; private : Extents extents_ ; // exposition only }; }; } 
26.7.�.3.1 
constexpr mapping () noexcept ; 
- 
     Effects: Default-initializes extents_ 
- 
     Ensures: extents () == Extents () true.
constexpr mapping ( const mapping & other ) noexcept ; 
- 
     Effects: Initializes extents_ other . extents_ 
- 
     Ensures: extents () == other . extents () true.
constexpr mapping ( mapping && other ) noexcept ; 
- 
     Effects: Initializes extents_ move ( other . extents_ ) 
- 
     Ensures: extents () other . extents () 
constexpr mapping ( Extents e ) noexcept ; 
- 
     Effects: Initializes extents_ e 
- 
     Ensures: extents () == e true.
template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other ); 
- 
     Requires: other . extents () extents_ 
- 
     Effects: Initializes extents_ other . extents () 
- 
     Ensures: extents () == other . extents () true.
- 
     Throws: Nothing. 
26.7.�.3.2 
Extents extents () const noexcept ; 
- 
     Returns: extents_ 
typename Extents :: index_type required_span_size () const noexcept ; 
- 
     Returns: The product of extents (). extent ( r ) r r extents (). rank () 
template < class ... Indices > typename Extents :: index_type operator ()( Indices ... i ) const noexcept ; 
- 
     Constraints: - 
       sizeof ...( Indices ) == extents (). rank () true, and
- 
       is_convertible_v < Indices , typename Extents :: index_type > && ... true.
 
- 
       
- 
     Requires: 0 <= array { i ...}[ r ] extents (). extent ( r ) r [ 0 , extents (). rank ()) 
- 
     Returns: Let k denote the k-th member of i ... extents (). rank () - 
       If R is zero, then zero; 
- 
       Otherwise, the sum of k stride ( k ) k 
 
- 
       
static constexpr bool is_always_unique () noexcept ; static constexpr bool is_always_contiguous () noexcept ; static constexpr bool is_always_strided () noexcept ; constexpr bool is_unique () const noexcept ; constexpr bool is_contiguous () const noexcept ; constexpr bool is_strided () const noexcept ; 
- 
     Returns: true.
typename Extents :: index_type stride ( size_t r ) const noexcept ; 
- 
     Returns: Equivalent to s Extents :: index_type s = 1 ; for ( size_t k = r + 1 ; k < extents (). rank (); ++ k ) s *= extents (). extent ( r ); 
template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ; 
- 
     Returns: extents () == other . extents () true.
template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ; 
- 
     Returns: extents () != other . extents () true.
 
 26.7.�.4 Class 
- 
     layout_stride 
- 
     The layout mapping property layout_stride 
- 
     If Extents extents 
namespace std { namespace experimental { namespace fundamentals_v3 { struct layout_stride { template < class Extents > class mapping { public : // [mdspan.layout.stride.cons], layout_stride::mapping constructors constexpr mapping () noexcept ; constexpr mapping ( mapping const & other ) noexcept ; constexpr mapping ( mapping && other ) noexcept ; constexpr mapping ( const Extents & e , const array < typename Extents :: index_type , Extents :: rank () >& s ) noexcept ; template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other ); mapping & operator = () noexcept = default ; mapping & operator = ( const mapping & other ) noexcept = default ; template < class OtherExtents > constexpr mapping & operator = ( const mapping < OtherExtents >& other ); // [mdspan.layout.stride.ops], layout_stride::mapping operations Extents extents () const noexcept ; array < typename Extents :: index_type , Extents :: rank () > strides () const noexcept ; constexpr typename Extents :: index_type required_span_size () const noexcept ; template < class ... Indices > typename Extents :: index_type operator ()( Indices ... is ) const ; static constexpr bool is_always_unique () noexcept ; static constexpr bool is_always_contiguous () noexcept ; static constexpr bool is_always_strided () noexcept ; constexpr bool is_unique () const noexcept ; constexpr bool is_contiguous () const noexcept ; constexpr bool is_strided () const noexcept ; typename Extents :: index_type stride ( size_t rank ) const noexcept ; template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ; template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ; private : Extents extents_ ; // exposition only array < typename Extents :: index_type , Extents :: rank () > strides_ ; // exposition only }; }; }}} 
26.7.�.4.1 layout_stride::mapping constructors [mdspan.layout.stride.cons]
constexpr mapping () noexcept ; 
- 
     Effects: Default-initializes extents_ 
- 
     Ensures: - 
       extents () == Extents () true, and
- 
       strides () == array < typename Extents :: index_type , Extents :: rank () > () true.
 
- 
       
constexpr mapping ( const mapping & other ) noexcept ; 
- 
     Effects: Initializes extents_ other . extents_ 
- 
     Ensures: - 
       extents () == other . extents () true, and
- 
       strides () == other . strides () true.
 
- 
       
constexpr mapping ( mapping && other ) noexcept ; 
- 
     Effects: Initializes extents_ move ( other . extents_ ) 
- 
     Ensures: - 
       extents () other . extents () 
- 
       strides () other . strides () 
 
- 
       
Let R equalconstexpr mapping ( Extents e , array < typename Extents :: index_type , Extents :: rank () > s ) noexcept ; 
Extents :: rank () p size_t p [ i ] i i - 
     Requires: - 
       s [ i ] > 0 truefor 0 <i 
- 
       If R is nonzero, then there exists a permutation of the integers 0, ..., R-1 such that s ( p [ i ]) >= s ( p [ i - 1 ]) * e . extent ( p [ i - 1 ]) truefor 1 <=i 
 
- 
       
- 
     Effects: - 
       Initializes extents_ e 
- 
       initializes strides_ s 
 
- 
       
- 
     Ensures: - 
       extents () == e true, and
- 
       strides () == s true.
 
- 
       
- 
     Throws: Nothing. 
template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other ); 
- 
     Requires: other . extents () extents_ 
- 
     Effects: - 
       Initializes extents_ other . extents () 
- 
       initializes strides_ other . strides () 
 
- 
       
- 
     Ensures: - 
       extents () == other . extents () true, and
- 
       strides () == other . strides () true.
 
- 
       
- 
     Throws: Nothing. 
26.7.�.4.2 layout_stride::mapping operations [mdspan.layout.stride.ops]
Extents extents () const noexcept ; 
- 
     Returns: extents_ 
array < typename Extents :: index_type , Extents :: rank () > strides () const noexcept ; 
- 
     Returns: strides_ 
typename Extents :: index_type required_span_size () const noexcept ; 
- 
     Returns: The maximum of extents (). extent ( r ) * stride ( r ) r r extents (). rank () 
template < class ... Indices > typename Extents :: index_type operator ()( Indices ... i ) const ; 
- 
     Constraints: - 
       sizeof ...( Indices ) == Extents :: rank () true, and
- 
       is_convertible_v < Indices , typename Extents :: index_type > && ... true.
 
- 
       
- 
     Requires: 0 <= array { i ...}[ r ] extents (). extent ( r ) r [ 0 , extents (). rank ()) 
- 
     Returns: Let k denote the k-th member of i ... Extents :: rank () s strides () - 
       If R is zero, then zero; 
- 
       Otherwise, the sum of k s [ k ] k 
 
- 
       
- 
     Throws: Nothing. 
static constexpr bool is_always_unique () noexcept ; static constexpr bool is_always_strided () noexcept ; constexpr bool is_unique () const noexcept ; constexpr bool is_strided () const noexcept ; 
- 
     Returns: true.
static constexpr bool is_always_contiguous () noexcept ; 
- 
     Returns: false.
Let R equalconstexpr bool is_contiguous () const noexcept ; 
Extents :: rank () p size_t p [ i ] i i - 
     Returns: - 
       If R true;
- 
       Else, if there is a permutation of the integers 0, ..., R-1 such that min ( stride ( p [ i ]) i stride ( p [ i ]) stride ( p [ i - 1 ]) * extents (). extent ( p [ i - 1 ]) i true;
- 
       Otherwise, false.
 
- 
       
typename Extents :: index_type stride ( size_t r ) const noexcept ; 
- 
     Returns: strides_ [ r ] 
template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ; 
- 
     Returns: extents () == other . extents () 
template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ; 
- 
     Returns: extents () != other . extents () 
 
26.7.� Accessor Policy [mdspan.accessor]
An accessor policy defines types and operations by which a contiguous set of objects of a particular type are accessed.
 26.7.�.1 Accessor policy requirements [mdspan.accessor.reqs]
An accessor policy defines:
- 
     a handle to a single element of type element_type 
- 
     a handle to a contiguous set of elements of type element_type access 
- 
     conversion of a handle to a contiguous set of elements, to a pointer [conv.array]; and 
- 
     getting a handle to the contiguous subset of elements beginning at an integer offset value. 
[Note: The type of 
[Note: The constructor of the object representing the contiguous set of objects
may impose additional restrictions on the contiguous set of objects, 
such as restricting 
In Table �:
- 
     A 
- 
     a A 
- 
     p A :: pointer 
- 
     i j ptrdiff_t 
Table �: Accessor policy requirements
| Expression | Return Type | Notes/Returns/Requires | 
|---|---|---|
|  | Type of each element in the contiguous set of elements. | |
|  | Type through which the range of elements are accessed. Requires: Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable. | |
|  | Type through which an element is accessed. | |
|  | Accessor policy for accessing a pointer returned by .Requires: 
 | |
|  |  | Returns: A pointer that references the same location as . | 
|  |  | Returns: An object which provides access to the -th element in the range of elements that starts at. | 
|  |  | Returns: A pointer that references the same location as  Requires: 
 | 
 26.7.�.2 Class 
- 
     accessor_basic 
- 
     If T 
namespace std { namespace experimental { namespace fundamentals_v3 { template < class ElementType > struct accessor_basic { using offset_policy = accessor_basic ; using element_type = ElementType ; using reference = ElementType & ; using pointer = ElementType * ; constexpr typename offset_policy :: pointer offset ( pointer p , ptrdiff_t i ) const noexcept ; constexpr reference access ( pointer p , ptrdiff_t i ) const noexcept ; constexpr pointer decay ( pointer p ) const noexcept ; }; }}} 
constexpr typename offset_policy :: pointer offset ( pointer p , ptrdiff_t i ) const noexcept ; 
- 
     Requires: p + i 
- 
     Returns: p + i 
constexpr reference access ( pointer p , ptrdiff_t i ) const noexcept ; 
- 
     Requires: p + i 
- 
     Returns: p [ i ] 
constexpr pointer decay ( pointer p ) const noexcept ; 
- 
     Returns: p 
 
 26.7.� Class template 
- 
     The basic_mdspan span 
- 
     The multi-index domain space is the Cartesian product of the extents: extent ( 0 ) extent ( 1 ) extent ( rank () - 1 ) 
- 
     As with span span basic_mdspan 
- 
     ElementType 
- 
     Extents extents 
- 
     LayoutPolicy 
- 
     AccessorPolicy std :: is_same_v < typename AccessorPolicy :: element_type , ElementType > false, otherwise the program is ill-formed.
namespace std { namespace experimental { namespace fundamentals_v3 { template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy > class basic_mdspan { public : // Domain and codomain types using extents_type = Extents ; using layout_type = LayoutPolicy ; using accessor_type = AccessorPolicy ; using mapping_type = typename layout_type :: template mapping_type < extents_type > ; using element_type = typename accessor_type :: element_type ; using value_type = remove_cv_t < element_type > ; using index_type = ptrdiff_t ; using difference_type = ptrdiff_t ; using pointer = typename accessor_type :: pointer ; using reference = typename accessor_type :: reference ; // [mdspan.basic.cons], basic_mdspan constructors, assignment, and destructor constexpr basic_mdspan () noexcept = default ; constexpr basic_mdspan ( const basic_mdspan & ) noexcept = default ; constexpr basic_mdspan ( basic_mdspan && ) noexcept ; template < class ... IndexType > explicit constexpr basic_mdspan ( pointer p , IndexType ... dynamic_extents ); template < class IndexType , size_t N > explicit constexpr basic_mdspan ( pointer p , const array < IndexType , N >& dynamic_extents ); constexpr basic_mdspan ( pointer p , const mapping_type & m ); constexpr basic_mdspan ( pointer p , const mapping_type & m , const accessor_type & a ); template < class OtherElementType , class OtherExtents , class OtherLayoutPolicy , class OtherAccessorPolicy > constexpr basic_mdspan ( const basic_mdspan < OtherElementType , OtherExtents , OtherLayoutPolicy , OtherAccessorPolicy >& other ); ~ basic_mdspan () = default ; constexpr basic_mdspan & operator = ( const basic_mdspan & ) noexcept = default ; constexpr basic_mdspan & operator = ( basic_mdspan && ) noexcept = default ; template < class OtherElementType , class OtherExtents , class OtherLayoutPolicy , class OtherAccessorPolicy > constexpr basic_mdspan & operator = ( const basic_mdspan < OtherElementType , OtherExtents , OtherLayoutPolicy , OtherAccessorPolicy >& other ) noexcept ; // [mdspan.basic.mapping], basic_mdspan mapping domain multi-index to access codomain element constexpr reference operator []( index_type ) const noexcept ; template < class ... IndexType > constexpr reference operator ()( IndexType ... indices ) const noexcept ; template < class IndexType , size_t N > constexpr reference operator ()( const array < IndexType , N >& indices ) const noexcept ; accessor_type accessor () const ; // [mdspan.basic.domobs], basic_mdspan observers of the domain multidimensional index space static constexpr int rank () noexcept ; static constexpr int rank_dynamic () noexcept ; static constexpr index_type static_extent ( size_t ) noexcept ; constexpr Extents extents () const noexcept ; constexpr index_type extent ( size_t ) const noexcept ; constexpr index_type size () const noexcept ; constexpr index_type unique_size () const noexcept ; // [mdspan.basic.codomain], basic_mdspan observers of the codomain constexpr span < element_type > span () const noexcept ; constexpr pointer data () const noexcept ; // [mdspan.basic.obs], basic_mdspan observers of the mapping static constexpr bool is_always_unique () noexcept ; static constexpr bool is_always_contiguous () noexcept ; static constexpr bool is_always_strided () noexcept ; constexpr mapping_type mapping () const noexcept ; constexpr bool is_unique () const noexcept ; constexpr bool is_contiguous () const noexcept ; constexpr bool is_strided () const noexcept ; constexpr index_type stride ( size_t ) const ; private : accessor_type acc_ ; // exposition only mapping_type map_ ; // exposition only pointer ptr_ ; // exposition only }; }}} 
 26.7.�.1 
constexpr basic_mdspan () noexcept = default ; 
- 
     Effects: - 
       Zero-initializes ptr_ 
- 
       Value-initializes map_ 
- 
       Value-initializes acc_ 
 
- 
       
- 
     Ensures: - 
       size () == 0 true,
- 
       extents () == Extents () true, and
- 
       mapping () == mapping_type () true.
 
- 
       
constexpr basic_mdspan ( const basic_mdspan & other ) noexcept = default ; 
- 
     Effects: - 
       Initializes ptr_ other . ptr_ 
- 
       Initializes map_ other . map_ 
- 
       Initializes acc_ other . acc_ 
 
- 
       
- 
     Ensures: - 
       size () == other . size () true,
- 
       extents () == other . extents () true, and
- 
       mapping () == other . mapping () true.
 
- 
       
constexpr basic_mdspan ( basic_mdspan && other ) noexcept ; 
- 
     Effects: - 
       Initializes ptr_ move ( other . ptr_ ) 
- 
       Initializes map_ move ( other . map_ ) 
- 
       Initializes acc_ move ( other . acc_ ) 
 
- 
       
template < class ... IndexType > explicit constexpr basic_mdspan ( pointer ptr , IndexType ... dynamic_extents ); 
- 
     Constraints: - 
       ( is_convertible_v < IndexType , index_type > && ...) true,
- 
       sizeof ...( dynamic_extents ) == rank_dynamic () true,
- 
       is_constructible_v < mapping_type , Extents > true, and
- 
       is_default_constructible_v < accessor_type > true.
 
- 
       
- 
     Effects: - 
       Initializes ptr_ ptr 
- 
       Initializes map_ Extents ( dynamic_extents ...) 
- 
       Value-initializes acc_ 
 
- 
       
- 
     Ensures: - 
       extents () == Extents ( dynamic_extents ...) true, and
- 
       mapping () == mapping_type ( Extents ( dynamic_extents ...)) true.
 
- 
       
- 
     Throws: Nothing. 
template < class IndexType , size_t N > explicit constexpr basic_mdspan ( pointer p , const array < IndexType , N >& dynamic_extents ); 
- 
     Constraints: - 
       is_convertible_v < IndexType , index_type > true,
- 
       N == rank_dynamic () true,
- 
       is_constructible_v < mapping_type , Extents > true, and
- 
       is_default_constructible_v < accessor_type > true.
 
- 
       
- 
     Effects: Equivalent to basic_mdspan ( p , dynamic_extents [ Rs ]...) Rs ... index_sequence < Rs ... > make_index_sequence < N > 
- 
     Throws: Nothing. 
constexpr basic_mdspan ( pointer p , const mapping_type & m ); 
- 
     Constraints: is_default_constructible_v < accessor_type > true.
- 
     Effects: - 
       Initializes ptr_ p 
- 
       Initializes map_ m 
- 
       Value-initializes acc_ 
 
- 
       
- 
     Ensures: - 
       extents () == m . extents () true, and
- 
       mapping () == m true.
 
- 
       
- 
     Throws: Nothing. 
constexpr basic_mdspan ( pointer p , const mapping_type & m , const accessor_type & a ); 
- 
     Effects: - 
       Initializes ptr_ p 
- 
       Initializes map_ m 
- 
       Initializes acc_ a 
 
- 
       
- 
     Ensures: - 
       extents () == m . extents () true, and
- 
       mapping () == m true.
 
- 
       
- 
     Throws: Nothing. 
template < class OtherElementType , class OtherExtents , class OtherLayoutPolicy , class OtherAccessor > constexpr basic_mdspan ( const basic_mdspan < OtherElementType , OtherExtents , OtherLayoutPolicy , OtherAccessor >& other ); 
- 
     Constraints: - 
       is_convertible_v < OtherLayoutPolicy :: template mapping < OtherExtents > , mapping_type true,
- 
       is_convertible_v < OtherAccessor , Accessor > true, and
- 
       is_convertible_v < OtherAccessor :: pointer , pointer > true.
- 
       is_convertible_v < OtherExtents , extents_type > true
- 
       For all r [ 0 , rank ()) other . static_extent ( r ) != dynamic_extent && static_extent ( r ) != dynamic_extent true, thenother . static_extent ( r ) == static_extent ( r ) true.
 
- 
       
- 
     Requires: - 
       For all r [ 0 , rank ()) other . static_extent ( r ) == dynamic_extent || static_extent ( r ) == dynamic_extent true, thenother . extent ( r ) == extent ( r ) true.
 
- 
       
- 
     Effects: - 
       Initializes ptr_ other . ptr_ 
- 
       Initializes map_ other . map_ 
- 
       Initializes acc_ other . acc_ 
 
- 
       
- 
     Ensures: - 
       extents () == Extents ( other . extents ()) true, and
- 
       mapping () == mapping_type ( other . mapping ()) true.
 
- 
       
- 
     Throws: Nothing. 
template < class OtherElementType , class OtherExtents , class OtherLayoutPolicy , class OtherAccessor > constexpr basic_mdspan & operator = ( const basic_mdspan < OtherElementType , OtherExtents , OtherLayoutPolicy , OtherAccessor >& other ); 
- 
     Constraints: - 
       is_assignable_v < mapping_type , OtherLayoutPolicy :: template mapping < OtherExtents >> true,
- 
       is_assignable_v < Accessor , OtherAccessor > true, and
- 
       is_assignable_v < pointer , OtherAccessor :: pointer > true.
- 
       OtherExtents :: rank () == rank () true
- 
       For all r [ 0 , rank ()) other . static_extent ( r ) != dynamic_extent && static_extent ( r ) != dynamic_extent true, thenother . static_extent ( r ) == static_extent ( r ) true.
 
- 
       
- 
     Requires: - 
       For all r [ 0 , rank ()) other . static_extent ( r ) == dynamic_extent || static_extent ( r ) == dynamic_extent true, thenother . extent ( r ) == extent ( r ) true.
 
- 
       
- 
     Effects: - 
       Assigns other . ptr_ ptr_ 
- 
       Assigns other . map_ map_ 
- 
       Assigns other . acc_ acc_ 
 
- 
       
- 
     Ensures: - 
       extents () == Extents ( other . extents ()) true, and
- 
       mapping () == mapping_type ( other . mapping ()) true.
 
- 
       
- 
     Throws: Nothing. 
 26.7.�.2 
constexpr reference operator []( index_type i ) const ; 
- 
     Constraints: rank () == 1 true.
- 
     Requires: acc_ . access ( ptr_ , map_ ( i )) 
- 
     Effects: Equivalent to return ( * this )( i ); 
template < class ... IndexType > constexpr reference operator ()( IndexType ... indices ) const ; 
- 
     Constraints: - 
       ( is_convertible_v < IndexType , index_type > && ...) true, and
- 
       sizeof ...( IndexType ) == rank () true.
 
- 
       
- 
     Requires: acc_ . access ( ptr_ , map_ ( indices ...)) 
- 
     Effects: Equivalent to return acc_ . access ( ptr_ , map_ ( indices ...)); 
- 
     Throws: Nothing. 
template < class IndexType , size_t N > constexpr reference operator ()( const array < IndexType , N >& indices ) const ; 
- 
     Constraints: - 
       is_convertible_v < IndexType , index_type > true, and
- 
       rank () == N true.
 
- 
       
- 
     Requires: acc_ . access ( ptr_ , std :: apply ( map_ , indices )) 
- 
     Effects: Equivalent to return std :: apply ( * this , indices ); 
- 
     Throws: nothing. 
accessor_type accessor () const ; 
- 
     Returns: acc_ 
 26.7.�.3 
static constexpr int rank () noexcept ; 
- 
     Returns: Extents :: rank () 
static constexpr int rank_dynamic () noexcept ; 
- 
     Returns: Extents :: rank_dynamic () 
static constexpr index_type static_extent ( size_t r ) noexcept ; 
- 
     Returns: Extents :: static_extent ( r ) 
constexpr Extents extents () const noexcept ; 
- 
     Returns: mapping (). extents () 
constexpr index_type extent ( size_t r ) const noexcept ; 
- 
     Returns: extents (). extent ( r ) 
constexpr index_type size () const noexcept ; 
- 
     Returns: Product of extent ( r ) r r extents (). rank () 
constexpr index_type unique_size () const noexcept ; 
- 
     Returns: The number of unique elements in the codomain. [Note: If mapping (). is_unique () true, this is identical tosize () 
 26.7.�.3 
constexpr span < element_type > span () const noexcept ; 
- 
     Returns: Equivalent to span < element_type > ( acc_ . decay ( ptr_ ), required_span_size ()) 
constexpr pointer data () const noexcept ; 
- 
     Returns: ptr_ 
 26.7.�.4 
static constexpr bool is_always_unique () noexcept ; 
- 
     Returns: mapping_type :: is_always_unique () 
static constexpr bool is_always_contiguous () noexcept ; 
- 
     Returns: mapping_type :: is_always_contiguous () 
static constexpr bool is_always_strided () noexcept ; 
- 
     Returns: mapping_type :: is_always_strided () 
constexpr mapping_type mapping () const noexcept ; 
- 
     Returns: map_ 
constexpr bool is_unique () const noexcept ; 
- 
     Returns: mapping (). is_unique () 
constexpr bool is_contiguous () const noexcept ; 
- 
     Returns: mapping (). is_contiguous () 
constexpr bool is_strided () const noexcept ; 
- 
     Returns: mapping (). is_strided () 
constexpr index_type stride ( size_t r ) const ; 
- 
     Returns: mapping (). stride ( r ) 
 
 26.7.� subspan [mdspan.subspan]
namespace std { namespace experimental { namespace fundamentals_v3 { // [mdspan.subspan], subspan creation template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy , class ... SliceSpecifiers > struct mdspan_subspan { // exposition only using extents_t = see below ; using layout_t = see below ; using type = basic_mdspan < ElementType , extents_t , layout_t , typename AccessorPolicy :: offset_policy > ; }; template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy , class ... SliceSpecifiers > using mdspan_subspan_t = // exposition only typename mdspan_subspan < ElementType , Extents , LayoutPolicy , AccessorPolicy , SliceSpecifiers ... >:: type ; template < class ElementType , class Extents , class LayoutPolicy , class AccessorPolicy , class ... SliceSpecifiers > mdspan_subspan_t < ElementType , Extents , LayoutPolicy , AccessorPolicy , SliceSpecifiers ... > subspan ( const basic_mdspan < ElementType , Extents , LayoutPolicy , AccessorPolicy >& src , SliceSpecifiers ... slices ) noexcept ; }}} 
The 
    Let 
    Let ρ be true.
   
    Define true.
Define the exposition-only 
In the exposition-only 
- 
     The extents_t extents subspan 
- 
     The layout_t 
- 
     The type subspan 
[Note: High-quality implementations will avoid 
Let 
- 
     If is_convertible_v < r , ptrdiff_t > first [ r ] r last [ r ] first [ r ] 
- 
     Else, if is_convertible_v < r , pair < ptrdiff_t , ptrdiff_t >> first [ r ] p . first last [ r ] p . second p r pair < ptrdiff_t , ptrdiff_t > 
- 
     Else, if is_convertible_v < r , all_type > first [ r ] = 0 last [ r ] src . extent ( r ) 
- 
     Requires: - 
       sizeof ( slices ...) src . rank () 
- 
       For 0 <= r sizeof ...( slices ) 0 <= first [ r ] && first [ r ] < last [ r ] && last [ r ] <= src . extent ( r ) true.
 
- 
       
- 
     Constraints: - 
       LayoutPolicy layout_left layout_right layout_stride subspan 
- 
       For 0 <= k sizeof ...( slices ) is_convertible_v < , ptrdiff_t > || is_convertible_v < , pair < ptrdiff_t , ptrdiff_t >> || is_convertible_v < , all_type > true.
 
- 
       
- 
     Ensures: - 
       sub . rank () 
- 
       mdspan_subspan < ElementType , Extents , LayoutPolicy , AccessorPolicy , SliceSpecifiers ... >:: extents_t :: rank () 
- 
       Let the pack i ... sub k sub . extents ( k ) k k k i ... j ... src get_seq < k > ( rank_map ) j ... first [ get_seq < k > ( rank_map )] k k r j ... first [ r ] r r src . rank () r rank_map sub ( i ...) src ( j ...) 
- 
       For 0 <= k sub . extent ( k ) last [ get_seq < k > ( rank_map )] - first [ get_seq < k > ( rank_map )] 
- 
       If src . is_strided () sub . is_strided () true, and for 0 <=k sub . stride ( k ) src . stride ( get_seq < k > ( rank_map )) 
- 
       For 0 <= k rmk get_seq < k > ( rank_map ) src . static_extent ( rmk ) dynamic_extent is_convertible_v < rmk , all_type > true, thensub . static_extent ( k ) src . static_extent ( rmk ) 
 
- 
       
[Note: Example of 
- end note]// Create a mapping typedef extents < 3 , dynamic_extent , 7 > Extents3D ; layout_right :: template mapping < Extents3D > map_right ( 10 ); // Allocate a basic_mdspan int * ptr = new int [ 3 * 8 * 10 ]; basic_mdspan < int , Extents3D , layout_right > a ( ptr , map_right ); // Initialize the span for ( int i0 = 0 ; i0 < a . extent ( 0 ); i0 ++ ) for ( int i1 = 0 ; i1 < a . extent ( 1 ); i1 ++ ) for ( int i2 = 0 ; i2 < a . extent ( 2 ); i2 ++ ) a ( i0 , i1 , i2 ) = 10000 * i0 + 100 * i1 + i2 ; // Create Subspan auto a_sub = subspan ( a , 1 , std :: pair < int , int > ( 4 , 6 ), std :: pair < int , int > ( 1 , 6 )); // Print values of subspan for ( int i0 = 0 ; i0 < a_sub . extent ( 0 ); i0 ++ ) { for ( int i1 = 0 ; i1 < a_sub . extent ( 1 ); i1 ++ ) { std :: cout << a_sub ( i0 , i1 ) << " " ; } std :: cout << std :: endl ; } /* Output 10401 10402 10403 10404 10405 10501 10502 10503 10504 10505 */ 
5. Next Steps
- 
     Wording editing as per guidance from LWG. 
6. Related Work
Previous paper:
P0860 : Access Policy Generating Proxy Reference
The 
Related papers:
- 
     P0122 : span: bounds-safe views for sequences of objects The mdspan 
- 
     P0367 : Accessors The P0367 Accessors proposal includes polymorphic mechanisms for accessing the memory an object or span of objects. The AccessorPolicy 
- 
     P0331 : Motivation and Examples for Multidimensional Array 
- 
     P0332 : Relaxed Incomplete Multidimensional Array Type Declaration 
- 
     P0454 : Wording for a Minimal mdspan span span mdspan 
- 
     P0546 : Preparing span span 
- 
     P0856 : Restrict access property for mdspan span 
- 
     P0860 : atomic access policy for mdspan 
- 
     P0900 : An Ontology of Properties for mdspan