Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
unique_test_value.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_UNIQUE_TEST_VALUE_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_INLINE_CONTAINER_TESTING_UNIQUE_TEST_VALUE_HPP_
7
8#include "arene/base/compiler_support/diagnostics.hpp"
9#include "arene/base/compiler_support/platform_queries.hpp"
10#include "arene/base/compiler_support/preprocessor.hpp"
11#include "arene/base/inline_container/testing/customization.hpp"
12#include "arene/base/stdlib_choice/cstddef.hpp"
13#include "arene/base/stdlib_choice/enable_if.hpp"
14#include "arene/base/stdlib_choice/ignore.hpp"
15#include "arene/base/stdlib_choice/terminate.hpp"
16#include "arene/base/type_info/type_name_string.hpp" // IWYU pragma: keep
17#include "arene/base/type_traits/comparison_traits.hpp"
18#include "arene/base/type_traits/conditional.hpp"
19
20#if ARENE_IS_OFF(ARENE_STDLIB_LIBARENECXX)
21#include <iostream>
22#endif
23
25ARENE_IGNORE_ALL("-Wfloat-equal", "exact equality is intended for floating point as we are testing uniqueness");
26
27namespace arene {
28namespace base {
29namespace testing {
30namespace detail {
31
32/// @brief memoized check that test values are unique
33/// @tparam T the type to return the test values of
34/// @tparam N the index of the last test value to check
35///
36template <class T, std::size_t N, class = void>
37struct assert_test_values_are_unique;
38
39/// @brief specifies if unique checks are @c noexcept
40/// @tparam T the type to return the test values of
41///
42template <class T, class = void>
43constexpr extern bool is_test_value_noexcept_usable_v = false;
44
45/// @brief specifies if unique checks are @c noexcept
46/// @tparam T the type to return the test values of
47///
48/// Specialization if @c test_value<T> is defined and equality comparable.
49///
50template <class T>
51constexpr extern bool is_test_value_noexcept_usable_v< //
52 T,
53 std::enable_if_t<is_equality_comparable_v<decltype(test_value<T>(0U))>>> =
54 noexcept(test_value<T>(0U) == test_value<T>(0U));
55
56/// @brief no-op function object
57///
58struct no_op {
59 /// @brief does nothing
60 ///
61 /// Used as the base case for checking that test values are unique.
62 ///
63 constexpr auto operator()() const noexcept -> void {}
64};
65
66/// @brief checks if values are unique
67/// @return @c true if values are unique, otherwise @c false
68///
69/// Determines if <tt> test_value<T>(0), ..., test_value<T>(n) </tt> are unique. That is,
70/// * <tt> test_value<T>(i) == test_value<T>(j) </tt> is @c <tt> i == j </tt>, for <tt> i, j </tt> in <tt>[0, ...,
71/// N]</tt>
72///
73template <class T, std::size_t N>
74constexpr auto are_test_values_unique() noexcept(is_test_value_noexcept_usable_v<T>) -> bool {
75 using assert_unique_for_smaller_n = conditional_t< //
76 N == 0U,
77 no_op,
78 assert_test_values_are_unique<T, N - 1U>>;
79 assert_unique_for_smaller_n{}();
80
81 auto const self_equal = test_value<T>(N) == test_value<T>(N);
82
83 auto equal_to_any_previous = false;
84 for (auto i = std::size_t{}; i < N; ++i) {
85 if (test_value<T>(i) == test_value<T>(N)) {
86 equal_to_any_previous = true;
87 break;
88 }
89 }
90
91 return self_equal && !equal_to_any_previous;
92 ;
93}
94
95/// @brief memoized check that test values are unique
96/// @tparam T the type to return the test values of
97/// @tparam N the index of the last test value to check
98///
99/// Specialization when uniqueness cannot be determined at compile-time.
100///
101template <class T, std::size_t N, class>
102struct assert_test_values_are_unique //
103{
104 /// @brief checks if values are unique
105 /// @return @c true if values are unique
106 ///
107 /// If <tt> test_value<T>(0), ..., test_value<T>(n) </tt> are not unique,
108 /// displays a message to @c std::cerr and calls @c std::terminate.
109 ///
110 auto operator()() const noexcept(is_test_value_noexcept_usable_v<T>) -> void //
111 {
112 static auto const unique = [] {
113 if (!are_test_values_unique<T, N>()) {
114#if ARENE_IS_OFF(ARENE_STDLIB_LIBARENECXX)
115 std::cerr //
116 << "ERROR: test requested unique values but " //
117 << "'arene::base::testing::test_values<" //
118 << arene::base::type_name_v<T>.c_str() << ">(" //
119 << N //
120 << ")'" //
121 << " duplicates an earlier test value\n";
122#endif
123 std::terminate();
124 }
125
126 return nullptr;
127 }();
128
129 std::ignore = unique;
130 }
131};
132
133/// @brief memoized check that test values are unique
134/// @tparam T the type to return the test values of
135/// @tparam N the index of the last test value to check
136///
137/// Specialization when uniqueness can be determined at compile-time.
138///
139template <class T, std::size_t N>
140struct assert_test_values_are_unique<
141 T,
142 N,
143 std::enable_if_t<(std::ignore = (test_value<T>(0U) == test_value<T>(0U)), true)>> //
144{
145 /// @brief determines if values are unique
146 static constexpr bool value = are_test_values_unique<T, N>();
147
148 /// @brief checks if values are unique
149 /// @return @c true if values are unique
150 ///
151 /// If <tt> test_value<T>(0), ..., test_value<T>(n) </tt> are not unique,
152 /// triggers a @c static_assert
153 ///
154 constexpr auto operator()() const noexcept -> void //
155 {
156 static_assert(value, "test requested N unique values but 'arene::base::testing::test_values' produces duplicates");
157 }
158};
159
160} // namespace detail
161
162/// @brief obtain the nth unique @c arene::base::testing::test_value
163/// @tparam T the type to return the test values of
164/// @tparam N the index of the test value to obtain
165/// @return @c arene::base::testing::test_value<T>(n)
166///
167/// Obtains @c test_value<T>(n) and ensures that the values
168/// <tt> test_value<T>(0), ..., test_value<T>(n) </tt> are unique.
169///
170/// If the values are not unique and this can be determined at compile-time,
171/// this function fails to compile.
172///
173/// If the values are not unique and this cannot be determined at compile-time,
174/// a call to this function calls @c std::terminate.
175///
176/// @note Requires `test_value<T>` to be regular invocable
177///
178template <class T, std::size_t N>
179constexpr auto unique_test_value() noexcept(detail::is_test_value_noexcept_usable_v<T>) -> decltype(test_value<T>(N)) {
180 static_assert(
181 is_equality_comparable_v<decltype(test_value<T>(N))>,
182 "if tests request a unique test value, the test value type must provide an equality operator"
183 );
184 detail::assert_test_values_are_unique<T, N>{}();
185 return test_value<T>(N);
186}
187
188} // namespace testing
189} // namespace base
190} // namespace arene
191
193
194#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_INLINE_CONTAINER_TESTING_UNIQUE_TEST_VALUE_HPP_
Definition customization.hpp:36
constexpr auto unique_test_value() noexcept(detail::is_test_value_noexcept_usable_v< T >) ->
obtain the nth unique arene::base::testing::test_value
Definition unique_test_value.hpp:179
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10
ARENE_IGNORE_START()
ARENE_IGNORE_END()
ARENE_IGNORE_ALL("-Wfloat-equal", "exact equality is intended for floating point as we are testing uniqueness")