Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
layout_right.hpp
Go to the documentation of this file.
1// parasoft-suppress CERT_C-EXP37-a AUTOSAR-A2_8_1-a "False positive: there is no function named '()' here. Header
2// defines layout_right types"
3
4// Copyright 2026, Toyota Motor Corporation
5//
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
8#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_LAYOUT_RIGHT_HPP_
9#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_LAYOUT_RIGHT_HPP_
10
11// IWYU pragma: no_include "arene/base/mdspan/layout.hpp"
12
13// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
14#include "arene/base/array/array.hpp"
15#include "arene/base/constraints/constraints.hpp"
16#include "arene/base/mdspan/detail/all_valid_submdspan_slice_types_for.hpp"
17#include "arene/base/mdspan/detail/is_submdspan_layout_preserving.hpp"
18#include "arene/base/mdspan/detail/layout_common.hpp" // IWYU pragma: keep
19#include "arene/base/mdspan/detail/strided_mapping_base.hpp" // IWYU pragma: keep
20#include "arene/base/mdspan/detail/submdspan_mapping_impl.hpp"
21#include "arene/base/mdspan/is_sliceable_mapping.hpp" // IWYU pragma: keep
22#include "arene/base/mdspan/submdspan_subextents_type.hpp"
23#include "arene/base/stdlib_choice/enable_if.hpp"
24#include "arene/base/stdlib_choice/is_constructible.hpp"
25#include "arene/base/stdlib_choice/is_convertible.hpp"
26#include "arene/base/stdlib_choice/move.hpp"
27// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
28
29// parasoft-begin-suppress AUTOSAR-M2_10_1-a "Similar names permitted by M2-10-1 Permit #1"
30// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
31
32namespace arene {
33namespace base {
34
35// parasoft-begin-suppress AUTOSAR-A2_10_1 "Base class is inherited privately so its identifiers are not visible"
36// parasoft-begin-suppress AUTOSAR-A7_3_1-a "False positive: there is no rule A7-3-1"
37// parasoft-begin-suppress AUTOSAR-A10_2_1-b "False positive: this is not a multiple inheritance hierarchy"
38// parasoft-begin-suppress AUTOSAR-A10_2_1-a "False positive: this is not a multiple inheritance hierarchy"
39/// @brief A mapping from a logical pack of indices into a single flat physical output index
40/// @tparam The extents of the space used for this mapping; must be a specialization of @c extents
41template <class Extents>
43 private:
44 /// @brief Convenience typedef referring to the base strided mapping
46
47 public:
48 using typename base_type::extents_type;
49 using typename base_type::index_type;
50 using typename base_type::rank_type;
51 using typename base_type::size_type;
52 /// @brief The tag type of the layout used by this @c mapping
54
55 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
56 /// @brief Construct a right-strided mapping for a default-constructed set of extents
57 constexpr mapping() noexcept
58 : mapping(extents_type{}) {}
59 // parasoft-end-suppress AUTOSAR-A12_1_1-a
60
61 /// @brief Construct a right-strided mapping for the given extents
62 /// @param exts The extents to use
63 /// @pre The size of the index space represented by @c exts fits within <c>index_type</c>, else @c ARENE_PRECONDITION
64 /// violation
65 // NOLINTNEXTLINE(hicpp-explicit-conversions) C++23 defines this as implicit
66 constexpr mapping(extents_type const& exts) noexcept
68
69 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
70 /// @brief Converting constructor from a mapping with a different (but compatible) @c extents_type
71 /// @note This is implicit if and only if @c OtherExtents is implicitly convertible to @c extents_type
72 /// @tparam OtherExtents Type of <c>other</c>'s @c extents
73 /// @param other The other @c layout_right::mapping
74 /// @pre @c other.required_span_size() can be represented as a value of *this* type's <c>index_type</c>, else
75 /// @c ARENE_PRECONDITION violation
76 template <
77 typename OtherExtents,
79 // NOLINTNEXTLINE(hicpp-explicit-conversions) C++23 defines this as implicit
82 // parasoft-end-suppress AUTOSAR-A12_1_1-a
83
84 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
85 /// @brief Converting constructor from a mapping with a different (but compatible) @c extents_type
86 /// @note This is implicit if and only if @c OtherExtents is implicitly convertible to @c extents_type
87 /// @tparam OtherExtents Type of <c>other</c>'s @c extents
88 /// @param other The other @c layout_right::mapping
89 /// @pre @c other.required_span_size() can be represented as a value of *this* type's <c>index_type</c>, else
90 /// @c ARENE_PRECONDITION violation
91 template <
92 typename OtherExtents,
96 constexpr explicit mapping(mapping<OtherExtents> const& other) noexcept
98 // parasoft-end-suppress AUTOSAR-A12_1_1-a
99
100 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
101 /// @brief Converting constructor from a @c layout_left::mapping when both have 0- or 1-dimensional extents
102 /// @note This is implicit if and only if @c OtherExtents is implicitly convertible to @c extents_type
103 /// @tparam OtherExtents Type of <c>other</c>'s @c extents
104 /// @param other The @c layout_left::mapping
105 /// @pre @c other.required_span_size() can be represented as a value of *this* type's <c>index_type</c>, else
106 /// @c ARENE_PRECONDITION violation
107 template <
108 typename OtherExtents,
111 std::enable_if_t<OtherExtents::rank() <= rank_type{1U}>> = nullptr>
112 // NOLINTNEXTLINE(hicpp-explicit-conversions) C++23 defines this as implicit
115 // parasoft-end-suppress AUTOSAR-A12_1_1-a
116
117 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
118 /// @brief Converting constructor from a @c layout_left::mapping when both have 0- or 1-dimensional extents
119 /// @note This is implicit if and only if @c OtherExtents is implicitly convertible to @c extents_type
120 /// @tparam OtherExtents Type of <c>other</c>'s @c extents
121 /// @param other The @c layout_left::mapping
122 /// @pre @c other.required_span_size() can be represented as a value of *this* type's <c>index_type</c>, else
123 /// @c ARENE_PRECONDITION violation
124 template <
125 typename OtherExtents,
129 std::enable_if_t<OtherExtents::rank() <= rank_type{1U}>> = nullptr>
132 // parasoft-end-suppress AUTOSAR-A12_1_1-a
133
134 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
135 /// @brief Converting constructor from a @c layout_stride::mapping with a compatible @c extents_type
136 /// @note This is implicit if and only if <c>OtherExtents::rank() == 0</c>
137 /// @tparam OtherExtents Type of <c>other</c>'s @c extents
138 /// @param other The @c layout_stride::mapping
139 /// @pre @c other.required_span_size() can be represented as a value of *this* type's <c>index_type</c>, else
140 /// @c ARENE_PRECONDITION violation
141 /// @pre <c>other</c>'s strides are exactly those of a @c layout_right::mapping with its <c>extents</c>, else
142 /// @c ARENE_PRECONDITION violation
143 template <
144 typename OtherExtents,
147 std::enable_if_t<OtherExtents::rank() == rank_type{0U}>> = nullptr>
148 // NOLINTNEXTLINE(hicpp-explicit-conversions) C++23 defines this as implicit
149 constexpr mapping(layout_stride::mapping<OtherExtents> const& other) noexcept
151 // The second precondition need not be checked here, because rank-0 strides are empty and so always right-strided.
152 }
153 // parasoft-end-suppress AUTOSAR-A12_1_1-a
154
155 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: this is a delegating constructor"
156 /// @brief Converting constructor from a @c layout_stride::mapping with a compatible @c extents_type
157 /// @note This is implicit if and only if <c>OtherExtents::rank() == 0</c>
158 /// @tparam OtherExtents Type of <c>other</c>'s @c extents
159 /// @param other The @c layout_stride::mapping
160 /// @pre @c other.required_span_size() can be represented as a value of *this* type's <c>index_type</c>, else
161 /// @c ARENE_PRECONDITION violation
162 /// @pre <c>other</c>'s strides are exactly those of a @c layout_right::mapping with its <c>extents</c>, else
163 /// @c ARENE_PRECONDITION violation
164 template <
165 typename OtherExtents,
168 std::enable_if_t<(OtherExtents::rank() > rank_type{0U})>> = nullptr>
169 constexpr explicit mapping(layout_stride::mapping<OtherExtents> const& other) noexcept
171 // For coverage purposes, this enforces the 2nd precondition in a separate function that doesn't depend on Extents.
173 this->strides(),
174 other.strides()
175 );
176 }
177 // parasoft-end-suppress AUTOSAR-A12_1_1-a
178
179 using base_type::extents;
181 using base_type::stride;
182 using base_type::operator();
183
186 using base_type::is_strided;
187 using base_type::is_unique;
188
189 /// @brief Return whether or not this mapping is always exhaustive, i.e. every element is reachable using some indices
190 /// @return @c true because the mapping is always computed by a simple invertible right-strided algorithm
191 /// @note In mathematical terms this asks if the mapping is always surjective/onto.
192 static constexpr auto is_always_exhaustive() noexcept -> bool { return true; }
193
194 /// @brief Return whether or not this instance is exhaustive, i.e. every element is reachable using some indices
195 /// @return @c true if every provided stride is the product of the extents corresponding to some subset of the other
196 /// strides, otherwise @c false
197 /// @note In mathematical terms this asks if the mapping is surjective/onto.
198 static constexpr auto is_exhaustive() noexcept -> bool { return true; }
199
200 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
201 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Mixed comparisons permitted by A13-5-5 Permit #1"
202 /// @brief Compare two right-strided mappings for equality
203 /// @tparam OtherExtents The type of the extents used by the right-hand side of the comparison
204 /// @param left An instance of @c layout_right::mapping
205 /// @param right An instance of @c layout_right::mapping<OtherExtents>
206 /// @return @c true if @c left and @c right have equal extents
207 template <
208 typename OtherExtents,
210 friend constexpr auto operator==(mapping const& left, mapping<OtherExtents> const& right) noexcept -> bool {
211 return left.extents() == right.extents();
212 }
213
214 /// @brief Compare two right-strided mappings for inequality
215 /// @tparam OtherExtents The type of the extents used by the right-hand side of the comparison
216 /// @param left An instance of @c layout_right::mapping
217 /// @param right An instance of @c layout_right::mapping<OtherExtents>
218 /// @return @c true if @c left and @c right have unequal extents
219 template <
220 typename OtherExtents,
222 friend constexpr auto operator!=(mapping const& left, mapping<OtherExtents> const& right) noexcept -> bool {
223 return !(left == right);
224 }
225 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
226 // parasoft-end-suppress AUTOSAR-A11_3_1-a
227
228 private:
229 /// @brief obtain a check_bypasser passkey to skip precondition checks on
230 /// mapping construction
231 /// @return check_bypasser value
232 static constexpr auto passkey() noexcept -> layout_detail::check_bypasser { return layout_detail::check_bypasser{}; }
233
234 /// @brief Access the strides of a @c mapping via the derived class rather than its private base
235 /// @param src the @c mapping to read strides from
236 /// @return @c src 's strides
237 ///
238 /// @note This exists as a workaround for a GCC bug (present on gcc8) where access checking for a
239 /// hidden friend's trailing return type incorrectly treats the mapping's private base class as
240 /// inaccessible when the friend is found via ADL through a separate SFINAE context
241 /// (e.g. @c is_invocable_v inside @c arene::base::invoke ). Routing the call through this
242 /// static member performs the access check on the derived class, which GCC handles correctly,
243 /// just like the @c passkey() workaround above.
244 static constexpr auto strides_of(mapping const& src) noexcept
246 return src.strides();
247 }
248
249 public:
250 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
251
252 /// @brief Compute the sub-mapping for a @c layout_right::mapping
253 /// @tparam CanonicalSliceSpecifiers types of the slice specifiers, one per dimension
254 /// @param src the source mapping to slice
255 /// @param slices the slice specifiers
256 ///
257 /// Uses @c slices to compute the sub-extents, sub-strides, and offset of the submdspan. The @c slices must be in
258 /// canonical form.
259 ///
260 /// @return A @c submdspan_mapping_result containing the sub-mapping and offset such that indexing the sub-mapping and
261 /// adding the offset recovers the corresponding index in the original mapping.
262 ///
263 /// @note Constraints <br>
264 /// * <c> sizeof...(CanonicalSliceSpecifiers) == extents_type::rank() </c>
265 /// * for each rank index @c k of @c src.extents(), @c CanonicalSliceSpecifiers...[k] is a valid submdspan slice
266 /// type for the @c k-th extent of @c extents_type
267 ///
268 /// @note Preconditions <br>
269 /// * for each rank index @c k of @c src.extents(), @c slices...[k] denotes a valid submdspan slice for the @c k-th
270 /// extent of @c src.extents()
271 ///
272 /// @note Remarks <br>
273 /// * the @c layout_right specialization of @c submdspan_mapping produces a @c layout_right::mapping if:
274 /// * for each k in the range <c> [SubExtents::rank() - 1, extents_type::rank()) </c>,
275 /// @c CanonicalSliceSpecifiers...[k] denotes @c full_extent_t; and
276 /// * for k equal to <c> extents_type::rank() - SubExtents::rank() </c>, @c CanonicalSliceSpecifiers...[k] is a
277 /// unit-stride slice type;
278 /// * Otherwise, it produces a @c layout_stride::mapping.
279 template <
285 nullptr>
310
311 // parasoft-end-suppress AUTOSAR-A11_3_1-a
312};
313// parasoft-end-suppress AUTOSAR-A2_10_1
314// parasoft-end-suppress AUTOSAR-A7_3_1-a
315// parasoft-end-suppress AUTOSAR-A10_2_1-b
316// parasoft-end-suppress AUTOSAR-A10_2_1-a
317
318/// @brief Specialization of @c is_sliceable_mapping_v indicating @c layout_right::mapping supports @c submdspan
319/// @tparam Extents Any specialization of @c arene::base::extents
320template <typename Extents>
322
323} // namespace base
324} // namespace arene
325
326// parasoft-end-suppress AUTOSAR-M2_10_1-a "Similar names permitted by M2-10-1 Permit #1"
327// parasoft-end-suppress AUTOSAR-A7_1_5-a-2
328
329#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_LAYOUT_RIGHT_HPP_
A mapping from a logical pack of indices into a single flat physical output index.
Definition layout_left.hpp:84
static constexpr auto is_always_exhaustive() noexcept -> bool
Return whether or not this mapping is always exhaustive, i.e. every element is reachable using some i...
Definition layout_left.hpp:234
constexpr mapping(extents_type const &exts) noexcept
Construct a left-strided mapping for the given extents.
Definition layout_left.hpp:108
constexpr mapping() noexcept
Construct a default left-strided mapping for the given extents.
Definition layout_left.hpp:99
static constexpr auto is_exhaustive() noexcept -> bool
Return whether or not this instance is exhaustive, i.e. every element is reachable using some indices...
Definition layout_left.hpp:240
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10