1. Revision History
1.1. P0009r9: Pre 2019-02-Kona Mailing
-
Wording fixes based on guidance: LWG small group at 2018-11-SanDiego
1.2. P0009r8: Pre 2018-11-SanDiego Mailing
-
Refinement based upon updated prototype / reference implementation
1.3. P0009r7: Post 2018-06-Rapperswil Mailing
-
wording reworked based on guidance: LWG review at 2018-06-Rapperswil
-
usage of
requires reference to C++20 working draftspan -
namespace for library TS
std :: experimental :: fundamentals_v3
1.4. 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
to be two
concepts
and
(akin to
design).
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
to be an
arbitrary (and potentially user-extensible) list of properties.
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
tomdspan
.basic_mdspan -
Added a
alias tomdspan
.basic_mdspan
-
1.5. P0009r5 : Pre 2018-03-Jacksonville Mailing
LEWG review of P0009r4 at 2017-11-Albuquerque meeting
LEWG Poll: We should be able to index with
(in
addition to array).
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.6. 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
, multidimensional span, to align withmdspan
.span -
Move preferred array extents mechanism to appendix.
-
Expose codomain as a
.span -
Add layout mapping concept.
1.7. P0009r3 : Post 2016-06-Oulu Mailing
LEWG did not like the name
, and suggested the following
alternatives: -
-
-
-
-
-
-
-
-
LEWG Poll: Are member
/
still good?
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
, etc).reference -
Expanded description of how the variadic properties list would work.
-
Stopped allowing
in addition toarray_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.8. 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.9. 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
)? Note there is no precedence for this
in the library.
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
toview
.array_ref -
How are users allowed to add properties? Needs elaboration in paper.
-
should be named.view < int [][][] >:: layout -
Rename
(possibly tois_regular
) to avoid overloading the term with theis_affine
concept.Regular -
Make static span(), operator(), constructor, etc variadic.
-
Demonstrate the need for improper access in the paper.
-
In
, take integral types by value.operator ()
1.10. P0009r0 : Pre 2015-10-Kona Mailing
Original non-owning multidimensional array reference (
) paper with
motivation, specification, and examples.
1.11. Related Activity
Related LEWG review of P0546r1 at 2017-11-Albuquerque meeting
LEWG Poll:
should specify the dynamic extent as the element
type of the first template parameter rather than the (current) second
template parameter
SF | F | N | A | SA |
---|---|---|---|---|
5 | 3 | 2 | 2 | 0 |
LEWG Poll:
should support the addition of access properties
variadic template parameters
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 (
)
defines types and functions for mapping multidimensional indices
in its domain, a
multidimensional index space, to the
's codomain,
elements of a contiguous span of objects.
A multidimensional index space of rank
is the Cartesian product
mdspan
has two policies: the layout mapping and the accessor. The layout mapping specifies the formula, and
properties of the formula, for mapping a multidimensional index from the domain to
an element in the codomain. The accessor is an extension point that
allows modification of how elements are accessed. For example, P0367 proposed a rich set of potential access properties.
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 multidimensional indices to element objects.
Optimized Implementation of Layout Mapping
We intend the layout mapping of a multidimensional index to be a constant-time
operation that is trivially inlined and optimized when possible.
Compiler vendors may apply optimizations such as loop invariant code
motion, including partial evaluation of multidimensional index layout mappings
when indices are loop invariant.
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
to the "C++ library headers" table in [headers],
in a place that respects the table’s current alphabetic order.
Add the header
to the "Containers library summary" table in [containers.general] below the listing for
.
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], after the current text, which consists only of the following sentence: "The header
defines the view span."
�. The header
defines the view
,
the type alias
,
and other facilities for interacting with these views.
Add the following subclauses to the end of the [views] subclause in the current draft:
26.7.� Header
synopsis [mdspan.syn]
namespace std { namespace experimental { inline 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
[mdspan.extents]
26.7.�.1 Overview [mdspan.extents.overview]
-
A multidimensional index space is the Cartesian product 0) ⨯ [0, N1) ⨯ ... ⨯ [0, NR-1) of half-open integer intervals.
-
The rank of a multidimensional index space is the number of intervals .
-
An
objectextents
defines a multidimensional index space where ise
and re . rank ()
.e . extent ( r ) -
A multidimensional index is an element of a multidimensional index space. We may identify a pack of integer type
with a multidimensional index in the multidimensional index space defined by ani ...
objectextents
, as long as:e -
issizeof ...( i ) == e . rank () true
; and -
for all
in the ranger
, the[ 0 , e . rank ())
-th element ofr
is in the rangei ...
.[ 0 , e . extent ( r ))
-
namespace std { namespace experimental { inline namespace fundamentals_v3 { template < ptrdiff_t ... StaticExtents > class extents { public : // types using index_type = ptrdiff_t ; // [mdspan.extents.cons], Constructors and assignment constexpr extents () noexcept ; constexpr extents ( const extents & ) noexcept ; template < class ... IndexType > constexpr explicit extents ( IndexType ... dynamic ); template < class IndexType > constexpr extents ( const array < IndexType , rank_dynamic () >& dynamic ) noexcept ; template < ptrdiff_t ... OtherExtents > constexpr extents ( const extents < OtherExtents ... >& other ); ~ extents () = default ; constexpr extents & operator = ( const 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 , ( size_t ( StaticExtents == dynamic_extent ) + ...) > dynamic_extents_ ; // exposition only static size_t dynamic_rank ( size_t ); // exposition only }; }}}
-
If
is(( StaticExtents >= 0 ) || ( StaticExtents == dynamic_extent ) && ...) false
, then the program is ill-formed. -
Each element of the
pack equal toStaticExtents
denotes a dynamic extent.dynamic_extent -
The exposition only
member contains an element for each dynamic extent.dynamic_extents_ -
Let
denote theStaticExtent [ r ]
-th element of ther
pack. The exposition onlyStaticExtents
member function is defined asdynamic_rank static size_t dynamic_rank ( size_t i ) // exposition only { size_t j = 0 ; for ( size_t r = 0 ; r < i ; ++ r ) if ( StaticExtents [ r ] == dynamic_extent ) ++ j ; return j ; }
26.7.�.2 Constructors and assignment [mdspan.extents.cons]
constexpr extents () noexcept ;
-
Effects: Value-initializes
todynamic_extents_
.{ }
constexpr extents ( const extents & other ) noexcept ;
-
Effects: Initializes
withdynamic_extents_
.other . dynamic_extents_
template < ptrdiff_t ... OtherExtents > constexpr extents ( const extents < OtherExtents ... >& other );
-
Constraints:
-
equalssizeof ...( StaticExtents )
; andsizeof ...( OtherExtents ) -
For all
in the ranger
where[ 0 , rank ())
andstatic_extent ( r ) != dynamic_extent
are bothother . static_extent ( r ) != dynamic_extent true
,
isstatic_extent ( r ) == other . static_extent ( r ) true
.
-
-
Expects: For all
in the ranger
,[ 0 , rank ())
isstatic_extent ( r ) == dynamic_extent || static_extent ( r ) == other . extent ( r ) true
. -
Effects: For each
in the ranger
where[ 0 , rank ())
isstatic_extent ( r ) == dynamic_extent true
, initializes
withdynamic_extent [ dynamic_rank ( r )]
.other . extent ( r ) -
Throws: Nothing.
template < class ... IndexType > constexpr explicit extents ( IndexType ... dynamic );
-
Constraints:
-
is( is_convertible_v < IndexType , index_type > && ...) true
, and -
issizeof ...( dynamic ) == rank_dynamic () true
. [Note: If
is zero, overload resolution will unambiguously pick the default constructor ofrank_dynamic ()
over this constructor. —end note]extents
-
-
Expects:
is(( dynamic_extents >= 0 ) && ...) true
. -
Effects: Initializes
withdynamic_extents_
.dynamic ... -
Throws: Nothing.
template < class IndexType > constexpr extents ( const array < IndexType , rank_dynamic () >& dynamic ) noexcept ;
-
Constraints:
isis_convertible_v < IndexType , index_type > true
. -
Expects:
for alldynamic [ i ] >= 0
in the rangei
.[ 0 , rank_dynamic ()) -
Effects: Initializes
withdynamic_extents_
.dynamic
template < ptrdiff_t ... OtherExtents > constexpr extents & operator = ( const extents < OtherExtents ... >& other );
-
Constraints:
-
equalssizeof ...( StaticExtents )
; andsizeof ...( OtherExtents ) -
For all
in the ranger
where[ 0 , rank ())
andstatic_extent ( r ) != dynamic_extent
are bothother . static_extent ( r ) != dynamic_extent true
,
isstatic_extent ( r ) == other . static_extent ( r ) true
.
-
-
Expects: For all
in the ranger
,[ 0 , rank ())
isstatic_extent ( r ) == dynamic_extent || static_extent ( r ) == other . extent ( r ) true
. -
Effects: For each
in the ranger
where[ 0 , rank ())
isstatic_extent ( r ) == dynamic_extent true
, assigns
toother . extent ( r )
.dynamic_extent [ dynamic_rank ( r )]
26.7.�.3 Observers of the domain multidimensional index space [mdspan.extents.obs]
static constexpr size_t rank () noexcept ;
-
Returns:
.sizeof ...( StaticExtents )
static constexpr size_t rank_dynamic () noexcept ;
-
Returns:
-
If
is( sizeof ...( StaticExtents ) == 0 ) true
, then zero; -
Otherwise, the number of elements of
that equalStaticExtents ...
.dynamic_extent
-
static constexpr index_type static_extent ( size_t r ) noexcept ;
-
Returns:
-
If
is in the ranger
, then the[ 0 , rank ())
-th entry in ther
parameter pack;StaticExtents -
Otherwise, 1.
-
constexpr index_type extent ( size_t r ) const noexcept ;
-
Returns:
-
If
isstatic_extent ( r ) == dynamic_extent true
, then
;dynamic_extents_ [ dynamic_rank ( r )] -
Otherwise,
.static_extent ( r )
-
26.7.�.4
comparison operators [mdspan.extents.compare]
template < ptrdiff_t ... LHS , ptrdiff_t ... RHS > constexpr bool operator == ( const extents < LHS ... >& lhs , const extents < RHS ... >& rhs ) noexcept ;
-
Returns:
-
If
islhs . rank () == rhs . rank () true
, and if
islhs . extent ( r ) == rhs . extent ( r ) true
for all
in the ranger
, then[ 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 ;
-
Effects: Equivalent to:
.return ! ( 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, which is a nested class template.
-
A layout mapping policy and its layout mapping nested class template meet the requirements in Table �.
-
A layout mapping meets the requirements of Cpp17DefaultConstructible, Cpp17CopyAssignable, Cpp17EqualityComparable, and the requirements in Table �.
-
In Table �:
-
denotes a layout mapping policy.MP -
denotes a specialization of the layout mapping policy’s nested layout mapping template class.M -
denotes a specialization ofE
.extents -
denotes an object of typee
.E -
denotes an object of typem
.M -
andi ...
are multidimensional indices in the multidimensional index space defined byj ...
.e -
is an integral value in the ranger
.[ 0 , e . rank ())
-
Table � — Layout mapping policy and layout mapping requirements
Expression | Return Type | Returns | Requires |
---|---|---|---|
|
| ||
|
| Returns: .
| |
|
| Returns: A nonnegative value, the layout mapping of .
| |
|
| Returns: If is zero for any in the range , then zero,
else 1 plus the maximum value of for all in .
| |
|
| Returns: true if for every , is true .
| |
|
| Returns: true if the set defined by equals the set {0, ..., }.
| |
|
|
Returns: true if,
for all
in ,
there exists an integer
r,
such that for all and in ,
if all elements of and are equal
except for the
-th element, where
r equals
r + 1,
then
r equals .
| |
|
| Returns: true if is true for any object of type .
| |
|
| Returns: true if is true for any object of type .
| |
|
| Returns: true if is true for any object of type .
| |
|
|
Returns: The integer
r,
such that for all and in ,
if all elements of and are equal
except for the
-th element, where
r equals
r + 1,
then
r equals . [Note:
r has the same definition here as in above. —end note] We call
r the stride of ordinate .
| Requires: is true .
|
26.7.�.2 Class template
[mdspan.layout.left]
-
meets the requirements of layout mapping policy.layout_left -
gives a layout mapping where the left-most extent is stride one and strides increase left-to-right as the product of extents.layout_left -
If
is not a (possibly cv-qualified) specialization ofExtents
, then the program is ill-formed.extents
namespace std { namespace experimental { inline 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
constructors [mdspan.layout.left.cons]
constexpr mapping () noexcept ;
-
Effects: Default-initializes
.extents_ -
Ensures:
isextents () == Extents () true
.
constexpr mapping ( const mapping & other ) noexcept ;
-
Effects: Initializes
withextents_
.other . extents_ -
Ensures:
isextents () == other . extents () true
.
constexpr mapping ( mapping && other ) noexcept ;
-
Effects: Initializes
withextents_
.move ( other . extents_ ) -
Ensures:
equals the result ofextents ()
before the invocation of the move.other . extents ()
constexpr mapping ( const Extents & e ) noexcept ;
-
Effects: Initializes
withextents_
.e -
Ensures:
isextents () == e true
.
template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other );
-
Requires:
meets the requirements for use in the initialization ofother . extents ()
.extents_ -
Effects: Initializes
withextents_
.other . extents () -
Ensures:
isextents () == other . extents () true
. -
Throws: Nothing.
26.7.�.2.2
operations [mdspan.layout.left.ops]
Extents extents () const noexcept ;
-
Returns:
.extents_
typename Extents :: index_type required_span_size () const noexcept ;
-
Returns: The product of
for allextents (). extent ( r )
in the ranger
.[ 0 , extents (). rank ())
template < class ... Indices > typename Extents :: index_type operator ()( Indices ... i ) const ;
-
Constraints:
-
issizeof ...( Indices ) == extents (). rank () true
, and -
is( is_convertible_v < Indices , typename Extents :: index_type > && ...) true
.
-
-
Requires: 0 <=
<array { i ...}[ r ]
for allextents (). extent ( r )
in the ranger
.[ 0 , extents (). rank ()) -
Returns: Let k denote the k-th element of
, and let equali ...
:extents (). rank () -
If is zero, then zero;
-
Otherwise, the sum of
⨯k
for allstride ( k )
in the rangek [ 0 ,
.)
-
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
is zero, then one;r -
Otherwise, the product of
for allextents (). extent ( k )
in the rangek
.[ 0 , r )
-
template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ;
-
Effects: Equivalent to:
.return extents () == other . extents ();
template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ;
-
Effects: Equivalent to:
.return extents () != other . extents ();
26.7.�.3 Class template
[mdspan.layout.right]
-
meets the requirements of layout mapping policy.layout_right -
The layout mapping property
gives a layout mapping where the right-most extent is stride one and strides increase right-to-left as the product of extents.layout_right -
If
is not a (possibly cv-qualified) specialization ofExtents
, then the program is ill-formed.extents
namespace std { namespace experimental { inline 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 ( 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.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
constructors [mdspan.layout.right.cons]
constexpr mapping () noexcept ;
-
Effects: Default-initializes
.extents_ -
Ensures:
isextents () == Extents () true
.
constexpr mapping ( const mapping & other ) noexcept ;
-
Effects: Initializes
withextents_
.other . extents_ -
Ensures:
isextents () == other . extents () true
.
constexpr mapping ( mapping && other ) noexcept ;
-
Effects: Initializes
withextents_
.move ( other . extents_ ) -
Ensures:
equals the result ofextents ()
before the invocation of the move.other . extents ()
constexpr mapping ( const Extents & e ) noexcept ;
-
Effects: Initializes
withextents_
.e -
Ensures:
isextents () == e true
.
template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other );
-
Requires:
meets the requirements for use in the initialization ofother . extents ()
.extents_ -
Effects: Initializes
withextents_
.other . extents () -
Ensures:
isextents () == other . extents () true
. -
Throws: Nothing.
26.7.�.3.2
operations [mdspan.layout.right.ops]
Extents extents () const noexcept ;
-
Returns:
.extents_
typename Extents :: index_type required_span_size () const noexcept ;
-
Returns: The product of
for allextents (). extent ( r )
in the ranger
.[ 0 , extents (). rank ())
template < class ... Indices > typename Extents :: index_type operator ()( Indices ... i ) const noexcept ;
-
Constraints:
-
issizeof ...( Indices ) == extents (). rank () true
, and -
is( is_convertible_v < Indices , typename Extents :: index_type > && ...) true
.
-
-
Requires: 0 <=
<array { i ...}[ r ]
for allextents (). extent ( r )
in the ranger
.[ 0 , extents (). rank ()) -
Returns: Let k denote the k-th element of
, and let equali ...
:extents (). rank () -
If is zero, then zero;
-
Otherwise, the sum of
⨯k
for allstride ( k )
in the rangek [ 0 ,
.)
-
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 ;
-
Effects: Equivalent to:
Extents :: index_type s = 1 ; for ( size_t k = r + 1 ; k < extents (). rank (); ++ k ) s *= extents (). extent ( r ); return s ;
template < class OtherExtents > constexpr bool operator == ( const mapping < OtherExtents >& other ) const noexcept ;
-
Effects: Equivalent to:
.return extents () == other . extents ();
template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ;
-
Effects: Equivalent to:
.return extents () != other . extents ();
26.7.�.4 Class template
[mdspan.layout.stride]
-
meets the requirements of layout mapping policy.layout_stride -
The layout mapping property
gives a layout mapping where the strides are user defined.layout_stride -
If
is not a (possibly cv-qualified) specialization ofExtents
, then the program is ill-formed.extents
namespace std { namespace experimental { inline 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:
-
isextents () == Extents () true
, and -
isstrides () == array < typename Extents :: index_type , Extents :: rank () > () true
.
-
constexpr mapping ( const mapping & other ) noexcept ;
-
Effects: Initializes
withextents_
.other . extents_ -
Ensures:
-
isextents () == other . extents () true
, and -
isstrides () == other . strides () true
.
-
constexpr mapping ( mapping && other ) noexcept ;
-
Effects: Initializes
withextents_
.move ( other . extents_ ) -
Ensures:
-
equals the result ofextents ()
before the invocation of the move, andother . extents () -
equals the result ofstrides ()
before the invocation of the move.other . strides ()
-
Let equalconstexpr mapping ( const Extents & e , array < typename Extents :: index_type , Extents :: rank () > s ) noexcept ;
Extents :: rank ()
.
If
is a permutation of the integers 0, ...,
,
then let p
be an exposition-only array of size_t
of length
such that p [ i ]
equals
i
for all i
in the range [ 0 ,
)
.
-
Requires:
-
iss [ i ] > 0 true
for all
in the rangei [ 0 ,
.) -
If R is nonzero, then there exists a permutation of the integers 0, ..., such that
iss ( p [ i ]) >= s ( p [ i - 1 ]) * e . extent ( p [ i - 1 ]) true
for
in the rangei [ 1 ,
.)
-
-
Effects:
-
Initializes
withextents_
, ande -
initializes
withstrides_
.s
-
-
Ensures:
-
isextents () == e true
, and -
isstrides () == s true
.
-
-
Throws: Nothing.
template < class OtherExtents > constexpr mapping ( const mapping < OtherExtents >& other );
-
Requires:
meets the requirements for use in the initialization ofother . extents ()
.extents_ -
Effects:
-
Initializes
withextents_
, andother . extents () -
initializes
withstrides_
.other . strides ()
-
-
Ensures:
-
isextents () == other . extents () true
, and -
isstrides () == 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
for allextents (). extent ( r ) * stride ( r )
in the ranger
.[ 0 , extents (). rank ())
template < class ... Indices > typename Extents :: index_type operator ()( Indices ... i ) const ;
-
Constraints:
-
issizeof ...( Indices ) == Extents :: rank () true
, and -
is( is_convertible_v < Indices , typename Extents :: index_type > && ...) true
.
-
-
Requires: 0 <=
<array { i ...}[ r ]
for allextents (). extent ( r )
in the ranger
.[ 0 , extents (). rank ()) -
Returns: Let k denote the k-th element of
, let equali ...
, and letExtents :: rank ()
bes
:strides () -
If is zero, then zero;
-
Otherwise, the sum of
⨯k
for alls [ k ]
in the rangek [ 0 ,
.)
-
-
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 ()
.
If
is a permutation of the integers 0, ...,
,
then let p
be an exposition-only array of size_t
of length
such that p [ i ]
equals
i
for all i
in the range [ 0 ,
)
.
-
Returns:
-
If is zero, then
true
; -
Else, if there is a permutation of the integers 0, ..., such that
equals 1 formin ( stride ( p [ i ])
in the rangei [ 0 ,
, and)
equalsstride ( p [ i ])
forstride ( p [ i - 1 ]) * extents (). extent ( p [ i - 1 ])
in the rangei [ 1 ,
, then) 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 ;
-
Effects: Equivalent to:
.return extents () == other . extents ();
template < class OtherExtents > constexpr bool operator != ( const mapping < OtherExtents >& other ) const noexcept ;
-
Effects: Equivalent to:
.return 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
, accessible through the policy’selement_type
function;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
need not be
.
The type of
need not be
. — end note]
[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
to be trivially copyable or
requiring a larger alignment than
. — end note]
In Table �:
-
denotes an accessor policy.A -
denotes an object of typea
.A -
denotes an object of typep
.A :: pointer -
andi
each denote aj
value.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 template
[mdspan.accessor.basic]
-
meets the requirements of accessor policy.accessor_basic -
is required to be a complete object type that is neither an abstract class type nor an array type.ElementType
namespace std { namespace experimental { inline 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:
is dereferenceable.p + i -
Returns:
.p + i
constexpr reference access ( pointer p , ptrdiff_t i ) const noexcept ;
-
Requires:
is dereferenceable.p + i -
Returns:
.p [ i ]
constexpr pointer decay ( pointer p ) const noexcept ;
-
Returns:
.p
26.7.� Class template
[mdspan.basic]
26.7.�.1
overview [mdspan.basic.overview]
-
maps a multidimensional index in its domain to a reference to an element in its codomainbasic_mdspan
.span -
The domain of a
object is a multidimensional index space, defined bybasic_mdspan
) ⨯ [0,extent ( 0 )
) ⨯ ... ⨯ [0,extent ( 1 )
). Each extent may be statically or dynamically specified.extent ( rank () - 1 ) -
The codomain of a
object is abasic_mdspan
of elements.span -
As with
, the storage of the objects in the codomainspan
of aspan
is owned by some other object.basic_mdspan
namespace std { namespace experimental { inline 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 multidimensional 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 }; }}}
-
is required to be a complete object type that is neither an abstract class type nor an array type.ElementType -
If
is not a (cv-unqualified) specialization ofExtents
, then the program is ill-formed.extents -
If
does not meet the layout mapping policy requirements, then the program is ill-formed.LayoutPolicy -
If
does not meet the accessor policy requirements or ifAccessorPolicy
isstd :: is_same_v < typename AccessorPolicy :: element_type , ElementType > false
, then the program is ill-formed.
26.7.�.1
constructors, assignment, and destructor [mdspan.basic.cons] // Mapping domain multidimensional index to access codomain element
constexpr basic_mdspan () noexcept = default ;
-
Effects:
-
Zero-initializes
,ptr_ -
Value-initializes
, andmap_ -
Value-initializes
.acc_
-
-
Ensures:
-
issize () == 0 true
, -
isextents () == Extents () true
, and -
ismapping () == mapping_type () true
.
-
constexpr basic_mdspan ( const basic_mdspan & other ) noexcept = default ;
-
Effects:
-
Initializes
withptr_
,other . ptr_ -
Initializes
withmap_
, andother . map_ -
Initializes
withacc_
.other . acc_
-
-
Ensures:
-
issize () == other . size () true
, -
isextents () == other . extents () true
, and -
ismapping () == other . mapping () true
.
-
constexpr basic_mdspan ( basic_mdspan && other ) noexcept ;
-
Effects:
-
Initializes
withptr_
,move ( other . ptr_ ) -
Initializes
withmap_
, andmove ( other . map_ ) -
Initializes
withacc_
.move ( other . acc_ )
-
template < class ... IndexType > explicit constexpr basic_mdspan ( pointer ptr , IndexType ... dynamic_extents );
-
Constraints:
-
is( is_convertible_v < IndexType , index_type > && ...) true
, -
issizeof ...( dynamic_extents ) == rank_dynamic () true
, -
isis_constructible_v < mapping_type , Extents > true
, and -
isis_default_constructible_v < accessor_type > true
.
-
-
Effects:
-
Initializes
withptr_
,ptr -
Initializes
withmap_
, andExtents ( dynamic_extents ...) -
Value-initializes
.acc_
-
-
Ensures:
-
isextents () == Extents ( dynamic_extents ...) true
, and -
ismapping () == 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:
-
isis_convertible_v < IndexType , index_type > true
, -
isN == rank_dynamic () true
, -
isis_constructible_v < mapping_type , Extents > true
, and -
isis_default_constructible_v < accessor_type > true
.
-
-
Effects: Equivalent to:
, withbasic_mdspan ( p , dynamic_extents [ Rs ]...)
fromRs ...
matchingindex_sequence < Rs ... >
.make_index_sequence < N > -
Throws: Nothing.
constexpr basic_mdspan ( pointer p , const mapping_type & m );
-
Constraints:
isis_default_constructible_v < accessor_type > true
. -
Effects:
-
Initializes
withptr_
,p -
Initializes
withmap_
, andm -
Value-initializes
.acc_
-
-
Ensures:
-
isextents () == m . extents () true
, and -
ismapping () == m true
.
-
-
Throws: Nothing.
constexpr basic_mdspan ( pointer p , const mapping_type & m , const accessor_type & a );
-
Effects:
-
Initializes
withptr_
,p -
Initializes
withmap_
, andm -
Initializes
withacc_
.a
-
-
Ensures:
-
isextents () == m . extents () true
, and -
ismapping () == 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:
-
isis_convertible_v < OtherLayoutPolicy :: template mapping < OtherExtents > , mapping_type true
; -
isis_convertible_v < OtherAccessor , Accessor > true
; -
isis_convertible_v < OtherAccessor :: pointer , pointer > true
; -
isis_convertible_v < OtherExtents , extents_type > true
; and -
For all
in the ranger
, if[ 0 , rank ())
isother . static_extent ( r ) != dynamic_extent && static_extent ( r ) != dynamic_extent true
, then
isother . static_extent ( r ) == static_extent ( r ) true
.
-
-
Requires:
-
For all
in the ranger
, if[ 0 , rank ())
isother . static_extent ( r ) == dynamic_extent || static_extent ( r ) == dynamic_extent true
, then
isother . extent ( r ) == extent ( r ) true
.
-
-
Effects:
-
Initializes
withptr_
,other . ptr_ -
Initializes
withmap_
, andother . map_ -
Initializes
withacc_
.other . acc_
-
-
Ensures:
-
isextents () == Extents ( other . extents ()) true
, and -
ismapping () == 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:
-
isis_assignable_v < mapping_type , OtherLayoutPolicy :: template mapping < OtherExtents >> true
; -
isis_assignable_v < Accessor , OtherAccessor > true
; -
isis_assignable_v < pointer , OtherAccessor :: pointer > true
; -
isOtherExtents :: rank () == rank () true
; and -
For all
in the ranger
, if[ 0 , rank ())
isother . static_extent ( r ) != dynamic_extent && static_extent ( r ) != dynamic_extent true
, then
isother . static_extent ( r ) == static_extent ( r ) true
.
-
-
Requires:
-
For all
in the ranger
, if[ 0 , rank ())
isother . static_extent ( r ) == dynamic_extent || static_extent ( r ) == dynamic_extent true
, then
isother . extent ( r ) == extent ( r ) true
.
-
-
Effects:
-
Assigns
toother . ptr_
,ptr_ -
Assigns
toother . map_
, andmap_ -
Assigns
toother . acc_
.acc_
-
-
Ensures:
-
isextents () == Extents ( other . extents ()) true
, and -
ismapping () == mapping_type ( other . mapping ()) true
.
-
-
Throws: Nothing.
26.7.�.2
mapping domain multidimensional index to access codomain element [mdspan.basic.mapping]
constexpr reference operator []( index_type i ) const ;
-
Constraints:
isrank () == 1 true
. -
Requires:
shall be valid.acc_ . access ( ptr_ , map_ ( i )) -
Effects: Equivalent to:
.return ( * this )( i );
template < class ... IndexType > constexpr reference operator ()( IndexType ... indices ) const ;
-
Constraints:
-
is( is_convertible_v < IndexType , index_type > && ...) true
, and -
issizeof ...( IndexType ) == rank () true
.
-
-
Requires:
shall be valid.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:
-
isis_convertible_v < IndexType , index_type > true
, and -
isrank () == N true
.
-
-
Requires:
shall be valid.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
observers of the domain multidimensional index space [mdspan.basic.domobs]
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
for allextent ( r )
in the ranger
.[ 0 , extents (). rank ())
constexpr index_type unique_size () const noexcept ;
-
Returns: The number of unique elements in the codomain. [Note: If
ismapping (). is_unique () true
, this is identical to
. —end note]size ()
26.7.�.3
observers of the codomain [mdspan.basic.codomain]
constexpr span < element_type > span () const noexcept ;
-
Effects: Equivalent to:
.return span < element_type > ( acc_ . decay ( ptr_ ), required_span_size ());
constexpr pointer data () const noexcept ;
-
Returns:
.ptr_
26.7.�.4
observers of the mapping [mdspan.basic.obs]
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]
-
The
function creates asubspan
with a domain that is a subset of the inputbasic_mdspan
's domain, and a codomain that is a subset of the inputbasic_mdspan
's codomain.basic_mdspan -
The
template argument(s) and the corresponding value(s) of the arguments ofSliceSpecifier
aftersubspan
determine the subset ofsrc
that the return value views.src
namespace std { namespace experimental { inline 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 ; }}}
-
Let
be the return value ofsub
. Denote the value of the -th element ofsubspan ( src , slices ...)
by k, and denote the type of the -th element ofslices ...
by k.slices ... -
Let equal the number of
such thatk
kis_convertible_v <
k, pair < ptrdiff_t , ptrdiff_t >> || is_convertible_v <
is, all_type > true
. -
Define
as the lengthrank_map
ofinteger_sequence
consisting of the unique values of k, in increasing order, such thatptrdiff_t
kis_convertible_v <
k, pair < ptrdiff_t , ptrdiff_t >> || is_convertible_v <
is, all_type > true
. -
Define the exposition-only
functionconstexpr
, whereget_seq < k > ( seq )
is an integer, as the function returning thek
-th entry of thek std :: integer_sequence
. We say that the integer r "is not inseq
" when, for allrank_map
in the range , r does not equalk
.get_seq < k > ( rank_map ) -
In the exposition-only
,struct mdspan_subspan -
The
type alias is a specialization ofextents_t
[mdspan.extents], and is determined by the description of the semantics ofextents
given below;subspan -
The
type alias meets the requirements of a layout mapping policy [mdspan.layout.reqs] and is implementation defined; andlayout_t -
The
type alias specifies the type returned bytype
.subspan
-
[Note: High-quality implementations will avoid
whenever possible,
if the input layout is
or
. — end note]
-
Let
andfirst
be exposition-onlylast
, wherearray < ptrdiff_t , sizeof ...( SliceSpecifier ) >
is the same parameter pack asSliceSpecifier ...
's. Forsubspan
in the ranger
, define the values of[ 0 , sizeof ...( SliceSpecifier ))
andfirst [ r ]
as follows, wherelast [ r ]
andsrc
are the arguments ofslices ...
:subspan -
If
is_convertible_v < r
, then, ptrdiff_t >
equalsfirst [ r ]
, andr
equalslast [ r ]
+ 1;first [ r ] -
Else, if
is_convertible_v < r
, then, pair < ptrdiff_t , ptrdiff_t >>
equalsfirst [ r ]
, andp . first
equalslast [ r ]
, wherep . second
is the result of convertingp
tor
;pair < ptrdiff_t , ptrdiff_t > -
Else, if
is_convertible_v < r
, then, all_type >
, andfirst [ r ] = 0
equalslast [ r ]
.src . extent ( r )
-
-
Requires:
-
equalssizeof ( slices ...)
; andsrc . rank () -
For all
in the ranger
,[ 0 , sizeof ...( slices ))
is0 <= first [ r ] && first [ r ] < last [ r ] && last [ r ] <= src . extent ( r ) true
.
-
-
Constraints:
-
isLayoutPolicy
,layout_left
,layout_right
, or any type in a possibly empty set of implementation-defined types, each of which meets the requirements of a layout mapping policy [mdspan.layout.reqs] [Note: Valid and useful layout mapping policies exist, for which taking an arbitrarylayout_stride
does not make sense. — end note]; andsubspan -
For all
in the rangek
,[ 0 , sizeof ...( slices ))
kis_convertible_v <
k, ptrdiff_t > || is_convertible_v <
k, pair < ptrdiff_t , ptrdiff_t >> || is_convertible_v <
is, all_type > true
.
-
-
Ensures: All of the following:
-
equals .sub . rank () -
equals .mdspan_subspan < ElementType , Extents , LayoutPolicy , AccessorPolicy , SliceSpecifiers ... >:: extents_t :: rank () -
Let the pack
denote a multidimensional index in the domain ofi ...
such thatsub
<k
for allsub . extents ( k )
in the range , wherek
denotes thek
-th element ofk
. Let the packi ...
denote a multidimensional index in the domain ofj ...
where thesrc
-th element ofget_seq < k > ( rank_map )
equalsj ...
+first [ get_seq < k > ( rank_map )]
for allk
in the range , and thek
-th element ofr
equalsj ...
for allfirst [ r ]
in the ranger
such that[ 0 , src . rank ())
is not inr
. Then,rank_map
andsub ( i ...)
refer to the same element.src ( j ...) -
For all
in the range ,k
equalssub . extent ( k )
.last [ get_seq < k > ( rank_map )] - first [ get_seq < k > ( rank_map )] -
If
, thensrc . is_strided ()
issub . is_strided () true
, and for all
in the range ,k
equalssub . stride ( k )
.src . stride ( get_seq < k > ( rank_map )) -
For all
in the range , letk
equalrmk
. Ifget_seq < k > ( rank_map )
does not equalsrc . static_extent ( rmk )
anddynamic_extent is_convertible_v < rmk
is, all_type > true
, then
equalssub . static_extent ( k )
.src . static_extent ( rmk )
-
[Note: Example of
use:
- 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
type may be a proxy for accessing an
object. For example, the atomic
in P0860 defines
to be
from P0019.
Related papers:
-
P0122 : span: bounds-safe views for sequences of objects The
codomain concept of span is well-aligned with this paper.mdspan -
P0367 : Accessors: The P0367 Accessors proposal includes polymorphic mechanisms for accessing the memory an object or span of objects. The
extension point in this proposal is intended to include such memory access properties.AccessorPolicy -
P0331 : Motivation and Examples for Multidimensional Array
-
P0332 : Relaxed Incomplete Multidimensional Array Type Declaration
-
P0454 : Wording for a Minimal
Included proposed modification ofmdspan
to better alignspan
withspan
.mdspan -
P0546 : Preparing
for the future Proposed modification ofspan span -
P0856 : Restrict access property for
andmdspan span -
P0860 : atomic access policy for
mdspan -
P0900 : An Ontology of Properties for
mdspan