Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
cartesian_product.hpp
Go to the documentation of this file.
1// parasoft-suppress AUTOSAR-A2_8_1-a "False positive: also defines arene::base::type_lists::cartesian_product"
2// Copyright 2026, Toyota Motor Corporation
3//
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5
6#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TYPE_LIST_CARTESIAN_PRODUCT_HPP_
7#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TYPE_LIST_CARTESIAN_PRODUCT_HPP_
8
9// IWYU pragma: private, include "arene/base/type_list.hpp"
10// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
11
12// parasoft-begin-suppress AUTOSAR-A16_2_2-a "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
13#include "arene/base/array/array.hpp"
14#include "arene/base/iterator/next.hpp"
15#include "arene/base/stdlib_choice/cstddef.hpp"
16#include "arene/base/stdlib_choice/integer_sequence.hpp"
17#include "arene/base/type_list/at.hpp"
18#include "arene/base/type_list/size.hpp"
19#include "arene/base/type_list/type_list.hpp"
20// parasoft-end-suppress AUTOSAR-A16_2_2-a
21
22namespace arene {
23namespace base {
24
25namespace type_lists {
26
27namespace cartesian_product_detail {
28
29/// @brief Determine the size of the space of all permutations of indices fitting within the given @c sizes
30/// @tparam Dimension The number of individual indices (and sizes) being permuted
31/// @param sizes The sizes within which the indices of a permutation must fit
32/// @return The number of unique permutations fitting within the given @c sizes
33/// @note This is essentially just a C++17 fold expression over multiplication but dim 0 is taken to be size 0
34template <std::size_t Dimension>
35constexpr auto permutation_space_size_impl(arene::base::array<std::size_t, Dimension> const& sizes) noexcept
36 -> std::size_t {
37 if (Dimension == 0U) {
38 return 0U;
39 }
40
41 std::size_t product{1U};
42 // This isn't a range-based for loop due to a bug in GCC8 C++17 mode, which treats *sizes.begin() as not constexpr.
43 // parasoft-begin-suppress AUTOSAR-A6_5_1-a "Index-based loop needed to work around a GCC8 bug"
44 for (std::size_t idx{}; idx < sizes.size(); ++idx) {
45 product *= sizes[idx];
46 }
47 // parasoft-end-suppress AUTOSAR-A6_5_1-a
48 return product;
49}
50
51/// @brief The size of the space of all permutations of indices fitting within the given @c Sizes
52/// @tparam Sizes The sizes within which the indices of a permutation must fit
53template <std::size_t... Sizes>
54struct permutation_space_size {
55 /// @brief @c Sizes as an array so they can be passed to @c permutation_space_size_impl
56 static constexpr arene::base::array<std::size_t, sizeof...(Sizes)> sizes{Sizes...};
57 /// @brief The actual size of the permutation space
58 static constexpr std::size_t value{permutation_space_size_impl(sizes)};
59};
60
61/// @brief The size of the space of all permutations of indices fitting within the given @c Sizes
62/// @tparam Sizes The sizes within which the indices of a permutation must fit
63template <std::size_t... Sizes>
64constexpr std::size_t permutation_space_size_v{permutation_space_size<Sizes...>::value};
65
66/// @brief Make an array of all permutations of indices fitting within the given @c Sizes
67/// @tparam Sizes A pack of sizes which all indices (of the same dimension) must be less than
68/// @return An array of all possible permutations of "one in-bounds index for each size in <c>Sizes</c>"
69template <std::size_t... Sizes>
70constexpr auto all_index_permutations_impl() noexcept
71 -> arene::base::array<arene::base::array<std::size_t, sizeof...(Sizes)>, permutation_space_size_v<Sizes...>> {
72 using permutation = arene::base::array<std::size_t, sizeof...(Sizes)>;
73
74 // parasoft-begin-suppress AUTOSAR-M8_5_2-a "False positive: this correctly initializes both objects to all 0s"
75 constexpr permutation sizes{Sizes...};
76 arene::base::array<permutation, permutation_space_size_v<Sizes...>> permutations{};
77 // parasoft-end-suppress AUTOSAR-M8_5_2-a
78
79 permutation indices{};
80 for (auto perm_itr = arene::base::next(permutations.begin()); perm_itr < permutations.end(); ++perm_itr) {
81 // Increment the least significant index and carry until we don't need to carry anymore
82 indices[sizeof...(Sizes) - 1U] += 1U;
83 bool carry{false};
84 auto size_itr = sizes.rbegin();
85 // parasoft-begin-suppress AUTOSAR-A6_5_1-a "False positive: loop is reversed so can't use range-for without ranges"
86 for (auto idx_itr = indices.rbegin(); idx_itr != indices.rend(); ++idx_itr) {
87 if (carry) {
88 carry = false;
89 *idx_itr += 1U;
90 }
91 if (*idx_itr == *size_itr) {
92 carry = true;
93 *idx_itr = 0U;
94 }
95 if (!carry) {
96 break;
97 }
98 ++size_itr;
99 }
100 // parasoft-end-suppress AUTOSAR-A6_5_1-a
101
102 // Save this permutation and move on to the next one
103 *perm_itr = indices;
104 }
105
106 return permutations;
107}
108
109/// @brief As a static variable, an array of all permutations of indices fitting within the given @c Sizes
110/// @tparam Sizes A pack of sizes which all indices (of the same dimension) must be less than
111template <std::size_t... Sizes>
112constexpr arene::base::array<arene::base::array<std::size_t, sizeof...(Sizes)>, permutation_space_size_v<Sizes...>>
113 all_index_permutations_v{all_index_permutations_impl<Sizes...>()};
114
115/// @brief Get the n'th permutation of the types in the type-list pack @c Ln and emit it wrapped in @c InnerTemplate
116/// @tparam InnerTemplate The template to apply to the permuted type-list
117/// @tparam PermIndex The index of this particular permutation
118/// @tparam Ln The pack of purported type lists to permute
119template <template <class...> class InnerTemplate, std::size_t PermIndex, class... Ln>
120class nth_type_permutation {
121 // parasoft-begin-suppress CERT_CPP-DCL56-a "False positive: constexpr variables are always initialized in constexpr"
122 // parasoft-begin-suppress AUTOSAR-A3_3_2-a "False positive: constexpr variables are always initialized in constexpr"
123 /// @brief The *index* permutation used by this type permutation
124 static constexpr arene::base::array<std::size_t, sizeof...(Ln)> const& index_permutation{
125 all_index_permutations_v<size_v<Ln>...>[PermIndex]
126 };
127 // parasoft-end-suppress CERT_CPP-DCL56-a
128 // parasoft-end-suppress AUTOSAR-A3_3_2-a
129
130 // parasoft-begin-suppress CERT_C-EXP37-a "False positive: rule does not mention naming all parameters"
131 /// @brief Generate a pack of types from some permutation of the lists in @c Ln and return it as @c InnerTemplate
132 /// @tparam TypeListIndices a pack of indices of the type *lists* in @c Ln (not the permuted indices)
133 /// @return Notionally a value of type @c InnerTemplate with the pack of permuted types; only used for @c decltype
134 template <std::size_t... TypeListIndices>
135 static constexpr auto deduce_type_from_permutation(std::index_sequence<TypeListIndices...>)
136 -> InnerTemplate<at_t<Ln, index_permutation[TypeListIndices]>...>;
137 // parasoft-end-suppress CERT_C-EXP37-a
138
139 public:
140 /// @brief The permuted types, wrapped in @c InnerTemplate
141 using type = decltype(deduce_type_from_permutation(std::index_sequence_for<Ln...>{}));
142};
143
144/// @brief Get the n'th permutation of the types in the type-list pack @c Ln and emit it wrapped in @c InnerTemplate
145/// @tparam InnerTemplate The template to apply to the permuted type-list
146/// @tparam PermIndex The index of this particular permutation
147/// @tparam Ln The pack of purported type lists to permute
148template <template <class...> class InnerTemplate, std::size_t PermIndex, class... Ln>
149using nth_type_permutation_t = typename nth_type_permutation<InnerTemplate, PermIndex, Ln...>::type;
150
151/// @brief Get a type-list of all permutations of the entries of the input type-lists @c Ln
152/// @tparam OuterTemplate The outer type-list template in which to wrap the pack of permuted type-lists
153/// @tparam InnerTemplate The template to apply to each individual permuted type-list within the list of permutations
154/// @tparam PermIndexList An index-list, one for each permutation to include in the emitted type-list
155/// @tparam Ln The pack of purported type lists to permute
156template <
157 template <class...>
158 class OuterTemplate,
159 template <class...>
160 class InnerTemplate,
161 class PermIndexList,
162 class... Ln>
163struct all_type_permutations;
164
165/// @brief Get a type-list of all permutations of the entries of the input type-lists @c Ln
166/// @tparam OuterTemplate The outer type-list template in which to wrap the pack of permuted type-lists
167/// @tparam InnerTemplate The template to apply to each individual permuted type-list within the list of permutations
168/// @tparam PermIndices A pack of indices, one for each permutation to include in the emitted type-list
169/// @tparam Ln The pack of purported type lists to permute
170template <
171 template <class...>
172 class OuterTemplate,
173 template <class...>
174 class InnerTemplate,
175 std::size_t... PermIndices,
176 class... Ln>
177struct all_type_permutations<OuterTemplate, InnerTemplate, std::index_sequence<PermIndices...>, Ln...> {
178 /// @brief A pack of all permutations of the types in <c>Ln</c>, wrapped in @c OuterTemplate
179 using type = OuterTemplate<nth_type_permutation_t<InnerTemplate, PermIndices, Ln...>...>;
180};
181
182/// @brief Get the first type-list template used in the given pack, or fall back to @c arene::base::type_list if none
183/// @tparam Ln The pack of purported type lists to check
184template <class... Ln>
185struct get_first_list_template {
186 /// @brief Fallback for the case where no first list template can be extracted: use @c arene::base::type_list
187 /// @tparam Types A pack of types to hold
188 template <class... Types>
189 using type = arene::base::type_list<Types...>;
190};
191
192/// @brief Get the first type-list template used in the given pack
193/// @tparam FirstInnerTemplate The type-list template to emit
194/// @tparam Ts The types on which @c FirstInnerTemplate is templated; only used for deduction
195/// @tparam RemainingLists Any other type lists which may remain in the pack after picking out the first one
196template <template <class...> class FirstInnerTemplate, class... Ts, class... RemainingLists>
197struct get_first_list_template<FirstInnerTemplate<Ts...>, RemainingLists...> {
198 /// @brief For the case where the first list template can be extracted, return it
199 /// @tparam Types A pack of types to hold
200 template <class... Types>
201 using type = FirstInnerTemplate<Types...>;
202};
203
204} // namespace cartesian_product_detail
205
206/// @brief Produce the cartesian product of multiple type-lists
207///
208/// @tparam Ln A pack of type-lists that holds the types to process.
209/// @return A type list of type lists, where each inner list holds one combination of one type from each @c Ln
210/// @note The type of the resulting type-list, as well as all of the individual permuted type-lists within it, will be
211/// the type of the first type-list within <c>Ln</c>. It will not necessarily be <c>arene::base::type_list</c>.
212/// @note Permutations within the resulting product are ordered lexicographically with respect to the indices of the
213/// types they refer to within the original lists. The first is (0, 0, ... , 0), followed by (0, 0, ... , 1), and so on.
214template <class... Ln>
219 Ln...>;
220
221/// @brief Produce the cartesian product of multiple type-lists
222///
223/// @tparam Ln A pack of type-lists that holds the types to process.
224/// @return A type list of type lists, where each inner list holds one combination of one type from each @c Ln
225/// @note The type of the resulting type-list, as well as all of the individual permuted type-lists within it, will be
226/// the type of the first type-list within <c>Ln</c>. It will not necessarily be <c>arene::base::type_list</c>.
227/// @note Permutations within the resulting product are ordered lexicographically with respect to the indices of the
228/// types they refer to within the original lists. The first is (0, 0, ... , 0), followed by (0, 0, ... , 1), and so on.
229template <class... Ln>
231
232/// @brief The cartesian product of multiple type-lists, with each combination of types bound to @c DesiredInnerTemplate
233///
234/// @tparam DesiredInnerTemplate A template taking only types, to be used as the inner template of the final list
235/// @tparam Ln A pack of type-lists that holds the types to process.
236/// @return A type list of <c>DesiredInnerTemplate</c>; each entry uses one combination of one type from each @c Ln
237/// @note The type of the resulting type-list will be the type of the first type-list within <c>Ln</c>, and the type of
238/// each permuted element within it will be <c>DesiredInnerTemplate</c>. Neither will necessarily be
239/// <c>arene::base::type_list</c>.
240/// @note Permutations within the resulting product are ordered lexicographically with respect to the indices of the
241/// types they refer to within the original lists. The first is (0, 0, ... , 0), followed by (0, 0, ... , 1), and so on.
242template <template <class...> class DesiredInnerTemplate, class... Ln>
247 Ln...>;
248
249/// @brief The cartesian product of multiple type-lists, with each combination of types bound to @c DesiredInnerTemplate
250///
251/// @tparam DesiredInnerTemplate A template taking only types, to be used as the inner template of the final list
252/// @tparam Ln A pack of type-lists that holds the types to process.
253/// @return A type list of <c>DesiredInnerTemplate</c>; each entry uses one combination of one type from each @c Ln
254/// @note The type of the resulting type-list will be the type of the first type-list within <c>Ln</c>, and the type of
255/// each permuted element within it will be <c>DesiredInnerTemplate</c>. Neither will necessarily be
256/// <c>arene::base::type_list</c>.
257/// @note Permutations within the resulting product are ordered lexicographically with respect to the indices of the
258/// types they refer to within the original lists. The first is (0, 0, ... , 0), followed by (0, 0, ... , 1), and so on.
259template <template <class...> class DesiredInnerTemplate, class... Ln>
261
262} // namespace type_lists
263} // namespace base
264} // namespace arene
265
266#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TYPE_LIST_CARTESIAN_PRODUCT_HPP_
Definition apply_all.hpp:14
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10