470 lines
17 KiB
Markdown
470 lines
17 KiB
Markdown
[mdspan.accessor]
|
||
|
||
# 23 Containers library [[containers]](./#containers)
|
||
|
||
## 23.7 Views [[views]](views#mdspan.accessor)
|
||
|
||
### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.accessor)
|
||
|
||
#### 23.7.3.5 Accessor policy [mdspan.accessor]
|
||
|
||
#### [23.7.3.5.1](#general) General [[mdspan.accessor.general]](mdspan.accessor.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24204)
|
||
|
||
An [*accessor policy*](#def:accessor_policy "23.7.3.5.1 General [mdspan.accessor.general]") defines types and operations by which
|
||
a reference to a single object is created
|
||
from an abstract data handle to a number of such objects and an index[.](#general-1.sentence-1)
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24209)
|
||
|
||
A range of indices [0,N) is an [*accessible range*](#def:range,accessible "23.7.3.5.1 General [mdspan.accessor.general]") of
|
||
a given data handle and an accessor
|
||
if, for each i in the range,
|
||
the accessor policy's access function produces a valid reference to an object[.](#general-2.sentence-1)
|
||
|
||
[3](#general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24215)
|
||
|
||
In [[mdspan.accessor.reqmts]](#reqmts "23.7.3.5.2 Requirements"),
|
||
|
||
- [(3.1)](#general-3.1)
|
||
|
||
A denotes an accessor policy[.](#general-3.1.sentence-1)
|
||
|
||
- [(3.2)](#general-3.2)
|
||
|
||
a denotes a value of type A or const A[.](#general-3.2.sentence-1)
|
||
|
||
- [(3.3)](#general-3.3)
|
||
|
||
p denotes a value of type A::data_handle_type or const A::data_handle_type[.](#general-3.3.sentence-1)
|
||
[*Note [1](#general-note-1)*:
|
||
The type A::data_handle_type need not be dereferenceable[.](#general-3.3.sentence-2)
|
||
â *end note*]
|
||
|
||
- [(3.4)](#general-3.4)
|
||
|
||
n, i, and j each denote values of type size_t[.](#general-3.4.sentence-1)
|
||
|
||
#### [23.7.3.5.2](#reqmts) Requirements [[mdspan.accessor.reqmts]](mdspan.accessor.reqmts)
|
||
|
||
[1](#reqmts-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24234)
|
||
|
||
A type A meets the accessor policy requirements if
|
||
|
||
- [(1.1)](#reqmts-1.1)
|
||
|
||
A models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"),
|
||
|
||
- [(1.2)](#reqmts-1.2)
|
||
|
||
is_nothrow_move_constructible_v<A> is true,
|
||
|
||
- [(1.3)](#reqmts-1.3)
|
||
|
||
is_nothrow_move_assignable_v<A> is true,
|
||
|
||
- [(1.4)](#reqmts-1.4)
|
||
|
||
is_nothrow_swappable_v<A> is true, and
|
||
|
||
- [(1.5)](#reqmts-1.5)
|
||
|
||
the following types and expressions
|
||
are well-formed and have the specified semantics[.](#reqmts-1.sentence-1)
|
||
|
||
[ð](#reqmts-itemdecl:1)
|
||
|
||
`typename A::element_type
|
||
`
|
||
|
||
[2](#reqmts-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24255)
|
||
|
||
*Result*: A complete object type that is not an abstract class type[.](#reqmts-2.sentence-1)
|
||
|
||
[ð](#reqmts-itemdecl:2)
|
||
|
||
`typename A::data_handle_type
|
||
`
|
||
|
||
[3](#reqmts-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24265)
|
||
|
||
*Result*: A type that models [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"), and
|
||
for which is_nothrow_move_constructible_v<A::data_handle_type> is true,is_nothrow_move_assignable_v<A::data_handle_type> is true, andis_nothrow_swappable_v<A::data_handle_type> is true[.](#reqmts-3.sentence-1)
|
||
|
||
[*Note [1](#reqmts-note-1)*:
|
||
|
||
The type of data_handle_type need not be element_type*[.](#reqmts-3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#reqmts-itemdecl:3)
|
||
|
||
`typename A::reference
|
||
`
|
||
|
||
[4](#reqmts-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24281)
|
||
|
||
*Result*: A type that models[common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<A::reference&&, A::element_type&>[.](#reqmts-4.sentence-1)
|
||
|
||
[*Note [2](#reqmts-note-2)*:
|
||
|
||
The type of reference need not be element_type&[.](#reqmts-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#reqmts-itemdecl:4)
|
||
|
||
`typename A::offset_policy
|
||
`
|
||
|
||
[5](#reqmts-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24295)
|
||
|
||
*Result*: A type OP such that:
|
||
|
||
- [(5.1)](#reqmts-5.1)
|
||
|
||
OP meets the accessor policy requirements,
|
||
|
||
- [(5.2)](#reqmts-5.2)
|
||
|
||
[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<OP, const A&> is modeled, and
|
||
|
||
- [(5.3)](#reqmts-5.3)
|
||
|
||
is_same_v<typename OP::element_type, typename A::element_type> is true[.](#reqmts-5.sentence-1)
|
||
|
||
[ð](#reqmts-itemdecl:5)
|
||
|
||
`a.access(p, i)
|
||
`
|
||
|
||
[6](#reqmts-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24313)
|
||
|
||
*Result*: A::reference
|
||
|
||
[7](#reqmts-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24317)
|
||
|
||
*Remarks*: The expression is equality preserving[.](#reqmts-7.sentence-1)
|
||
|
||
[8](#reqmts-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24321)
|
||
|
||
[*Note [3](#reqmts-note-3)*:
|
||
|
||
Concrete accessor policies can impose preconditions for their access function[.](#reqmts-8.sentence-1)
|
||
|
||
However, they might not[.](#reqmts-8.sentence-2)
|
||
|
||
For example, an accessor wherep is span<A::element_type, dynamic_extent> andaccess(p, i) returns p[i % p.size()] does not need to impose a precondition on i[.](#reqmts-8.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#reqmts-itemdecl:6)
|
||
|
||
`a.offset(p, i)
|
||
`
|
||
|
||
[9](#reqmts-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24337)
|
||
|
||
*Result*: A::offset_policy::data_handle_type
|
||
|
||
[10](#reqmts-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24341)
|
||
|
||
*Returns*: q such that for b being A::offset_policy(a), and
|
||
any integer n for which [0, n) is
|
||
an accessible range of p and a:
|
||
|
||
- [(10.1)](#reqmts-10.1)
|
||
|
||
[0,nâi) is an accessible range of q and b; and
|
||
|
||
- [(10.2)](#reqmts-10.2)
|
||
|
||
b.access(q, j) provides access to
|
||
the same element as a.access(p, i + j),
|
||
for every j in the range [0,nâi)[.](#reqmts-10.sentence-1)
|
||
|
||
[11](#reqmts-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24355)
|
||
|
||
*Remarks*: The expression is equality-preserving[.](#reqmts-11.sentence-1)
|
||
|
||
#### [23.7.3.5.3](#default) Class template default_accessor [[mdspan.accessor.default]](mdspan.accessor.default)
|
||
|
||
#### [23.7.3.5.3.1](#default.overview) Overview [[mdspan.accessor.default.overview]](mdspan.accessor.default.overview)
|
||
|
||
namespace std {template<class ElementType>struct default_accessor {using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; constexpr default_accessor() noexcept = default; template<class OtherElementType>constexpr default_accessor(default_accessor<OtherElementType>) noexcept; constexpr reference access(data_handle_type p, size_t i) const noexcept; constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; };}
|
||
|
||
[1](#default.overview-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24382)
|
||
|
||
default_accessor meets the accessor policy requirements[.](#default.overview-1.sentence-1)
|
||
|
||
[2](#default.overview-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24385)
|
||
|
||
ElementType is required to be a complete object type
|
||
that is neither an abstract class type nor an array type[.](#default.overview-2.sentence-1)
|
||
|
||
[3](#default.overview-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24389)
|
||
|
||
Each specialization of default_accessor is
|
||
a trivially copyable type that models [semiregular](concepts.object#concept:semiregular "18.6 Object concepts [concepts.object]")[.](#default.overview-3.sentence-1)
|
||
|
||
[4](#default.overview-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24393)
|
||
|
||
[0,n) is an accessible range for
|
||
an object p of type data_handle_type and
|
||
an object of type default_accessor if and only if [p, p + n) is a valid range[.](#default.overview-4.sentence-1)
|
||
|
||
#### [23.7.3.5.3.2](#default.members) Members [[mdspan.accessor.default.members]](mdspan.accessor.default.members)
|
||
|
||
[ð](#lib:default_accessor,constructor)
|
||
|
||
`template<class OtherElementType>
|
||
constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}
|
||
`
|
||
|
||
[1](#default.members-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24408)
|
||
|
||
*Constraints*: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true[.](#default.members-1.sentence-1)
|
||
|
||
[ð](#lib:access,default_accessor)
|
||
|
||
`constexpr reference access(data_handle_type p, size_t i) const noexcept;
|
||
`
|
||
|
||
[2](#default.members-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24420)
|
||
|
||
*Effects*: Equivalent to: return p[i];
|
||
|
||
[ð](#lib:offset,default_accessor)
|
||
|
||
`constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
|
||
`
|
||
|
||
[3](#default.members-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24431)
|
||
|
||
*Effects*: Equivalent to: return p + i;
|
||
|
||
#### [23.7.3.5.4](#aligned) Class template aligned_accessor [[mdspan.accessor.aligned]](mdspan.accessor.aligned)
|
||
|
||
#### [23.7.3.5.4.1](#aligned.overview) Overview [[mdspan.accessor.aligned.overview]](mdspan.accessor.aligned.overview)
|
||
|
||
namespace std {template<class ElementType, size_t ByteAlignment>struct [aligned_accessor](#lib:aligned_accessor "23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]") {using offset_policy = default_accessor<ElementType>; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; static constexpr size_t byte_alignment = ByteAlignment; constexpr aligned_accessor() noexcept = default; template<class OtherElementType, size_t OtherByteAlignment>constexpr aligned_accessor( aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept; template<class OtherElementType>constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept; template<class OtherElementType>constexpr operator default_accessor<OtherElementType>() const noexcept; constexpr reference access(data_handle_type p, size_t i) const noexcept; constexpr typename offset_policy::data_handle_type offset( data_handle_type p, size_t i) const noexcept; };}
|
||
|
||
[1](#aligned.overview-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24469)
|
||
|
||
*Mandates*:
|
||
|
||
- [(1.1)](#aligned.overview-1.1)
|
||
|
||
byte_alignment is a power of two, and
|
||
|
||
- [(1.2)](#aligned.overview-1.2)
|
||
|
||
byte_alignment >= alignof(ElementType) is true[.](#aligned.overview-1.sentence-1)
|
||
|
||
[2](#aligned.overview-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24476)
|
||
|
||
aligned_accessor meets the accessor policy requirements[.](#aligned.overview-2.sentence-1)
|
||
|
||
[3](#aligned.overview-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24479)
|
||
|
||
ElementType is required to be a complete object type
|
||
that is neither an abstract class type nor an array type[.](#aligned.overview-3.sentence-1)
|
||
|
||
[4](#aligned.overview-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24483)
|
||
|
||
Each specialization of aligned_accessor is
|
||
a trivially copyable type that models [semiregular](concepts.object#concept:semiregular "18.6 Object concepts [concepts.object]")[.](#aligned.overview-4.sentence-1)
|
||
|
||
[5](#aligned.overview-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24487)
|
||
|
||
[0, n) is an accessible range
|
||
for an object p of type data_handle_type and
|
||
an object of type aligned_accessor if and only if
|
||
|
||
- [(5.1)](#aligned.overview-5.1)
|
||
|
||
[p, p + n) is a valid range, and,
|
||
|
||
- [(5.2)](#aligned.overview-5.2)
|
||
|
||
if n is greater than zero,
|
||
then is_sufficiently_aligned<byte_alignment>(p) is true[.](#aligned.overview-5.sentence-1)
|
||
|
||
[6](#aligned.overview-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24499)
|
||
|
||
[*Example [1](#aligned.overview-example-1)*:
|
||
|
||
The following function compute uses is_sufficiently_aligned to check
|
||
whether a given mdspan with default_accessor has
|
||
a data handle with sufficient alignment
|
||
to be used with aligned_accessor<float, 4 * sizeof(float)>[.](#aligned.overview-6.sentence-1)
|
||
|
||
If so, the function dispatches to
|
||
a function compute_using_fourfold_overalignment that requires fourfold over-alignment of arrays,
|
||
but can therefore use hardware-specific instructions,
|
||
such as four-wide SIMD (Single Instruction Multiple Data) instructions[.](#aligned.overview-6.sentence-2)
|
||
|
||
Otherwise, compute dispatches to a
|
||
possibly less optimized function compute_without_requiring_overalignment that has no over-alignment requirement[.](#aligned.overview-6.sentence-3)
|
||
|
||
void compute_using_fourfold_overalignment( std::mdspan<float, std::dims<1>, std::layout_right,
|
||
std::aligned_accessor<float, 4 * alignof(float)>> x);
|
||
|
||
void compute_without_requiring_overalignment( std::mdspan<float, std::dims<1>, std::layout_right> x);
|
||
|
||
void compute(std::mdspan<float, std::dims<1>> x) {constexpr auto byte_alignment = 4 * sizeof(float); auto accessor = std::aligned_accessor<float, byte_alignment>{}; auto x_handle = x.data_handle(); if (std::is_sufficiently_aligned<byte_alignment>(x_handle)) { compute_using_fourfold_overalignment(std::mdspan{x_handle, x.mapping(), accessor}); } else { compute_without_requiring_overalignment(x); }} â *end example*]
|
||
|
||
#### [23.7.3.5.4.2](#aligned.members) Members [[mdspan.accessor.aligned.members]](mdspan.accessor.aligned.members)
|
||
|
||
[ð](#lib:aligned_accessor,constructor)
|
||
|
||
`template<class OtherElementType, size_t OtherByteAlignment>
|
||
constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
|
||
`
|
||
|
||
[1](#aligned.members-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24545)
|
||
|
||
*Constraints*:
|
||
|
||
- [(1.1)](#aligned.members-1.1)
|
||
|
||
is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true[.](#aligned.members-1.1.sentence-1)
|
||
|
||
- [(1.2)](#aligned.members-1.2)
|
||
|
||
OtherByteAlignment >= byte_alignment is true[.](#aligned.members-1.2.sentence-1)
|
||
|
||
[2](#aligned.members-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24555)
|
||
|
||
*Effects*: None[.](#aligned.members-2.sentence-1)
|
||
|
||
[ð](#lib:aligned_accessor,constructor_)
|
||
|
||
`template<class OtherElementType>
|
||
constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
|
||
`
|
||
|
||
[3](#aligned.members-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24567)
|
||
|
||
*Constraints*: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true[.](#aligned.members-3.sentence-1)
|
||
|
||
[4](#aligned.members-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24572)
|
||
|
||
*Effects*: None[.](#aligned.members-4.sentence-1)
|
||
|
||
[ð](#lib:access,aligned_accessor)
|
||
|
||
`constexpr reference access(data_handle_type p, size_t i) const noexcept;
|
||
`
|
||
|
||
[5](#aligned.members-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24583)
|
||
|
||
*Preconditions*: [0, i + 1) is an accessible range for p and *this[.](#aligned.members-5.sentence-1)
|
||
|
||
[6](#aligned.members-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24587)
|
||
|
||
*Effects*: Equivalent to: return assume_aligned<byte_alignment>(p)[i];
|
||
|
||
[ð](#lib:operator_default_accessor,aligned_accessor)
|
||
|
||
`template<class OtherElementType>
|
||
constexpr operator default_accessor<OtherElementType>() const noexcept;
|
||
`
|
||
|
||
[7](#aligned.members-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24599)
|
||
|
||
*Constraints*: is_convertible_v<element_type(*)[], OtherElementType(*)[]> is true[.](#aligned.members-7.sentence-1)
|
||
|
||
[8](#aligned.members-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24604)
|
||
|
||
*Effects*: Equivalent to: return {};
|
||
|
||
[ð](#lib:offset,aligned_accessor)
|
||
|
||
`constexpr typename offset_policy::data_handle_type
|
||
offset(data_handle_type p, size_t i) const noexcept;
|
||
`
|
||
|
||
[9](#aligned.members-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24616)
|
||
|
||
*Preconditions*: [0, i + 1) is an accessible range for p and *this[.](#aligned.members-9.sentence-1)
|
||
|
||
[10](#aligned.members-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24620)
|
||
|
||
*Effects*: Equivalent to: return assume_aligned<byte_alignment>(p) + i;
|