Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
mdspan.hpp
Go to the documentation of this file.
1// Copyright 2026, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_MDSPAN_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_MDSPAN_HPP_
7
8// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
9#include "arene/base/array/array.hpp"
10#include "arene/base/constraints/constraints.hpp"
11#include "arene/base/contracts/contract.hpp"
12#include "arene/base/detail/dynamic_extent.hpp"
13#include "arene/base/integer_sequences/sequential_values.hpp"
14#include "arene/base/mdspan/default_accessor.hpp" // IWYU pragma: export
15#include "arene/base/mdspan/detail/representable_cast.hpp"
16#include "arene/base/mdspan/detail/tuple_span.hpp"
17#include "arene/base/mdspan/extents.hpp"
18#include "arene/base/mdspan/is_accessor_policy.hpp"
19#include "arene/base/mdspan/is_layout_mapping.hpp"
20#include "arene/base/mdspan/layout.hpp"
21#include "arene/base/span/span.hpp"
22#include "arene/base/stdlib_choice/cstddef.hpp"
23#include "arene/base/stdlib_choice/declval.hpp"
24#include "arene/base/stdlib_choice/enable_if.hpp"
25#include "arene/base/stdlib_choice/integral_constant.hpp"
26#include "arene/base/stdlib_choice/is_abstract.hpp"
27#include "arene/base/stdlib_choice/is_array.hpp"
28#include "arene/base/stdlib_choice/is_constructible.hpp"
29#include "arene/base/stdlib_choice/is_convertible.hpp"
30#include "arene/base/stdlib_choice/is_default_constructible.hpp"
31#include "arene/base/stdlib_choice/is_object.hpp"
32#include "arene/base/stdlib_choice/is_same.hpp"
33#include "arene/base/stdlib_choice/move.hpp"
34#include "arene/base/stdlib_choice/remove_cv.hpp"
35#include "arene/base/tuple/apply.hpp"
36#include "arene/base/type_traits/all_of.hpp"
37#include "arene/base/type_traits/is_invocable.hpp"
38#include "arene/base/utility/safe_comparisons.hpp"
39#include "arene/base/utility/swap.hpp"
40// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
41
42// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
43
44namespace arene {
45namespace base {
46
47namespace mdspan_detail {
48
49/// @brief Helper variable to indicate if all the extents are dynamic
50/// @tparam Extents The extents
51template <typename Extents>
52extern constexpr bool all_extents_are_dynamic_v = Extents::rank() == Extents::rank_dynamic();
53
54/// @brief Helper variable to indicate if all the extents are static
55/// @tparam Extents The extents
56template <typename Extents>
57extern constexpr bool all_extents_are_static_v = Extents::rank_dynamic() == 0;
58
59/// @brief Validate that @c SourceExtents can be used to construct @c TargetExtents at runtime
60/// @tparam TargetExtents The extents type to construct
61/// @tparam SourceExtents The extents type to construct from
62///
63/// @pre For each rank index @c r of @c extents_type, <c> static_extent(r) == dynamic_extent || static_extent(r) ==
64/// other.extent(r) </c> is true, otherwise this is an @c ARENE_PRECONDITION violation.
65///
66/// Note: this overload is a no-op as the extent values can be verified by the converting constructor constraints. This
67/// prevents instantiating a branch that cannot actually be covered by tests.
68// parasoft-begin-suppress AUTOSAR-M0_1_8-b "This overload avoids checking when the extents are statically known to be
69// compatible"
70template <
71 class TargetExtents,
72 class SourceExtents,
73 arene::base::constraints<std::enable_if_t<
74 TargetExtents::rank() == 0 || all_extents_are_dynamic_v<TargetExtents> ||
75 all_extents_are_static_v<SourceExtents>>> = nullptr>
76constexpr auto validate_extents_compatibility(SourceExtents const&) -> void {}
77// parasoft-end-suppress AUTOSAR-M0_1_8-b
78
79/// @brief Validate that @c SourceExtents can be used to construct @c TargetExtents at runtime
80/// @tparam TargetExtents The extents type to construct
81/// @tparam SourceExtents The extents type to construct from
82/// @param source The extents to construct from
83///
84/// @pre For each rank index @c r of @c extents_type, <c> static_extent(r) == dynamic_extent || static_extent(r) ==
85/// other.extent(r) </c> is true, otherwise this is an @c ARENE_PRECONDITION violation.
86///
87/// Note: this overload does not perform the dynamic extent check as all the @c TargetExtents are static. This prevents
88/// instantiating a branch that cannot actually be covered by tests.
89template <
90 class TargetExtents,
91 class SourceExtents,
92 arene::base::constraints<
93 std::enable_if_t<TargetExtents::rank() != 0>,
94 std::enable_if_t<!all_extents_are_static_v<SourceExtents>>,
95 std::enable_if_t<all_extents_are_static_v<TargetExtents>>> = nullptr>
96constexpr auto validate_extents_compatibility(SourceExtents const& source) -> void {
97 // parasoft-begin-suppress AUTOSAR-M14_6_1-a "False positive: No unqualified size_t"
98 for (auto dim : arene::base::sequential_values<typename TargetExtents::rank_type, TargetExtents::rank()>) {
99 // parasoft-end-suppress AUTOSAR-M14_6_1-a
100 // Note that static_extent() always returns std::size_t, while extent() returns index_type.
101 ARENE_PRECONDITION(cmp_equal(TargetExtents::static_extent(dim), source.extent(dim)));
102 }
103}
104
105/// @brief Validate that @c SourceExtents can be used to construct @c TargetExtents at runtime
106/// @tparam TargetExtents The extents type to construct
107/// @tparam SourceExtents The extents type to construct from
108/// @param source The extents to construct from
109///
110/// @pre For each rank index @c r of @c extents_type, <c> static_extent(r) == dynamic_extent || static_extent(r) ==
111/// other.extent(r) </c> is true, otherwise this is an @c ARENE_PRECONDITION violation.
112template <
113 class TargetExtents,
114 class SourceExtents,
115 arene::base::constraints<
116 std::enable_if_t<TargetExtents::rank() != 0>,
117 std::enable_if_t<!all_extents_are_static_v<SourceExtents>>,
118 std::enable_if_t<!all_extents_are_static_v<TargetExtents>>,
119 std::enable_if_t<!all_extents_are_dynamic_v<TargetExtents>>> = nullptr>
120constexpr auto validate_extents_compatibility(SourceExtents const& source) -> void {
121 // parasoft-begin-suppress AUTOSAR-M14_6_1-a "False positive: No unqualified size_t"
122 for (auto dim : arene::base::sequential_values<typename TargetExtents::rank_type, TargetExtents::rank()>) {
123 // parasoft-end-suppress AUTOSAR-M14_6_1-a
124 // Note that static_extent() always returns std::size_t, while extent() returns index_type.
125 ARENE_PRECONDITION(
126 (TargetExtents::static_extent(dim) == arene::base::dynamic_extent) ||
127 cmp_equal(TargetExtents::static_extent(dim), source.extent(dim))
128 );
129 }
130}
131
132} // namespace mdspan_detail
133
134// parasoft-begin-suppress AUTOSAR-A12_1_6-a "False positive: Constructors for mdspan have different constraints"
135// parasoft-begin-suppress AUTOSAR-A10_1_1-a "Multiple inheritance is private and used to allow for
136// empty-base-optimization"
137// parasoft-begin-suppress AUTOSAR-A12_1_5-a "False positive: Delegating constructors are used where they can be"
138/// @brief A multidimensional view of elements over a contiguous sequence of elements
139/// @tparam ElementType the element type
140/// @tparam Extents an instantiation of @c extents representing the shape of the multidimensional index space
141/// @tparam LayoutPolicy a layout policy (defaults to @c layout_right)
142/// @tparam AccessorPolicy an accessor policy (defaults to @c default_accessor<ElementType>)
143///
144/// Backport of @c std::mdspan from C++23. The @c mdspan class template is a multidimensional array view that maps a
145/// multidimensional index to an element of the array. The mapping and element access policies are configurable, and the
146/// underlying array need not be contiguous or even exist in memory at all.
147template <
148 typename ElementType,
149 typename Extents,
150 typename LayoutPolicy = layout_right,
151 typename AccessorPolicy = default_accessor<ElementType>>
152// NOLINTNEXTLINE(hicpp-special-member-functions) Defines all constructors specified by the standard.
154 : private AccessorPolicy
155 , private LayoutPolicy::template mapping<Extents> {
156 static_assert(std::is_object<ElementType>::value, "ElementType must be a complete object type");
157 static_assert(!std::is_abstract<ElementType>::value, "ElementType must not be an abstract class");
158 static_assert(!std::is_array<ElementType>::value, "ElementType must not be an array");
159 static_assert(is_extents_v<Extents>, "Extents type parameter must be a specialization of arene::base::extents");
160 static_assert(is_accessor_policy_v<AccessorPolicy>, "AccessorPolicy must meet the accessor policy requirements");
161 static_assert(
163 "ElementType must match AccessorPolicy::element_type"
164 );
165 static_assert(
167 "LayoutPolicy must meet the layout mapping policy requirements"
168 );
169
170 public:
171 /// @brief The extents type
172 using extents_type = Extents;
173 /// @brief The layout policy type
174 using layout_type = LayoutPolicy;
175 /// @brief The accessor policy type
176 using accessor_type = AccessorPolicy;
177 /// @brief The mapping type
178 using mapping_type = typename layout_type::template mapping<extents_type>;
179 /// @brief The element type
180 using element_type = ElementType;
181 /// @brief The value type
183
184 /// @brief The index type
185 using index_type = typename extents_type::index_type;
186 /// @brief The size type
187 using size_type = typename extents_type::size_type;
188 /// @brief The rank type
189 using rank_type = typename extents_type::rank_type;
190 /// @brief The data handle type
191 using data_handle_type = typename accessor_type::data_handle_type;
192 /// @brief The reference type
193 using reference = typename accessor_type::reference;
194
195 // parasoft-begin-suppress AUTOSAR-M11_0_1-a-2 "False positive: these are not 'member data', they are a public
196 // property"
197 /// @brief Get the number of dimensions
198 /// @return The rank of the mdspan
199 static constexpr std::integral_constant<rank_type, Extents::rank()> rank{};
200
201 /// @brief Get the number of dimensions with dynamic extent
202 /// @return The dynamic rank of the mdspan
204 // parasoft-end-suppress AUTOSAR-M11_0_1-a-2
205
206 // parasoft-begin-suppress AUTOSAR-A10_2_1-a "False positive: Extents is inherited privately by the mapping_type, so
207 // it is not redefined here."
208 /// @brief Get the static extent for the given dimension
209 /// @param dimension The index of the dimension for which to get the static extent
210 /// @return The value from @c Extents for the specified dimension
211 static constexpr auto static_extent(rank_type dimension) noexcept -> std::size_t {
212 return extents_type::static_extent(dimension);
213 }
214
215 /// @brief Get the actual extent for the given dimension, returning the extent supplied to the constructor for dynamic
216 /// extents
217 /// @param dimension The index of the dimension for which to get the extent
218 /// @return The extent of the specified dimension
219 constexpr auto extent(rank_type dimension) const noexcept -> index_type { return this->extents().extent(dimension); }
220 // parasoft-end-suppress AUTOSAR-A10_2_1-a
221
222 /// @brief Default constructor
223 ///
224 /// @pre <c>[0, mapping().required_span_size())</c> is an accessible range of @c data_handle() and @c accessor() for
225 /// the values of @c mapping() and @c accessor() after the invocation of this constructor. This precondition is not
226 /// checked, but violating it is undefined behavior.
227 ///
228 /// @note This constructor has no visible effect and creates an mdspan with all dynamic
229 /// extents equal to zero. This implies that a default constructed span covers no elements.
230 template <
231 typename Ext = Extents,
232 typename Map = mapping_type,
233 typename Acc = AccessorPolicy,
235 std::enable_if_t<(Ext::rank_dynamic() > 0)>,
239 constexpr mdspan() noexcept
240 : accessor_type{},
241 mapping_type{},
242 ptr_{} {}
243
244 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: Delegates to constructor which does initialize the base
245 // parasoft-begin-suppress CERT_C-EXP37-a "False positive: All parameters *are* named."
246
247 /// @brief Construct mdspan with a data handle and extents
248 /// @tparam OtherIndexTypes The types of the extents used to initialize the layout mapping
249 /// @param handle A user supplied data handle
250 /// @param extents_in User supplied extents
251 ///
252 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, a variadic list of extents which are
253 /// converted to @c extents_type and used to initialize the layout mapping, and a default constructed @c
254 /// accessor_type.
255 ///
256 /// @pre <c> [0, mapping().required_span_size()) </c> is an accessible range of @c handle and @c accessor() for the
257 /// values of @c mapping() and @c accessor() after the invocation of this constructor. This precondition is not
258 /// checked, but violating it is undefined behavior.
259 template <
260 class... OtherIndexTypes,
261 typename Ext = Extents,
262 typename Map = mapping_type,
263 typename Acc = AccessorPolicy,
267 std::enable_if_t<sizeof...(OtherIndexTypes) == rank() || sizeof...(OtherIndexTypes) == rank_dynamic()>,
270 constexpr explicit mdspan(data_handle_type handle, OtherIndexTypes... extents_in) noexcept
271 : mdspan{std::move(handle), extents_type{static_cast<index_type>(std::move(extents_in))...}} {}
272 // parasoft-end-suppress CERT_C-EXP37-a
273
274 // classes"
275 /// @brief Construct mdspan with a data handle and extents
276 /// @tparam OtherIndexType The type of the extent values used to initialize the layout mapping
277 /// @param handle A user supplied data handle
278 /// @param extents_in User supplied extents
279 ///
280 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, a span of extents which are
281 /// converted to @c extents_type and used to initialize the layout mapping, and a default constructed @c
282 /// accessor_type.
283 ///
284 /// @pre <c> [0, mapping().required_span_size()) </c> is an accessible range of @c handle and @c accessor() for the
285 /// values of @c mapping() and @c accessor() after the invocation of this constructor. This precondition is not
286 /// checked, but violating it is undefined behavior.
287 ///
288 /// @note This constructor is @c explicit only if <c> N != rank_dynamic() </c>.
289 template <
290 class OtherIndexType,
291 std::size_t Size,
292 typename Ext = Extents,
293 typename Map = mapping_type,
294 typename Acc = AccessorPolicy,
298 std::enable_if_t<Size == rank()>,
304
305 /// @brief Construct mdspan with a data handle and extents
306 /// @tparam OtherIndexType The type of the extent values used to initialize the layout mapping
307 /// @param handle A user supplied data handle
308 /// @param extents_in User supplied extents
309 ///
310 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, a span of extents which are
311 /// converted to @c extents_type and used to initialize the layout mapping, and a default constructed @c
312 /// accessor_type.
313 ///
314 /// @pre <c> [0, mapping().required_span_size()) </c> is an accessible range of @c handle and @c accessor() for the
315 /// values of @c mapping() and @c accessor after the invocation of this constructor. This precondition is not checked,
316 /// but violating it is undefined behavior.
317 ///
318 /// @note This constructor is @c explicit only if <c> N != rank_dynamic() </c>.
319 template <
320 class OtherIndexType,
321 typename Ext = Extents,
322 typename Map = mapping_type,
323 typename Acc = AccessorPolicy,
331
332 /// @brief Construct mdspan with a data handle and extents
333 /// @tparam OtherIndexType The type of the extent values used to initialize the layout mapping
334 /// @param handle A user supplied data handle
335 /// @param extents_in User supplied extents
336 ///
337 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, an array of extents which are
338 /// converted to @c extents_type and used to initialize the layout mapping, and a default constructed @c
339 /// accessor_type.
340 ///
341 /// @pre <c> [0, mapping().required_span_size()) </c> is an accessible range of @c handle and @c accessor() for the
342 /// values of @c mapping() and @c accessor after the invocation of this constructor. This precondition is not checked,
343 /// but violating it is undefined behavior.
344 ///
345 /// @note This constructor is @c explicit only if <c> N != rank_dynamic() </c>.
346 template <
347 class OtherIndexType,
348 std::size_t Size,
349 typename Ext = Extents,
350 typename Map = mapping_type,
351 typename Acc = AccessorPolicy,
355 std::enable_if_t<Size == rank()>,
361
362 /// @brief Construct mdspan with a data handle and extents
363 /// @tparam OtherIndexType The type of the extent values used to initialize the layout mapping
364 /// @param handle A user supplied data handle
365 /// @param extents_in User supplied extents
366 ///
367 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, an array of extents which are
368 /// converted to @c extents_type and used to initialize the layout mapping, and a default constructed @c
369 /// accessor_type.
370 ///
371 /// @pre <c> [0, mapping().required_span_size()) </c> is an accessible range of @c handle and @c accessor() for the
372 /// values of @c mapping() and @c accessor after the invocation of this constructor. This precondition is not checked,
373 /// but violating it is undefined behavior.
374 ///
375 /// @note This constructor is @c explicit only if <c> N != rank_dynamic() </c>.
376 template <
377 class OtherIndexType,
378 typename Ext = Extents,
379 typename Map = mapping_type,
380 typename Acc = AccessorPolicy,
388
389 // parasoft-end-suppress AUTOSAR-A12_1_1-a
390
391 /// @brief Construct mdspan with a data handle and extents
392 /// @param handle A user supplied data handle
393 /// @param extents_in User supplied extents
394 ///
395 /// @pre <c>[0, mapping().required_span_size())</c> is an accessible range of @c handle and @c accessor() for
396 /// the values of @c mapping() and @c accessor() after the invocation of this constructor. This precondition is not
397 /// checked, but violating it is undefined behavior.
398 ///
399 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, a user supplied @c extents_type used
400 /// to initialize the layout mapping, and a default constructed @c accessor_type.
401 template <
402 typename Ext = Extents,
403 typename Map = mapping_type,
404 typename Acc = AccessorPolicy,
408 // parasoft-begin-suppress AUTOSAR-A0_1_4-a "False positive: Parameter 'extents_in' is used"
413 // parasoft-end-suppress AUTOSAR-A0_1_4-a
414
415 /// @brief Construct mdspan with a data handle and mapping
416 /// @param handle A user supplied data handle
417 /// @param mapping_in User supplied mapping
418 ///
419 /// @pre <c>[0, mapping_in.required_span_size())</c> is an accessible range of @c handle and @c accessor() for
420 /// the value of @c accessor() after the invocation of this constructor. This precondition is not checked, but
421 /// violating it is undefined behavior.
422 ///
423 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, a user supplied @c mapping, and a
424 /// default constructed @c accessor_type.
425 template <
426 typename Acc = AccessorPolicy,
432
433 /// @brief Construct mdspan with a data handle, mapping, and accessor
434 /// @param handle A user supplied data handle
435 /// @param mapping_in User supplied mapping
436 /// @param accessor_in User supplied accessor
437 ///
438 /// @pre <c>[0, mapping_in.required_span_size())</c> is an accessible range of @c handle and @c accessor_in. This
439 /// precondition is not checked, but violating it is undefined behavior.
440 ///
441 /// Construct an @c mdspan initialized with a user supplied @c data_handle_type, a user supplied @c mapping, and a
442 /// user supplied @c accessor_type.
447
448 private:
449 /// @brief Check if the converting constructor should be explicit
450 /// @tparam OtherExtents The extents type of the other @c mdspan
451 /// @tparam OtherLayoutPolicy The layout policy of the other @c mdspan
452 /// @tparam OtherAccessor The accessor policy of the other @c mdspan
453 template <class OtherExtents, class OtherLayoutPolicy, class OtherAccessor>
454 static constexpr bool converting_constructor_is_explicit_v{
457 };
458
459 public:
460 /// @brief Converting constructor from another @c mdspan
461 /// @tparam OtherElementType The element type of the other @c mdspan
462 /// @tparam OtherExtents The extents type of the other @c mdspan
463 /// @tparam OtherLayoutPolicy The layout policy of the other @c mdspan
464 /// @tparam OtherAccessor The accessor policy of the other @c mdspan
465 /// @param other The other mdspan to construct from
466 ///
467 /// @pre For each rank index @c r of @c extents_type, <c> static_extent(r) == dynamic_extent || static_extent(r) ==
468 /// other.extent(r) </c> is true, otherwise this is an @c ARENE_PRECONDITION violation.
469 /// @pre <c>[0, mapping().required_span_size())</c> is an accessible range of @c handle() and @c accessor() for values
470 /// of handle(), mapping(), and accessor() after the invocation of this constructor. This precondition is not checked,
471 /// but violating it is undefined behavior.
472 ///
473 /// @note This constructor is @c explicit only if <c> !std::is_convertible<typename OtherLayoutPolicy::template
474 /// mapping<OtherExtents> const&, mapping_type>::value || !std::is_convertible<OtherAccessor const&,
475 /// accessor_type>::value; </c>
476 template <
477 class OtherElementType,
478 class OtherExtents,
479 class OtherLayoutPolicy,
480 class OtherAccessor,
485 typename OtherLayoutPolicy::template mapping<OtherExtents> const&>::value>,
496
497 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: Delegates to constructor which does construct base
498 // classes"
499 /// @brief Converting constructor from another @c mdspan
500 /// @tparam OtherElementType The element type of the other @c mdspan
501 /// @tparam OtherExtents The extents type of the other @c mdspan
502 /// @tparam OtherLayoutPolicy The layout policy of the other @c mdspan
503 /// @tparam OtherAccessor The accessor policy of the other @c mdspan
504 /// @param other The other mdspan to construct from
505 ///
506 /// @pre For each rank index @c r of @c extents_type, <c> static_extent(r) == dynamic_extent || static_extent(r) ==
507 /// other.extent(r) </c> is true, otherwise this is an @c ARENE_PRECONDITION violation.
508 /// @pre <c>[0, mapping().required_span_size())</c> is an accessible range of @c handle() and @c accessor() for
509 /// values of handle(), mapping(), and accessor() after the invocation of this constructor. This precondition is not
510 /// checked, but violating it is undefined behavior.
511 ///
512 /// @note This constructor is @c explicit only if <c> !std::is_convertible<typename OtherLayoutPolicy::template
513 /// mapping<OtherExtents> const&, mapping_type>::value || !std::is_convertible<OtherAccessor const&,
514 /// accessor_type>::value; </c>
515 template <
516 class OtherElementType,
517 class OtherExtents,
518 class OtherLayoutPolicy,
519 class OtherAccessor,
524 typename OtherLayoutPolicy::template mapping<OtherExtents> const&>::value>,
529 // NOLINTNEXTLINE(hicpp-explicit-conversions)
536
537 // parasoft-end-suppress AUTOSAR-A12_1_1-a
538
539 /// @brief Get the size of the multidimensional index space
540 /// @return The size of the multidimensional index space
541 constexpr auto size() const noexcept -> size_type {
542 return static_cast<size_type>(
543 layout_detail::extent_product(this->extents(), {static_cast<rank_type>(0), rank()}).value
544 );
545 }
546
547 /// @brief Check if the size is zero
548 /// @return @c true if the size is zero, @c false otherwise
549 constexpr auto empty() const noexcept -> bool { return this->size() == static_cast<size_type>(0); }
550
551 /// @brief Get the extents object
552 /// @return A reference to the extents object
553 using mapping_type::extents;
554
555 // parasoft-begin-suppress AUTOSAR-M9_3_1-a "False positive: Returns a const reference to member data."
556 // parasoft-begin-suppress AUTOSAR-A9_3_1-a "False positive: Returns a const reference to member data."
557 /// @brief Get the data handle
558 /// @return The data handle
559 constexpr auto data_handle() const noexcept -> data_handle_type const& { return ptr_; }
560 // parasoft-end-suppress AUTOSAR-M9_3_1-a
561 // parasoft-end-suppress AUTOSAR-A9_3_1-a
562
563 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: No identifiers are hidden by this function"
564 /// @brief Get the mapping
565 /// @return A reference to the mapping object
566 constexpr auto mapping() const noexcept -> mapping_type const& { return *this; }
567 // parasoft-end-suppress AUTOSAR-A2_10_1-d
568
569 /// @brief Get the accessor
570 /// @return A reference to the accessor object
571 constexpr auto accessor() const noexcept -> accessor_type const& { return *this; }
572
573 /// @brief Access an element at the specified multi-dimensional index
574 /// @tparam OtherIndexTypes Non-type template parameter pack of indices
575 /// @param indices The multi-dimensional index as a variadic
576 /// @return reference to the indices-th element of the mdspan
577 template <
578 class... OtherIndexTypes,
582 std::enable_if_t<sizeof...(OtherIndexTypes) == extents_type::rank>> = nullptr>
583 constexpr auto operator()(OtherIndexTypes... indices) const //
584 noexcept(arene::base::is_nothrow_invocable_v<mapping_type const&, OtherIndexTypes&&...>&& noexcept(
585 std::declval<accessor_type const&>().access( //
586 std::declval<data_handle_type const&>(), //
587 std::declval<std::size_t>()
588 )
589 )) //
590 -> reference //
591 {
592 return accessor().access(
593 data_handle(),
595 );
596 }
597
598 /// @brief Access an element with an @c array of indices
599 /// @tparam OtherIndexType Index type contained by the array
600 /// @param indices The multi-dimensional index as an @c array
601 /// @return reference to the indices-th element of the mdspan
602 template <
603 class OtherIndexType,
607 constexpr auto operator()(array<OtherIndexType, extents_type::rank> const& indices) const //
609 decltype(apply),
610 mdspan const&,
611 array<OtherIndexType, extents_type::rank()> const&>) //
612 -> reference {
613 return apply(*this, indices);
614 }
615
616 /// @brief Access an mdspan element with a @c span of indices
617 /// @tparam OtherIndexType Index type contained by the span
618 /// @param indices The multi-dimensional index as an @c span
619 /// @return reference to the indices-th element of the mdspan
620 template <
621 class OtherIndexType,
625 constexpr auto operator()(span<OtherIndexType, extents_type::rank> const indices) const //
627 decltype(apply),
628 mdspan const&,
630 -> reference {
632 }
633
634 /// @brief Return whether or not this mdspan's mapping is always unique, i.e. distinct indices always map to distinct
635 /// elements
636 /// @return @c true because this is enforced by the constructors as a precondition
637 /// @note In mathematical terms this asks if the mapping is always injective/one-to-one.
639
640 /// @brief Return whether or not this mdspan's mapping is always exhaustive, i.e. every element is reachable using
641 /// some indices
642 /// @return @c false because it's possible to construct non-exhaustive mappings using this class
643 /// @note In mathematical terms this asks if the mapping is always surjective/onto.
644 using mapping_type::is_always_exhaustive;
645
646 /// @brief Return whether or not this mdspan's mapping is always strided, i.e. every dimension has a constant stride
647 /// @return @c true because this class directly uses striding to compute its mapped indices
648 /// @note In mathematical terms this asks if the mapping is always affine (isomorphic to a dot product plus offset).
649 using mapping_type::is_always_strided;
650
651 /// @brief Return whether or not this instance is unique, i.e. distinct indices always map to distinct elements
652 /// @return Always @c true because this is enforced by the constructors as a precondition
653 /// @note In mathematical terms this asks if the mapping is injective/one-to-one.
654 using mapping_type::is_unique;
655
656 /// @brief Return whether or not this instance is exhaustive, i.e. every element is reachable using some indices
657 /// @return @c true if every provided stride is the product of the extents corresponding to some subset of the other
658 /// strides, otherwise @c false
659 /// @note In mathematical terms this asks if the mapping is surjective/onto.
660 using mapping_type::is_exhaustive;
661
662 /// @brief Return whether or not this instance is strided, i.e. every dimension has a constant stride
663 /// @return Always @c true because this class directly uses striding to compute its mapped indices
664 /// @note In mathematical terms this asks if the mapping is affine (isomorphic to a dot product plus an offset).
665 using mapping_type::is_strided;
666
667 /// @brief Get the stride of a particular rank in this @c mapping
668 /// @param dimension The index of the dimension to return the stride of
669 /// @return The stride of the selected rank
670 /// @pre <c>dimension < extents_type::rank()</c>
671 using mapping_type::stride;
672
673 // parasoft-begin-suppress AUTOSAR-A7_1_1-a "Declaring 'lhs' or 'rhs' as reference to const changes semantics"
674 // parasoft-begin-suppress AUTOSAR-M7_1_2-c "Declaring 'lhs' or 'rhs' as reference to const changes semantics"
675 // parasoft-begin-suppress AUTOSAR-A8_4_9-a "Declaring 'lhs' or 'rhs' as reference to const changes semantics"
676 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Friend swap operators permitted by A11-3-1 Permit #2 v1.0.0"
677 // parasoft-begin-suppress AUTOSAR-A0_1_3-a "False positive: This is a public function, and doesn't need to be used
678 // in the translation unit"
679
680 /// @brief swaps the contents
681 /// @param lhs left @c mdspan value to swap
682 /// @param rhs right @c mdspan value to swap
683 friend constexpr auto swap(mdspan& lhs, mdspan& rhs) noexcept -> void {
684 arene::base::swap(lhs.ptr_, rhs.ptr_);
685 arene::base::swap(static_cast<mapping_type&>(lhs), static_cast<mapping_type&>(rhs));
686 arene::base::swap(static_cast<accessor_type&>(lhs), static_cast<accessor_type&>(rhs));
687 }
688
689 // parasoft-end-suppress AUTOSAR-A7_1_1-a
690 // parasoft-end-suppress AUTOSAR-M7_1_2-c
691 // parasoft-end-suppress AUTOSAR-A8_4_9-a
692 // parasoft-end-suppress AUTOSAR-A11_3_1-a
693 // parasoft-end-suppress AUTOSAR-A0_1_3-a
694
695 private:
696 // parasoft-begin-suppress AUTOSAR-M14_6_1-a "False positive: The identifier data_handle_type is brought into this
697 // class scope"
698 /// @brief The data handle
699 data_handle_type ptr_;
700 // parasoft-end-suppress AUTOSAR-M14_6_1-a
701};
702
703// parasoft-end-suppress AUTOSAR-A12_1_5-a
704// parasoft-end-suppress AUTOSAR-A10_1_1-a
705// parasoft-end-suppress AUTOSAR-A12_1_6-a
706
707/// @brief Get the number of dimensions in the extents
708/// @tparam ElementType the element type
709/// @tparam Extents an instantiation of @c extents representing the shape of the multidimensional index space
710/// @tparam LayoutPolicy a layout policy (defaults to @c layout_right)
711/// @tparam AccessorPolicy an accessor policy (defaults to @c default_accessor<ElementType>)
712template <typename ElementType, typename Extents, typename LayoutPolicy, typename AccessorPolicy>
713constexpr std::
715 mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>::rank;
716
717/// @brief Get the number of dimensions with dynamic extent
718/// @tparam ElementType the element type
719/// @tparam Extents an instantiation of @c extents representing the shape of the multidimensional index space
720/// @tparam LayoutPolicy a layout policy (defaults to @c layout_right)
721/// @tparam AccessorPolicy an accessor policy (defaults to @c default_accessor<ElementType>)
722template <typename ElementType, typename Extents, typename LayoutPolicy, typename AccessorPolicy>
723constexpr std::integral_constant<
726 mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>::rank_dynamic;
727
728namespace is_mdspan_detail {
729/// @brief Type trait to determine if the given type is an mdspan of some kind
730/// @tparam T The type to check
731template <typename T>
732extern constexpr bool is_mdspan_v{false};
733
734/// @brief Type trait to determine if the given type is an mdspan of some kind
735/// @tparam ElementType The element type of an @c mdspan being checked
736/// @tparam Extents The extents type of an @c mdspan being checked
737/// @tparam LayoutPolicy The layout policy type (note: not the layout mapping) of an @c mdspan being checked
738/// @tparam AccessorPolicy The accessor policy type of an @c mdspan being checked
739template <typename ElementType, typename Extents, typename LayoutPolicy, typename AccessorPolicy>
740extern constexpr bool is_mdspan_v<mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>>{true};
741} // namespace is_mdspan_detail
742
743/// @brief Type trait to determine if the given type is an mdspan of some kind
744/// @tparam T The type to check
745template <typename T>
746extern constexpr bool is_mdspan_v{is_mdspan_detail::is_mdspan_v<std::remove_cv_t<T>>};
747
748} // namespace base
749} // namespace arene
750
751#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_MDSPAN_HPP_
A multidimensional view of elements over a contiguous sequence of elements.
Definition mdspan.hpp:155
friend constexpr auto swap(mdspan &lhs, mdspan &rhs) noexcept -> void
swaps the contents
Definition mdspan.hpp:683
static constexpr std::integral_constant< rank_type, Extents::rank_dynamic()> rank_dynamic
Get the number of dimensions with dynamic extent.
Definition mdspan.hpp:203
constexpr auto accessor() const noexcept -> accessor_type const &
Get the accessor.
Definition mdspan.hpp:571
constexpr auto data_handle() const noexcept -> data_handle_type const &
Get the data handle.
Definition mdspan.hpp:559
static constexpr std::integral_constant< rank_type, Extents::rank()> rank
Get the number of dimensions.
Definition mdspan.hpp:199
static constexpr auto static_extent(rank_type dimension) noexcept -> std::size_t
Get the static extent for the given dimension.
Definition mdspan.hpp:211
constexpr auto mapping() const noexcept -> mapping_type const &
Get the mapping.
Definition mdspan.hpp:566
constexpr auto extent(rank_type dimension) const noexcept -> index_type
Get the actual extent for the given dimension, returning the extent supplied to the constructor for d...
Definition mdspan.hpp:219
Definition array_exceptions_disabled.cpp:11
constexpr bool is_mdspan_v
Type trait to determine if the given type is an mdspan of some kind.
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10