Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
extents.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_EXTENTS_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_EXTENTS_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/compiler_support/cpp14_inline.hpp"
11#include "arene/base/constraints/constraints.hpp"
12#include "arene/base/detail/dynamic_extent.hpp"
13#include "arene/base/functional/not_fn.hpp"
14#include "arene/base/mdspan/detail/deduced_static_extent.hpp"
15#include "arene/base/mdspan/detail/extent_sequence.hpp"
16#include "arene/base/mdspan/detail/extract_dynamic_extents_for.hpp"
17#include "arene/base/mdspan/detail/to_array.hpp"
18#include "arene/base/span/span.hpp"
19#include "arene/base/stdlib_choice/cstddef.hpp"
20#include "arene/base/stdlib_choice/enable_if.hpp"
21#include "arene/base/stdlib_choice/forward.hpp"
22#include "arene/base/stdlib_choice/integer_sequence.hpp"
23#include "arene/base/stdlib_choice/integral_constant.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/is_integral.hpp"
27#include "arene/base/stdlib_choice/is_same.hpp"
28#include "arene/base/stdlib_choice/make_unsigned.hpp"
29#include "arene/base/stdlib_choice/move.hpp"
30#include "arene/base/stdlib_choice/numeric_limits.hpp"
31#include "arene/base/type_traits/all_of.hpp"
32#include "arene/base/type_traits/remove_cvref.hpp"
33#include "arene/base/utility/safe_comparisons.hpp"
34// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
35
36namespace arene {
37namespace base {
38
39namespace extents_detail {
40
41/// @brief helper to check that index type and extents are valid
42/// @tparam IndexType the index type
43/// @tparam Extents sequence of static extent values
44///
45/// Determines if @c IndexType and @c Extents are valid for a specialization of
46/// @c extents. The value of this helper is @c true if:
47/// * @c IndexType is a signed or unsigned integer type, and
48/// * each element of @c Extents is either equal to @c dynamic_extent, or is
49/// representable as a value of type @c IndexType
50///
51template <class IndexType, std::size_t... Extents>
52static constexpr bool valid_extents_template_parameters_v{
53 //
54 std::is_integral<IndexType>::value && //
55 !std::is_same<IndexType, bool>::value && //
56 all_of_v<((Extents == dynamic_extent) || cmp_less_equal(Extents, std::numeric_limits<IndexType>::max()))...>};
57
58} // namespace extents_detail
59
60// parasoft-begin-suppress AUTOSAR-A10_1_1-a-2 "Multiple inheritance does not make the code any more difficult to
61// maintain than a class having multiple data members"
62// parasoft-begin-suppress AUTOSAR-A12_1_5-a "False positive: Delegating constructors are used where they can be"
63// parasoft-begin-suppress AUTOSAR-A14_5_1-a "False positive: There is no template constructor"
64// parasoft-begin-suppress AUTOSAR-A2_10_1-e "False positive: 'extents' does not hide an identifier in 'tuple'"
65/// @brief represents a multidimensional index space
66/// @tparam IndexType the index type
67/// @tparam Extents the static extents of each dimension
68template <typename IndexType, std::size_t... Extents>
72{
73 /// @brief sequence of static extents
75
76 /// @brief array holding the dynamic extents, if any
78
79 /// @brief obtain the array holding the dynamic extents
80 /// @return reference to the array holding dynamic extents
81 constexpr auto dynamic_extents() const noexcept -> dynamic_extents_storage_type const& //
82 {
83 return static_cast<dynamic_extents_storage_type const&>(*this);
84 }
85
86 /// @brief Helper trait to specify if copying from another @c extents object with a different index type and/or
87 /// extents list should be explicit. The value is @c true if the constructor should be explicit, @c false otherwise.
88 /// @tparam OtherIndexType The index type of the other @c extents object
89 /// @tparam OtherExtentSequence The extents of the other @c extents object
90 template <class OtherIndexType, class OtherExtentSequence>
91 static constexpr bool copy_from_other_extents_is_explicit_v{
97 )
98 };
99
100 public:
101 static_assert(
102 extents_detail::valid_extents_template_parameters_v<IndexType, Extents...>,
103 "invalid template parameters for 'extents'"
104 );
105
106 // parasoft-begin-suppress AUTOSAR-A2_10_1-e "False positive: static members cannot hide members of mdspan"
107 /// @brief The specified index type for the extents
108 using index_type = IndexType;
109 /// @brief An unsigned type for representing an index into a dimension
111 /// @brief The type of the rank
113 // parasoft-end-suppress AUTOSAR-A2_10_1-e
114
118
119 /// @brief Construct an @c extents object with the specified list of extents
120 /// @tparam OtherIndexType The type of the supplied extents
121 /// @tparam N The number of supplied extents
122 /// @param exts The supplied extents
123 /// @pre @c OtherIndexType must be convertible to @c IndexType without throwing
124 /// @pre Each of @c exts must be representable as a non-negative value of @c IndexType
125 /// @pre The size of the span, @c N , must be equal to @c rank()
126 /// @pre For each extent in @c Extents, if the corresponding value is not @c dynamic_extent, then the provided
127 /// value, when converted to @c IndexType, must be the same as the specified value in @c Extents
128 template <
129 typename OtherIndexType,
130 std::size_t N,
132 std::enable_if_t<N == rank()>,
136 // NOLINTNEXTLINE(hicpp-explicit-conversions)
141
142 /// @brief Construct an @c extents object with the specified list of extents
143 /// @tparam OtherIndexType The type of the supplied extents
144 /// @param exts The supplied extents
145 /// @pre @c OtherIndexType must be convertible to @c IndexType without throwing
146 /// @pre The size of the span must be equal to @c rank() or @c dynamic_rank()
147 /// @pre Each of @c exts must be representable as a non-negative value of @c IndexType
148 template <
149 typename OtherIndexType,
153 // NOLINTNEXTLINE(hicpp-explicit-conversions)
158
159 /// @brief Construct an @c extents object with the specified list of extents
160 /// @tparam OtherIndexType The type of the supplied extents
161 /// @param exts The supplied extents
162 /// @pre @c OtherIndexType must be convertible to @c IndexType without throwing
163 /// @pre The size of the array must be equal to @c rank() or @c dynamic_rank()
164 /// @pre Each of @c exts must be representable as a non-negative value of @c IndexType
165 /// @pre For each extent in @c Extents, if the corresponding value is not @c dynamic_extent, then the provided
166 /// value, when converted to @c IndexType, must be the same as the specified value in @c Extents
167 template <
168 typename OtherIndexType,
172 // NOLINTNEXTLINE(hicpp-explicit-conversions)
177
178 /// @brief Construct an @c extents object with the specified list of extents
179 /// @tparam OtherIndexType The type of the supplied extents
180 /// @tparam N The number of supplied extents
181 /// @param exts The supplied extents
182 /// @pre @c OtherIndexType must be convertible to @c IndexType without throwing
183 /// @pre The size of the array, @c N , must be equal to @c rank()
184 /// @pre Each of @c exts must be representable as a non-negative value of @c IndexType
185 /// @pre For each extent in @c Extents, if the corresponding value is not @c dynamic_extent, then the provided
186 /// value, when converted to @c IndexType, must be the same as the specified value in @c Extents
187 template <
188 typename OtherIndexType,
189 std::size_t N,
191 std::enable_if_t<N == rank()>,
195 // NOLINTNEXTLINE(hicpp-explicit-conversions)
200
201 // parasoft-begin-suppress CERT_C-EXP37-a "False positive: All parameters have a name"
202 /// @brief Construct an @c extents object with the specified list of dynamic extents
203 /// @tparam OtherIndexTypes The types of the supplied dynamic extents
204 /// @param exts The supplied dynamic extents
205 /// @pre Each of @c OtherIndexTypes must be convertible to @c IndexType without throwing
206 /// @pre Each of @c exts must be representable as a non-negative value of @c IndexType
207 template <
208 typename... OtherIndexTypes,
213 // NOLINTNEXTLINE(hicpp-explicit-conversions)
214 explicit constexpr extents(OtherIndexTypes... exts) noexcept
216 {}
217 // parasoft-end-suppress CERT_C-EXP37-a
218
219 // parasoft-begin-suppress CERT_C-EXP37-a "False positive: All parameters have a name"
220 /// @brief Construct an @c extents object with the specified list of extents
221 /// @tparam OtherIndexTypes The types of the supplied extents
222 /// @param exts The supplied extents
223 /// @pre Each of @c OtherIndexTypes must be convertible to @c IndexType without throwing
224 /// @pre Each of @c exts must be representable as a non-negative value of @c IndexType
225 /// @pre For each extent in @c Extents, if the corresponding value is not @c dynamic_extent, then the provided
226 /// value, when converted to @c IndexType, must be the same as the specified value in @c Extents
227 template <
228 typename... OtherIndexTypes,
230 std::enable_if_t<sizeof...(OtherIndexTypes) == rank()>,
234 // NOLINTNEXTLINE(hicpp-explicit-conversions)
235 explicit constexpr extents(OtherIndexTypes... exts) noexcept
237 {}
238 // parasoft-end-suppress CERT_C-EXP37-a
239
240 /// @brief Construct an @c extents object with the same set of extents as the source extents object
241 /// @tparam OtherIndexType The index type of the supplied extents
242 /// @tparam OtherExtents The supplied extents
243 /// @param source_extents The @c extents object to copy the extents from
244 /// @pre The other extents must match fixed extents, or be in range of @c IndexType for dynamic extents
245 template <
246 typename OtherIndexType,
251 std::enable_if_t<sizeof...(OtherExtents) == rank()>,
254 nullptr>
255 // NOLINTNEXTLINE(hicpp-explicit-conversions)
259
260 // parasoft-begin-suppress AUTOSAR-A0_1_4-a "False positive: parameter 'source_extents' is used"
261 /// @brief Construct an @c extents object with the same set of extents as the source extents object
262 /// @tparam OtherIndexType The index type of the supplied extents
263 /// @tparam OtherExtents The supplied extents
264 /// @param source_extents The @c extents object to copy the extents from
265 /// @pre The other extents must match fixed extents, or be in range of @c IndexType for dynamic extents
266 template <
267 typename OtherIndexType,
272 std::enable_if_t<sizeof...(OtherExtents) == rank()>,
275 nullptr>
279 // parasoft-end-suppress AUTOSAR-A0_1_4-a
280
281 /// @brief Construct an @c extents object with all the dynamic extents set to zero, if any
282 constexpr extents() noexcept
283 // GCC earlier than 12 does not default initialize base classes correctly with '=default'
285 {}
286
287 // parasoft-begin-suppress AUTOSAR-M9_3_3-a-2 "False positive: member function cannot be 'static'"
288 // parasoft-begin-suppress AUTOSAR-A8_4_2-a CERT_CPP-MSC52-a-2 CERT_C-MSC37-a "False positive: this function returns a
289 // value"
290 /// @brief Get the actual extent for the given dimension, returning the extent supplied to the constructor for dynamic
291 /// extents
292 /// @param dimension The index of the dimension for which to get the extent
293 /// @return The extent of the specified dimension
294 constexpr auto extent(rank_type dimension) const noexcept -> index_type {
297 // parasoft-begin-suppress AUTOSAR-M14_6_1-a-2 "Use of 'qualified-id::operator[]' hurts developer readability"
299 // parasoft-end-suppress AUTOSAR-M14_6_1-a-2
300 }
301 return static_cast<index_type>(default_extent);
302 }
303 // parasoft-end-suppress AUTOSAR-A8_4_2-a CERT_CPP-MSC52-a-2 CERT_C-MSC37-a
304 // parasoft-end-suppress AUTOSAR-M9_3_3-a-2
305
306 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
307 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Mixed comparisons permitted by A13-5-5 Permit #1"
308 /// @brief Compare two extents objects with the same rank to see if they have the same values
309 /// @tparam OtherIndexType The index type of the other extents type
310 /// @tparam OtherExtents The extents of the other extents type
311 /// @param lhs The first @c extents object to compare
312 /// @param rhs The second @c extents object to compare
313 /// @return @c true if @c lhs.extent(index) is equal to @c rhs.extent(index) for all @c index values in @c
314 /// [0,lhs.rank()) otherwise @c false.
315 template <
316 typename OtherIndexType,
318 constraints<std::enable_if_t<rank() == sizeof...(OtherExtents)>> = nullptr>
319 friend constexpr auto operator==(extents const& lhs, extents<OtherIndexType, OtherExtents...> const& rhs) noexcept
320 -> bool {
321 for (rank_type index{}; index < rank(); ++index) {
323 return false;
324 }
325 }
326 return true;
327 }
328 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
329 // parasoft-end-suppress AUTOSAR-A11_3_1-a
330
331 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
332 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Mixed comparisons permitted by A13-5-5 Permit #1"
333 /// @brief Compare two extents objects with different ranks to see if they have the same values
334 /// @tparam OtherIndexType The index type of the other extents type
335 /// @tparam OtherExtents The extents of the other extents type
336 /// @return @c false.
337 template <
338 typename OtherIndexType,
340 constraints<std::enable_if_t<rank() != sizeof...(OtherExtents)>> = nullptr>
341 friend constexpr auto operator==(extents const&, extents<OtherIndexType, OtherExtents...> const&) noexcept -> bool {
342 return false;
343 }
344 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
345 // parasoft-end-suppress AUTOSAR-A11_3_1-a
346
347 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
348 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Mixed comparisons permitted by A13-5-5 Permit #1"
349 /// @brief Compare two extents objects to see if they have different values
350 /// @tparam OtherIndexType The index type of the other extents type
351 /// @tparam OtherExtents The extents of the other extents type
352 /// @param lhs The first @c extents object to compare
353 /// @param rhs The second @c extents object to compare
354 /// @return The inverse of @c lhs==rhs
355 template <typename OtherIndexType, std::size_t... OtherExtents>
356 friend constexpr auto operator!=(extents const& lhs, extents<OtherIndexType, OtherExtents...> const& rhs) noexcept
357 -> bool {
358 return !(lhs == rhs);
359 }
360 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
361 // parasoft-end-suppress AUTOSAR-A11_3_1-a
362};
363// parasoft-end-suppress AUTOSAR-A14_5_1-a
364// parasoft-end-suppress AUTOSAR-A12_1_5-a
365// parasoft-end-suppress AUTOSAR-A10_1_1-a-2
366// parasoft-end-suppress AUTOSAR-A2_10_1-e
367
368namespace extents_detail {
369
370/// @brief helper to determine the @c extents type with repeated
371/// @c dynamic_extent s
372/// @tparam IndexType @c extents index type
373/// @tparam IndexSequence specialization of @c std::index_sequence
374template <class IndexType, class IndexSequence>
375class dextents_helper {};
376
377/// @brief helper to determine the @c extents type with repeated
378/// @c dynamic_extent s
379/// @tparam IndexType @c extents index type
380/// @tparam Is index sequence, values are ignored
381template <class IndexType, std::size_t... Is>
382class dextents_helper<IndexType, std::index_sequence<Is...>> {
383 public:
384 /// @brief specialization of @c extents
385 using type = extents<IndexType, (static_cast<void>(Is), dynamic_extent)...>;
386};
387
388/// @brief helper to determine the @c extents type with repeated
389/// @c dynamic_extent s
390/// @tparam IndexType @c extents index type
391/// @tparam Rank @c extents rank
392///
393/// @note This indirection is used to prevent IWYU from suggesting users of
394/// @c dextents include a header for @c make_integer_sequence.
395template <class IndexType, std::size_t Rank>
396class dextents_helper<IndexType, std::integral_constant<std::size_t, Rank>>
397 : public dextents_helper<IndexType, std::make_index_sequence<Rank>> {};
398
399} // namespace extents_detail
400
401/// @brief Backport of @c std::dextents from C++23, a type representing the extents of a multidimensional array with all
402/// dynamic extents
403/// @tparam IndexType the index type
404/// @tparam Rank The number of dimensions of the array
405/// @pre @c IndexType must be an integral type other than @c bool
406template <typename IndexType, std::size_t Rank>
408
409/// @brief Helper variable to check if a provided type is an instantiation of @c extents
410///
411/// The value is @c true if the type is an instantiation of @c extents, @c false otherwise
412/// @tparam T The type to check
413template <typename T>
414extern constexpr bool is_extents_v = false;
415
416/// @brief Helper variable to check if a provided type is an instantiation of @c extents
417///
418/// The value is @c true if the type is an instantiation of @c extents, @c false otherwise
419/// @tparam IndexType the index type
420/// @tparam Extents sequence of static extents
421template <typename IndexType, std::size_t... Extents>
422extern constexpr bool is_extents_v<extents<IndexType, Extents...>> = true;
423
424namespace extents_detail {
425
426/// @brief function object implementing make_extents
427class make_extents_fn //
428{
429 public:
430 // parasoft-begin-suppress AUTOSAR-A0_1_4-a "False positive: parameter 'extents_values' is used"
431 // parasoft-begin-suppress AUTOSAR-A8_4_2-a "False positive: function does have a return"
432 // parasoft-begin-suppress CERT_C-MSC37-a "False positive: function does have a return"
433 // parasoft-begin-suppress CERT_CPP-MSC52-a "False positive: function does have a return"
434 /// @brief Construct an @c extents object from the supplied extents values, using static extents if the arguments are
435 /// instances of @c std::integral_constant and dynamic extents otherwise
436 /// @tparam Integrals The types of the arguments
437 /// @param extents_values The specified extents values
438 /// @return An @c extents object with static extents with the specified values
439 /// for every value in @c extents_values that is an instance of @c
440 /// std::integral_constant, and dynamic extents for all other extents.
441 template <typename... Integrals>
442 // parasoft-begin-suppress CERT_C-EXP37-a "False positive: The rule does not mention naming all parameters, also
443 // they are named"
444 constexpr auto operator()(Integrals&&... extents_values) const noexcept
445 -> arene::base::extents<std::size_t, mdspan_detail::deduced_static_extent_v<remove_cvref_t<Integrals>>...> {
446 return arene::base::extents<std::size_t, mdspan_detail::deduced_static_extent_v<remove_cvref_t<Integrals>>...>(
447 std::forward<Integrals>(extents_values)...
448 );
449 }
450 // parasoft-end-suppress CERT_C-EXP37-a
451 // parasoft-end-suppress AUTOSAR-A8_4_2-a
452 // parasoft-end-suppress CERT_C-MSC37-a
453 // parasoft-end-suppress CERT_CPP-MSC52-a
454 // parasoft-end-suppress AUTOSAR-A0_1_4-a
455};
456} // namespace extents_detail
457
458/// @def arene::base::make_extents
459/// @copydoc arene::base::extents_detail::make_extents_fn::operator()
460// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
461// object used in multiple TUs."
462// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
463// object used in multiple TUs."
464ARENE_CPP14_INLINE_VARIABLE(extents_detail::make_extents_fn, make_extents);
465// parasoft-end-suppress AUTOSAR-M7_3_3-a
466// parasoft-end-suppress CERT_CPP-DCL59-a
467
468} // namespace base
469} // namespace arene
470
471#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_MDSPAN_EXTENTS_HPP_
represents a multidimensional index space
Definition extents.hpp:72
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(extents_detail::make_extents_fn, make_extents)
constexpr bool is_extents_v
Helper variable to check if a provided type is an instantiation of extents.
constexpr bool is_extents_v< extents< IndexType, Extents... > >
Helper variable to check if a provided type is an instantiation of extents.
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10