Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
customization.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_INLINE_CONTAINER_TESTING_CUSTOMIZATION_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_INLINE_CONTAINER_TESTING_CUSTOMIZATION_HPP_
7
8#include "arene/base/array/array.hpp"
9#include "arene/base/constraints/constraints.hpp"
10#include "arene/base/contracts/contract.hpp"
11#include "arene/base/inline_container/detail/iterator_interface.hpp"
12#include "arene/base/stdlib_choice/cstddef.hpp"
13#include "arene/base/stdlib_choice/enable_if.hpp"
14#include "arene/base/stdlib_choice/initializer_list.hpp"
15#include "arene/base/stdlib_choice/integer_sequence.hpp"
16#include "arene/base/stdlib_choice/integral_constant.hpp" // IWYU pragma: keep
17#include "arene/base/stdlib_choice/is_array.hpp"
18#include "arene/base/stdlib_choice/is_constructible.hpp"
19#include "arene/base/stdlib_choice/is_copy_constructible.hpp"
20#include "arene/base/stdlib_choice/is_floating_point.hpp"
21#include "arene/base/stdlib_choice/is_integral.hpp"
22#include "arene/base/stdlib_choice/is_move_assignable.hpp"
23#include "arene/base/stdlib_choice/is_move_constructible.hpp"
24#include "arene/base/stdlib_choice/is_signed.hpp"
25#include "arene/base/stdlib_choice/is_unsigned.hpp"
26#include "arene/base/stdlib_choice/iterator_tags.hpp"
27#include "arene/base/stdlib_choice/make_signed.hpp"
28#include "arene/base/stdlib_choice/move.hpp"
29#include "arene/base/stdlib_choice/remove_cv.hpp"
30#include "arene/base/stdlib_choice/remove_reference.hpp"
31#include "arene/base/type_traits/remove_cvref.hpp"
32#include "testlibs/utilities/configurable_value.hpp"
33
34namespace arene {
35namespace base {
36namespace testing {
37
38//////////////////////////////////////////////////////////////////////
39// Customization points for generating values of user-defined types //
40//////////////////////////////////////////////////////////////////////
41
42namespace customization_detail {
43/// @brief A version of arene::base::to_array where the individual elements are cast to the specified type
44/// @tparam OutType The element type of the output array, specified by the caller
45/// @tparam InType The element type of the input C-array, deduced from the first argument
46/// @tparam Indices A pack of indices the same size as the input and output arrays, deduced from the second argument
47/// @param arr A C-Array containing the values as instances of some type @c InType
48/// @return An <c>arene::base::array<OutType, sizeof...(Indices)></c> where the elements are constructed from @c arr
49template <typename OutType, typename InType, std::size_t... Indices>
50constexpr auto to_array_cast(
51 // NOLINTNEXTLINE(hicpp-avoid-c-arrays)
52 InType (&&arr)[sizeof...(Indices)],
53 std::index_sequence<Indices...>
54) noexcept(std::is_nothrow_constructible<OutType, InType&&>::value) -> array<base::remove_cvref_t<OutType>, sizeof...(Indices)> {
55 return {{std::move(arr[Indices])...}};
56}
57} // namespace customization_detail
58
59/// @brief A version of arene::base::to_array where the individual elements are cast to the specified type
60/// @tparam OutType The element type of the output array, specified by the caller
61/// @tparam InType The element type of the input C-array, deduced from the argument
62/// @tparam Size The size of the input and output arrays, deduced from the argument
63/// @param arr A C-Array containing the values as instances of some type @c InType
64/// @return An <c>arene::base::array<OutType, Size></c> where the elements are constructed from the elements of @c arr
65template <
66 typename OutType,
67 typename InType,
72// NOLINTNEXTLINE(hicpp-avoid-c-arrays)
77
78/// @brief An array used in the default implementation of @c ::test_value ; by default it's empty and unusable
79/// @note This must be explicitly specialized to be usable; specializations can use different array sizes
80/// @tparam T The type of which this is an array of test values
81template <typename T, typename = ::arene::base::constraints<>>
82extern constexpr ::arene::base::array<T, 0UL> test_value_array{};
83
84/// @brief A partial specialization of @c test_value_array for built-in unsigned integers to make it easier to use
85/// @tparam T The type of which this is an array of test values
86template <typename T>
87extern constexpr auto test_value_array<
88 T,
89 ::arene::base::
91 to_array_cast<T>({0U, 8U, 19U, 6612U, 777124U, 7U, 609124U, 1224545862U, 2561U, 976173U});
92
93/// @brief A partial specialization of @c test_value_array for built-in signed integers to make it easier to use
94/// @tparam T The type of which this is an array of test values
95template <typename T>
96extern constexpr auto test_value_array<
97 T,
98 ::arene::base::
100 to_array_cast<T>({1, -2, 6, -24, 120, -720, 5'040, -40'320, 362'880, -3'628'800});
101
102/// @brief A partial specialization of @c test_value_array for built-in floating point numbers to make it easier to use
103/// @tparam T The type of which this is an array of test values
104template <typename T>
105extern constexpr auto
107 to_array_cast<T>({0.0, -1.0, 3.14, 2.72, 1.41, 0.577});
108
109namespace customization_detail {
110/// @brief A class to hold the default generation function so that it can be partially specialized for our test classes
111/// @tparam T The type to generate a test value of
112template <typename T>
113struct test_value_generator {
114 /// @brief The default implementation of <tt>test_value</tt>, returning a value copied from @c test_value_array
115 /// @param idx The index of the test value to be generated
116 static constexpr auto test_value(std::size_t idx) noexcept(std::is_nothrow_copy_constructible<T>::value) -> T {
117 static_assert(
118 !test_value_array<T>.empty(),
119 "To use a type T for parameterized testing, you must specialize arene::base::testing::test_value_array<T> for "
120 "copyable types or arene::base::testing::test_value<T> for non-copyable types"
121 );
122 return test_value_array<T>[idx % test_value_array<T>.size()];
123 }
124};
125
126/// @brief A partial specialization of @c test_value for @c configurable_value
127/// @tparam T The underlying value type held by the @c configurable_value
128/// @tparam ThrowsOn A specification of which operations should throw
129/// @tparam Disable A specification of which operations to disable entirely
130/// @tparam IsConstexpr A specification of whether or not the @c configurable_value should be usable in @c constexpr
131template <typename T, ::testing::throws_on ThrowsOn, ::testing::disable Disable, ::testing::is_constexpr IsConstexpr>
132struct test_value_generator<::testing::configurable_value<T, ThrowsOn, Disable, IsConstexpr>> {
133 /// @brief An implementation of @c test_value for @c configurable_value which generates based on the value type
134 /// @param idx The index of the test value to be generated
135 static constexpr auto test_value(std::size_t idx
136 ) noexcept((ThrowsOn & ::testing::throws_on::value_construct) == ::testing::throws_on::nothing) -> T {
137 return {test_value_generator<T>::test_value(idx)};
138 }
139};
140} // namespace customization_detail
141
142/// @brief Get the @c idx 'th test value of type @c T
143/// @note The default implementation copies the @c idx 'th element of @c test_value_array , wrapping to stay in bounds
144/// @note For non-copyable types, this function can be specialized to construct the test value without copying
145/// @tparam T The type to return test values of
146/// @param idx The index of the test value to be generated
147/// @return A test value of type @c T ; test values with different @c idx may be different from each other, but may not
148template <typename T>
149constexpr auto test_value(std::size_t idx
150) noexcept(noexcept(customization_detail::test_value_generator<T>::test_value(idx))) -> T {
151 return customization_detail::test_value_generator<T>::test_value(idx);
152}
153
154/// @brief Check whether or not a given type's @c test_value function works in @c constexpr contexts
155/// @tparam T The type to check
156template <typename T, typename = std::integral_constant<bool, true>>
157constexpr bool has_constexpr_test_value = false;
158
159/// @brief Check whether or not a given type's @c test_value function works in @c constexpr contexts
160/// @tparam T The type to check
161// This uses the comma operator to instantiate a test_value<T> and then discard it; if it compiles the trait is true.
162template <typename T>
163constexpr bool has_constexpr_test_value<T, std::integral_constant<bool, (test_value<T>(0), true)>> = true;
164
165namespace customization_detail {
166
167/// @brief A function object to provide a @c std::initializer_list implemented differently for @c constexpr and runtime
168/// @tparam T The type for which an initializer list is requested
169/// @tparam IsConstexpr Whether or not the provided initializer list should be declared @c constexpr
170/// @tparam Indices A pack of indices, one for each test value in the initializer list
171template <typename T, bool IsConstexpr, std::size_t... Indices>
172class init_list_holder {
173 /// @brief @c constexpr functions can not have static variables until C++23 so this has to be outside the function
174 static constexpr std::initializer_list<T> list{test_value<T>(Indices)...};
175
176 public:
177 /// @brief Call the function object, returning a reference to the statically-allocated @c std::initializer_list
178 /// @return A copy of a statically-allocated @c std::initializer_list<T> containing one test value per index
179 constexpr auto operator()() const noexcept -> std::initializer_list<T> { return list; }
180};
181
182// This static variable definition is required until C++17.
183template <typename T, bool IsConstexpr, std::size_t... Indices>
184constexpr std::initializer_list<T> init_list_holder<T, IsConstexpr, Indices...>::list;
185
186/// @brief A function object to provide a @c std::initializer_list implemented differently for @c constexpr and runtime
187/// @tparam T The type for which an initializer list is requested
188/// @tparam IsConstexpr Whether or not the provided initializer list should be declared @c constexpr
189/// @tparam Indices A pack of indices, one for each test value in the initializer list
190template <typename T, std::size_t... Indices>
191class init_list_holder<T, false, Indices...> {
192 public:
193 /// @brief Call the function object, returning a reference to the statically-allocated @c std::initializer_list
194 /// @return A copy of a statically-allocated @c std::initializer_list<T> containing one test value per index
195 auto operator()() const noexcept -> std::initializer_list<T> {
196 // For non-constexpr T, this needs to be *inside* the function to ensure it's initialized after test_value_array
197 static std::initializer_list<T> const list{test_value<T>(Indices)...};
198 return list;
199 }
200};
201
202} // namespace customization_detail
203
204/// @brief A function object returning a @c std::initializer_list of one @c test_value per index in the given pack
205/// @tparam T The type for which an initializer list is requested
206/// @tparam Indices A pack of indices, one for each test value in the initializer list
207/// @return A copy of a statically-allocated @c std::initializer_list<T> containing one test value per index
208template <typename T, std::size_t... Indices>
211
212/// @brief An iterator whose i'th position yields an rvalue reference to @c test_value(i) of the given type
213/// @tparam T The type to yield
214template <typename T>
216 /// @brief A type trait indicating whether or not retrieving a @c test_value<T> can throw an exception
217 static constexpr bool test_value_is_noexcept = noexcept(test_value<T>(0));
218
219 /// @brief Alias for the iterator mixin, used to initialize it in various constructors
221
222 public:
223 /// @brief The value type of the iterator; this is the type whose test values are being retrieved
224 using value_type = T;
225 /// @brief The pointer type of the iterator; basically not meaningful, and it would be ill-formed to use it
226 using pointer = T*;
227 /// @brief The reference type of the iterator; a value of the expected type, since there's nothing to rvalue-refer to
228 using reference = T&&;
229 /// @brief The difference type of the iterator; test_value takes @c std::size_t so the difference is that but signed
231 /// @brief The iterator category; random access because we just store an index and yield from it
233
234 /// @brief Construct an rvalue_iterator containing the test value with the given index (defaulting to 0)
235 /// @param index Index to retrieve the test value with
236 /// @pre <c>index >= 0</c>, otherwise ARENE_PRECONDITION violation
237 explicit constexpr rvalue_iterator(difference_type index = 0) noexcept(test_value_is_noexcept)
241
242 /// @brief Copy construct an rvalue_iterator, retrieving a new test value so that the value type can be move-only
243 /// @param other Iterator to copy from
248
249 /// @brief Move construct an rvalue_iterator
250 /// @param other Iterator to move from
251 // NOLINTNEXTLINE(hicpp-noexcept-move) noexcept-specification accurately reflects that of the underlying type
256
257 /// @brief Copy assign an rvalue_iterator, retrieving a new test value so that the value type can be move-only
258 /// @param other Iterator to copy from
259 constexpr auto operator=(rvalue_iterator const& other) noexcept(test_value_is_noexcept) -> rvalue_iterator& {
260 current_index_ = other.current_index_;
261 current_value_ = get_test_value(current_index_);
262 }
263
264 /// @brief Move assign an rvalue_iterator
265 /// @param other Iterator to move from
266 // NOLINTNEXTLINE(hicpp-noexcept-move) noexcept-specification accurately reflects that of the underlying type
267 constexpr auto operator=(rvalue_iterator&& other) noexcept(std::is_nothrow_move_assignable<T>::value)
268 -> rvalue_iterator& {
269 current_index_ = other.current_index_;
270 current_value_ = std::move(other.current_value_);
271 }
272
273 /// @brief Destroy an rvalue_iterator
274 ~rvalue_iterator() = default;
275
276 /// @brief Dereference an rvalue_iterator; data may no longer be meaningful after the first use
277 /// @return An rvalue reference to the current test value
278 constexpr auto operator*() noexcept -> reference { return std::move(current_value_); }
279
280 /// @brief Shift an rvalue_iterator by the given amount
281 /// @param diff Amount by which to shift the iterator
282 /// @return A reference to @c *this
283 /// @pre <c>current_index_ + diff >= 0</c>, otherwise ARENE_PRECONDITION violation
284 constexpr auto operator+=(difference_type diff) noexcept(test_value_is_noexcept) -> rvalue_iterator& {
285 current_index_ += diff;
286 current_value_ = get_test_value(current_index_);
287 return *this;
288 }
289
290 /// @brief Get the difference between two rvalue_iterators
291 /// @param left Left side of the difference
292 /// @param right Right side of the difference
293 /// @return The difference between the operands' respective current indices
294 friend constexpr auto operator-(rvalue_iterator const& left, rvalue_iterator const& right) noexcept
295 -> difference_type {
296 return left.current_index_ - right.current_index_;
297 }
298
299 private:
300 /// @brief Current index whose @c test_value is yielded upon dereferencing
301 difference_type current_index_;
302 /// @brief Current value which will be yielded upon dereferencing; needs to be saved so we can get an rvalue ref to it
303 T current_value_;
304
305 /// @brief Get the @c test_value<T> with the given index, checking to make sure the index hasn't become negative
306 /// @param Index to retrieve the test value with
307 /// @return @c test_value<T>(index)
308 /// @pre <c>index >= 0</c>, otherwise ARENE_PRECONDITION violation
309 static constexpr auto get_test_value(difference_type index) noexcept(test_value_is_noexcept) -> T {
310 ARENE_PRECONDITION(index >= 0);
311 return test_value<T>(static_cast<std::size_t>(index));
312 }
313};
314
315} // namespace testing
316} // namespace base
317} // namespace arene
318
319#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_INLINE_CONTAINER_TESTING_CUSTOMIZATION_HPP_
An iterator whose i'th position yields an rvalue reference to test_value(i) of the given type.
Definition customization.hpp:215
constexpr auto operator+=(difference_type diff) noexcept(test_value_is_noexcept) -> rvalue_iterator &
Shift an rvalue_iterator by the given amount.
Definition customization.hpp:284
constexpr auto operator=(rvalue_iterator const &other) noexcept(test_value_is_noexcept) -> rvalue_iterator &
Copy assign an rvalue_iterator, retrieving a new test value so that the value type can be move-only.
Definition customization.hpp:259
friend constexpr auto operator-(rvalue_iterator const &left, rvalue_iterator const &right) noexcept -> difference_type
Get the difference between two rvalue_iterators.
Definition customization.hpp:294
~rvalue_iterator()=default
Destroy an rvalue_iterator.
constexpr auto operator*() noexcept -> reference
Dereference an rvalue_iterator; data may no longer be meaningful after the first use.
Definition customization.hpp:278
constexpr rvalue_iterator(rvalue_iterator &&other) noexcept(std::is_nothrow_move_constructible< T >::value)
Move construct an rvalue_iterator.
Definition customization.hpp:252
constexpr rvalue_iterator(rvalue_iterator const &other) noexcept(test_value_is_noexcept)
Copy construct an rvalue_iterator, retrieving a new test value so that the value type can be move-onl...
Definition customization.hpp:244
constexpr auto operator=(rvalue_iterator &&other) noexcept(std::is_nothrow_move_assignable< T >::value) -> rvalue_iterator &
Move assign an rvalue_iterator.
Definition customization.hpp:267
constexpr rvalue_iterator(difference_type index=0) noexcept(test_value_is_noexcept)
Construct an rvalue_iterator containing the test value with the given index (defaulting to 0)
Definition customization.hpp:237
Definition customization.hpp:36
constexpr bool has_constexpr_test_value
Check whether or not a given type's test_value function works in constexpr contexts.
Definition customization.hpp:157
constexpr customization_detail::init_list_holder< T, has_constexpr_test_value< T >, Indices... > test_initializer_list
A function object returning a std::initializer_list of one test_value per index in the given pack.
constexpr auto test_value(std::size_t idx) noexcept(noexcept(customization_detail::test_value_generator< T >::test_value(idx))) -> T
Get the idx 'th test value of type T.
Definition customization.hpp:149
constexpr ::arene::base::array< T, 0UL > test_value_array
An array used in the default implementation of test_value ; by default it's empty and unusable.
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10