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