[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 is true,
- [(1.3)](#reqmts-1.3)
is_nothrow_move_assignable_v is true,
- [(1.4)](#reqmts-1.4)
is_nothrow_swappable_v 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 is true,is_nothrow_move_assignable_v is true, andis_nothrow_swappable_v 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]")[.](#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]") is modeled, and
- [(5.3)](#reqmts-5.3)
is_same_v 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 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 {templatestruct default_accessor {using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; constexpr default_accessor() noexcept = default; templateconstexpr default_accessor(default_accessor) 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
constexpr default_accessor(default_accessor) noexcept {}
`
[1](#default.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24408)
*Constraints*: is_convertible_v 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 {templatestruct [aligned_accessor](#lib:aligned_accessor "23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]") {using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; static constexpr size_t byte_alignment = ByteAlignment; constexpr aligned_accessor() noexcept = default; templateconstexpr aligned_accessor( aligned_accessor) noexcept; templateconstexpr explicit aligned_accessor(default_accessor) noexcept; templateconstexpr operator default_accessor() 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(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[.](#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, std::layout_right,
std::aligned_accessor> x);
void compute_without_requiring_overalignment( std::mdspan, std::layout_right> x);
void compute(std::mdspan> x) {constexpr auto byte_alignment = 4 * sizeof(float); auto accessor = std::aligned_accessor{}; auto x_handle = x.data_handle(); if (std::is_sufficiently_aligned(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
constexpr aligned_accessor(aligned_accessor) 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 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
constexpr explicit aligned_accessor(default_accessor) noexcept;
`
[3](#aligned.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24567)
*Constraints*: is_convertible_v 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(p)[i];
[ð](#lib:operator_default_accessor,aligned_accessor)
`template
constexpr operator default_accessor() const noexcept;
`
[7](#aligned.members-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L24599)
*Constraints*: is_convertible_v 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(p) + i;