Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
transform.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::transform"
2
3// Copyright 2024, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_TRANSFORM_HPP_
7#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_TRANSFORM_HPP_
8
9// IWYU pragma: private, include "arene/base/algorithm.hpp"
10// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
11
12// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
13#include "arene/base/compiler_support/cpp14_inline.hpp"
14#include "arene/base/constraints/constraints.hpp"
15#include "arene/base/stdlib_choice/cstddef.hpp"
16#include "arene/base/stdlib_choice/decay.hpp"
17#include "arene/base/stdlib_choice/declval.hpp"
18#include "arene/base/stdlib_choice/enable_if.hpp"
19#include "arene/base/stdlib_choice/forward.hpp"
20#include "arene/base/stdlib_choice/integer_sequence.hpp"
21#include "arene/base/stdlib_choice/make_tuple.hpp"
22#include "arene/base/stdlib_choice/move.hpp"
23#include "arene/base/stdlib_choice/pair.hpp"
24#include "arene/base/stdlib_choice/remove_cv.hpp"
25#include "arene/base/stdlib_choice/remove_reference.hpp"
26#include "arene/base/stdlib_choice/tuple.hpp"
27#include "arene/base/stdlib_choice/tuple_size.hpp"
28#include "arene/base/tuple/detail/get.hpp"
29#include "arene/base/type_traits/comparison_traits.hpp"
30#include "arene/base/type_traits/is_instantiation_of.hpp"
31#include "arene/base/type_traits/iterator_category_traits.hpp"
32#include "arene/base/type_traits/remove_cvref.hpp"
33#include "arene/base/utility/forward_like.hpp"
34// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
35
36namespace arene {
37namespace base {
38
39namespace transform_detail {
40
41/// @brief Transform each element of a tuple-like object with the specified
42/// function. The tuple-like object should support std::get and
43/// std::tuple_size.
44/// @tparam F The transformation function type.
45/// @tparam TupleType The tuple type.
46/// @tparam Is The index sequence.
47/// @param func The transformation function.
48/// @param tuple The tuple.
49/// @return A tuple with elements defined by @c f(std::get<I>(tuple)) for each I.
50template <class F, typename TupleType, std::size_t... Is>
51constexpr auto transform_tuple_impl(F&& func, TupleType&& tuple, std::index_sequence<Is...>) -> decltype(auto) {
52 return std::make_tuple(func(std::get<Is>(std::forward<TupleType>(tuple)))...);
53}
54
55/// @brief Transform each element of an array with the specified function.
56/// @tparam F The transformation function type.
57/// @tparam ArrayType The array type.
58/// @tparam N The array size.
59/// @tparam Is The index sequence.
60/// @param func The transformation function.
61/// @param array The array.
62/// @return An array with elements defined by @c f(std::get<I>(array)) for each I.
63template <template <typename U, std::size_t N> class ToType, typename F, typename FromArrayType>
64constexpr auto transform_array_impl(F&& func, FromArrayType&& array)
65 -> ToType<std::decay_t<decltype(func(*array.begin()))>, 0U> {
66 return ToType<std::decay_t<decltype(func(*array.begin()))>, 0U>{};
67}
68
69/// @brief Transform each element of an array with the specified function.
70/// @tparam F The transformation function type.
71/// @tparam ArrayType The array type.
72/// @tparam N The array size.
73/// @tparam Is The index sequence.
74/// @param func The transformation function.
75/// @param array The array.
76/// @return An array with elements defined by @c f(tuple_detail::get<I>(array)) for each I.
77template <template <typename U, std::size_t N> class ToType, typename F, typename FromArrayType, std::size_t... Is>
78constexpr auto transform_array_impl(F&& func, FromArrayType&& array, std::index_sequence<Is...>)
79 -> ToType<std::decay_t<decltype(func(*array.begin()))>, sizeof...(Is)> {
80 return ToType<std::decay_t<decltype(func(*array.begin()))>, sizeof...(Is)>{
81 func(tuple_detail::get<Is>(std::forward<FromArrayType>(array)))...
82 };
83}
84
85///
86/// @brief Helper for implementing transform as a Niebloid
87///
88class transform_fn {
89 public:
90 ///
91 /// @brief Backport of C++20's unary op constexpr @c std::transform .
92 ///
93 /// @tparam StartItr type of the iterator for the sequence to transform. Must model @c InputIterator .
94 /// @tparam EndItr type of the iterator to compare to for the sequence to transform. Must satisfy
95 /// @c is_equality_comparable<StartItr,EndItr> .
96 /// @tparam OutputItr type of iterator for the output sequence. Must model @c OutputIterator .
97 /// @tparam UnaryOperation type of the function to invoke to transform elements.
98 /// @param start Iterator to the start of the sequence to transform.
99 /// @param end Iterator to the end of the sequence to transform.
100 /// @param out Iterator to the start of the sequence to output the transformed values to.
101 /// @param transform_op Callable that will be invoked on each element in the range @c [start,end) exactly once.
102 /// @return OutputItr iterator in the output sequence pointing to the position after the last element transformed.
103 ///
104 template <
105 typename StartItr,
106 typename EndItr,
107 typename OutputItr,
108 typename UnaryOperation,
109 constraints<
110 std::enable_if_t<is_input_iterator_v<StartItr>>,
111 std::enable_if_t<is_output_iterator_v<OutputItr>>,
112 std::enable_if_t<is_inequality_comparable_v<StartItr, EndItr>>> = nullptr>
113 constexpr auto operator()(StartItr start, EndItr end, OutputItr out, UnaryOperation transform_op) const noexcept( //
114 arene::base::is_nothrow_inequality_comparable_v<StartItr&, EndItr&>&& //
115 noexcept(*std::declval<OutputItr&>()++ = transform_op(*std::declval<StartItr&>()++))
116 ) -> OutputItr {
117 while (start != end) {
118 // parasoft-begin-suppress AUTOSAR-M5_2_10-a "idiomatic iterator operations permitted by M5-2-10 Permit #1"
119 // parasoft-begin-suppress AUTOSAR-M5_0_15-a "These are iterator types, so incrementing is ok"
120 *out++ = transform_op(*start++);
121 // parasoft-end-suppress AUTOSAR-M5_0_15-a
122 // parasoft-end-suppress AUTOSAR-M5_2_10-a
123 }
124 return out;
125 }
126
127 ///
128 /// @brief Backport of C++20's binary op constexpr @c std::transform.
129 ///
130 /// @tparam LhsStartItr type of the iterator for the left hand side sequence to transform. Must model
131 /// @c InputIterator.
132 /// @tparam LhsEndItr type of the iterator to compare to for the left hand side sequence to transform. Must satisfy
133 /// @c is_equality_comparable<StartItr,EndItr>.
134 /// @tparam RhsIter type of the iterator to the right hand side sequence to transform. Must model @c InputIterator.
135 /// @tparam OutputItr type of iterator for the output sequence. Must model @c OutputIterator.
136 /// @tparam BinaryOperation type of the function to invoke to transform elements.
137 /// @param lhs_start Iterator to the start of the left hand side sequence to transform.
138 /// @param lhs_end Iterator to the end of the left hand side sequence to transform.
139 /// @param rhs_start Iterator to the start of the right hand side sequence.
140 /// @param out Iterator to the start of the sequence to output the transformed values to.
141 /// @param transform_op Callable that will be invoked exactly once on each element in the range @c [lhs_start,lhs_end)
142 /// and the range starting at @c rhs_start of length @c distance(lhs_start,lhs_end).
143 /// @return OutputItr iterator in the output sequence pointing to the position after the last element transformed.
144 ///
145 template <
146 typename LhsStartItr,
147 typename LhsEndItr,
148 typename RhsItr,
149 typename OutputItr,
150 typename BinaryOperation,
151 constraints<
152 std::enable_if_t<is_input_iterator_v<LhsStartItr>>,
153 std::enable_if_t<is_input_iterator_v<RhsItr>>,
154 std::enable_if_t<is_output_iterator_v<OutputItr>>,
155 std::enable_if_t<is_inequality_comparable_v<LhsStartItr, LhsEndItr>>> = nullptr>
156 constexpr auto operator()(
157 LhsStartItr lhs_start,
158 LhsEndItr lhs_end,
159 RhsItr rhs_start,
160 OutputItr out,
161 BinaryOperation transform_op
162 ) const noexcept( //
163 arene::base::is_nothrow_inequality_comparable_v<LhsStartItr&, LhsEndItr&>&& //
164 noexcept(
165 *std::declval<OutputItr&>()++ = transform_op(*std::declval<LhsStartItr&>()++, *std::declval<RhsItr&>()++)
166 )
167 ) -> OutputItr {
168 while (lhs_start != lhs_end) {
169 // parasoft-begin-suppress AUTOSAR-M5_2_10-a "idiomatic iterator operations permitted by M5-2-10 Permit #1"
170 // parasoft-begin-suppress AUTOSAR-M5_0_15-a "These are iterator types, so incrementing is ok"
171 *out++ = transform_op(*lhs_start++, *rhs_start++);
172 // parasoft-end-suppress AUTOSAR-M5_0_15-a
173 // parasoft-end-suppress AUTOSAR-M5_2_10-a
174 }
175 return out;
176 }
177
178 /// @brief Transform each element of a std::pair with the specified function.
179 /// @tparam F The transformation function type.
180 /// @param func The transformation function.
181 /// @param pair The pair.
182 /// @return A pair with elements defined by f(pair.first, pair.second).
183 template <
184 typename F,
185 typename PairType,
186 constraints<std::enable_if_t<is_instantiation_of_v<remove_cvref_t<PairType>, std::pair>>> = nullptr>
187 constexpr auto operator()(F&& func, PairType&& pair) const {
188 return std::make_pair(func(forward_like<PairType>(pair.first)), func(forward_like<PairType>(pair.second)));
189 }
190
191 /// @brief Transform each element of a @c std::tuple
192 /// @tparam F The transformation function type.
193 /// @tparam TupleType The tuple-like object type.
194 /// @param func The transformation function.
195 /// @param tuple The tuple-like object.
196 /// @return A @c std::tuple with elements defined by f(std::get<I>(tuple)) for each I.
197 template <
198 class F,
199 class TupleType,
200 constraints<std::enable_if_t<is_instantiation_of_v<remove_cvref_t<TupleType>, std::tuple>>> = nullptr>
201 constexpr auto operator()(F&& func, TupleType&& tuple) const { // CODEQLFP(DCL51-CPP)
202 return transform_tuple_impl(
203 std::forward<F>(func),
204 std::forward<TupleType>(tuple),
205 std::make_index_sequence<std::tuple_size<remove_cvref_t<TupleType>>::value>{}
206 );
207 }
208
209 /// @brief Transform each element of a std::array with the specified function.
210 /// @tparam F The transformation function type.
211 /// @tparam T The array element type.
212 /// @tparam N The array size.
213 /// @param func The transformation function.
214 /// @param array The array.
215 /// @return An array with elements defined by f(std::get<I>(array)) for each I.
216 template <
217 class F,
218 template <typename T, std::size_t N>
219 class ArrayLikeType,
220 typename T,
221 std::size_t N,
222 constraints<std::enable_if_t<N != 0>, std::enable_if_t<std::tuple_size<ArrayLikeType<T, N>>::value == N>> =
223 nullptr>
224 constexpr auto operator()(F&& func, ArrayLikeType<T, N> const& array) const {
225 return transform_array_impl<ArrayLikeType>(std::forward<F>(func), array, std::make_index_sequence<N>{});
226 }
227 /// @brief Transform each element of a std::array with the specified function.
228 /// @tparam F The transformation function type.
229 /// @tparam T The array element type.
230 /// @tparam N The array size.
231 /// @param func The transformation function.
232 /// @param array The array.
233 /// @return An array with elements defined by f(std::get<I>(array)) for each I.
234 template <
235 class F,
236 template <typename T, std::size_t N>
237 class ArrayLikeType,
238 typename T,
239 std::size_t N,
240 constraints<std::enable_if_t<N != 0>, std::enable_if_t<std::tuple_size<ArrayLikeType<T, N>>::value == N>> =
241 nullptr>
242 constexpr auto operator()(F&& func, ArrayLikeType<T, N>&& array) const {
243 return transform_array_impl<ArrayLikeType>(std::forward<F>(func), std::move(array), std::make_index_sequence<N>{});
244 }
245 /// @brief Transform each element of a std::array with the specified function.
246 /// @tparam F The transformation function type.
247 /// @tparam T The array element type.
248 /// @param func The transformation function.
249 /// @param array The array.
250 /// @return An array with elements defined by f(std::get<I>(array)) for each I.
251 template <
252 class F,
253 template <typename T, std::size_t N>
254 class ArrayLikeType,
255 typename T,
256 constraints<std::enable_if_t<std::tuple_size<ArrayLikeType<T, 0U>>::value == 0>> = nullptr>
257 constexpr auto operator()(F&& func, ArrayLikeType<T, 0U> const& array) const {
258 return transform_array_impl<ArrayLikeType>(std::forward<F>(func), array);
259 }
260};
261
262} // namespace transform_detail
263
264/// @def arene::base::transform
265/// @copydoc arene::base::transform_detail::transform_fn::operator()
266// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
267// object used in multiple TUs."
268// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
269// object used in multiple TUs."
270ARENE_CPP14_INLINE_VARIABLE(transform_detail::transform_fn, transform);
271// parasoft-end-suppress AUTOSAR-M7_3_3-a
272// parasoft-end-suppress CERT_CPP-DCL59-a
273
274} // namespace base
275} // namespace arene
276
277// parasoft-end-suppress AUTOSAR-A2_8_1-a-2
278#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_TRANSFORM_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(transform_detail::transform_fn, transform)
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10