[mdspan.accessor] (original) (raw)

23 Containers library [containers]

23.7 Views [views]

23.7.3 Multidimensional access [views.multidim]

23.7.3.5 Accessor policy [mdspan.accessor]


23.7.3.5.1 General [mdspan.accessor.general]

23.7.3.5.2 Requirements [mdspan.accessor.reqmts]

23.7.3.5.3 Class template default_accessor [mdspan.accessor.default]

23.7.3.5.3.1 Overview [mdspan.accessor.default.overview]

23.7.3.5.3.2 Members [mdspan.accessor.default.members]

23.7.3.5.4 Class template aligned_accessor [mdspan.accessor.aligned]

23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]

23.7.3.5.4.2 Members [mdspan.accessor.aligned.members]


23.7.3.5.1 General [mdspan.accessor.general]

An accessor policy 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.

A range of indices is an accessible range 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.

23.7.3.5.2 Requirements [mdspan.accessor.reqmts]

A type A meets the accessor policy requirements if

Result: A complete object type that is not an abstract class type.

typename A::data_handle_type

Result: A type that models copyable, 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.

[Note 1:

The type of data_handle_type need not be element_type*.

— _end note_]

Result: A type that modelscommon_reference_with<A​::​reference&&, A​::​element_type&>.

[Note 2:

The type of reference need not be element_type&.

— _end note_]

typename A::offset_policy

Result: A type OP such that:

Remarks: The expression is equality preserving.

[Note 3:

Concrete accessor policies can impose preconditions for their access function.

However, they might not.

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.

— _end note_]

Result: A​::​offset_policy​::​data_handle_type

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:

Remarks: The expression is equality-preserving.

23.7.3.5.3 Class template default_accessor [mdspan.accessor.default]

23.7.3.5.3.1 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;};}

default_accessor meets the accessor policy requirements.

ElementType is required to be a complete object type that is neither an abstract class type nor an array type.

Each specialization of default_accessor is a trivially copyable type that models semiregular.

is an accessible range for an object p of type data_handle_type and an object of type default_accessorif and only if [p, p + n) is a valid range.

23.7.3.5.3.2 Members [mdspan.accessor.default.members]

template<class OtherElementType> constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}

Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]>is true.

constexpr reference access(data_handle_type p, size_t i) const noexcept;

Effects: Equivalent to: return p[i];

constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;

Effects: Equivalent to: return p + i;

23.7.3.5.4 Class template aligned_accessor [mdspan.accessor.aligned]

23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]

namespace std { template<class ElementType, size_t ByteAlignment> struct aligned_accessor { 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;};}

Mandates:

aligned_accessor meets the accessor policy requirements.

ElementType is required to be a complete object type that is neither an abstract class type nor an array type.

Each specialization of aligned_accessor is a trivially copyable type that models semiregular.

[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

[Example 1:

The following function computeuses 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)>.

If so, the function dispatches to a function compute_using_fourfold_overalignmentthat requires fourfold over-alignment of arrays, but can therefore use hardware-specific instructions, such as four-wide SIMD (Single Instruction Multiple Data) instructions.

Otherwise, compute dispatches to a possibly less optimized function compute_without_requiring_overalignmentthat has no over-alignment requirement.

void compute_using_fourfold_overalignment( mdspan<float, dims<1>, layout_right, aligned_accessor<float, 4 * alignof(float)>> x);void compute_without_requiring_overalignment( mdspan<float, dims<1>, layout_right> x);void compute(mdspan<float, dims<1>> x) { constexpr auto byte_alignment = 4 * sizeof(float);auto accessor = aligned_accessor<float, byte_alignment>{};auto x_handle = x.data_handle();if (is_sufficiently_aligned<byte_alignment>(x_handle)) { compute_using_fourfold_overalignment(mdspan{x_handle, x.mapping(), accessor});} else { compute_without_requiring_overalignment(x);} } — _end example_]

23.7.3.5.4.2 Members [mdspan.accessor.aligned.members]

template<class OtherElementType, size_t OtherByteAlignment> constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;

Constraints:

template<class OtherElementType> constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;

Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]>is true.

constexpr reference access(data_handle_type p, size_t i) const noexcept;

Preconditions: [0, i + 1) is an accessible range for p and *this.

Effects: Equivalent to: return assume_aligned<byte_alignment>(p)[i];

template<class OtherElementType> constexpr operator default_accessor<OtherElementType>() const noexcept;

Constraints: is_convertible_v<element_type(*)[], OtherElementType(*)[]>is true.

Effects: Equivalent to: return {};

constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const noexcept;

Preconditions: [0, i + 1) is an accessible range for p and *this.

Effects: Equivalent to: return assume_aligned<byte_alignment>(p) + i;