[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;
