1414
1515#include < beman/optional/detail/iterator.hpp>
1616#include < beman/optional/test_types.hpp>
17+ #include < beman/optional/test_utilities.hpp>
1718
1819#include < algorithm>
19- #include < concepts>
2020#include < cstdlib>
2121#if defined(__cpp_lib_format_ranges)
2222#include < format>
2323#endif
24- #include < functional>
2524#include < ranges>
2625#include < tuple>
27- #include < optional>
2826#include < type_traits>
2927#include < unordered_set>
3028#include < vector>
3129
32- #define CONSTEXPR_EXPECT_EQ (val1, val2 ) \
33- if (::std::is_constant_evaluated()) { \
34- if (!((val1) == (val2))) { \
35- ::std::abort (); \
36- } \
37- } else \
38- EXPECT_EQ (val1, val2)
3930
4031#define CONSTEXPR_EXPECT_TRUE (val ) \
4132 if (::std::is_constant_evaluated()) { \
4536 } else \
4637 EXPECT_TRUE (val)
4738
48- #define CONSTEXPR_ASSERT_TRUE (val ) \
49- if (::std::is_constant_evaluated()) { \
50- if (!(val)) { \
51- ::std::abort (); \
52- } \
53- } else \
54- ASSERT_TRUE (val)
39+ template <typename U, typename V>
40+ auto gtest_expect_eq(U&& val1, V&& val2) {
41+ EXPECT_EQ (std::forward<U>(val1), std::forward<V>(val2));
42+ }
5543
56- #define CONSTEXPR_ASSERT_FALSE (val ) \
57- if (::std::is_constant_evaluated()) { \
58- if (val) { \
59- ::std::abort (); \
60- } \
61- } else \
62- ASSERT_FALSE (val)
44+ template <typename U, typename V>
45+ constexpr auto constexpr_expect_eq (U&& val1, V&& val2) {
46+ if (::std::is_constant_evaluated ()) {
47+ if (!(val1 == val2))
48+ std::abort ();
49+ } else {
50+ gtest_expect_eq (std::forward<U>(val1), std::forward<V>(val2));
51+ }
52+ }
6353
6454using namespace beman ::optional::tests;
6555
@@ -123,6 +113,7 @@ TEST(RangeSupportTest, IteratorConcepts) {
123113 test (beman::optional::optional<derived>{});
124114}
125115
116+
126117TEST (RangeSupportTest, BeginOnEmptyOptional) {
127118 auto lambda = [&] {
128119 const auto test = [](auto && opt) {
@@ -132,10 +123,10 @@ TEST(RangeSupportTest, BeginOnEmptyOptional) {
132123 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
133124 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
134125
135- CONSTEXPR_EXPECT_EQ (opt. begin (), iterator ());
126+ constexpr_expect_eq ( iterator (), opt. begin ());
136127
137128 const auto & const_opt = opt;
138- CONSTEXPR_EXPECT_EQ (const_opt. begin (), const_iterator ());
129+ constexpr_expect_eq ( const_iterator (), const_opt. begin ());
139130 };
140131
141132 test (beman::optional::optional<int >{});
@@ -144,9 +135,11 @@ TEST(RangeSupportTest, BeginOnEmptyOptional) {
144135 test (beman::optional::optional<no_default_ctor>{});
145136 test (beman::optional::optional<base>{});
146137 test (beman::optional::optional<derived>{});
138+ return true ;
147139 };
148- static_assert ((lambda (), true ));
149- lambda ();
140+ using beman::optional::tests::constify;
141+ EXPECT_TRUE (constify (lambda ()));
142+ EXPECT_TRUE (lambda ());
150143}
151144
152145TEST (RangeSupportTest, BeginOnNonEmptyOptional) {
@@ -158,10 +151,10 @@ TEST(RangeSupportTest, BeginOnNonEmptyOptional) {
158151 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
159152 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
160153
161- CONSTEXPR_EXPECT_EQ (opt.begin (), iterator (&*opt));
154+ constexpr_expect_eq (opt.begin (), iterator (&*opt));
162155
163156 const auto & const_opt = opt;
164- CONSTEXPR_EXPECT_EQ (const_opt.begin (), const_iterator (&*opt));
157+ constexpr_expect_eq (const_opt.begin (), const_iterator (&*opt));
165158 };
166159
167160 test (beman::optional::optional<int >{26 });
@@ -172,9 +165,10 @@ TEST(RangeSupportTest, BeginOnNonEmptyOptional) {
172165 test (beman::optional::optional<no_default_ctor>{no_default_ctor{empty{}}});
173166 test (beman::optional::optional<base>{base{}});
174167 test (beman::optional::optional<derived>{derived{}});
168+ return true ;
175169 };
176- static_assert ( (lambda (), true ));
177- lambda ();
170+ EXPECT_TRUE ( constify (lambda ()));
171+ EXPECT_TRUE ( lambda () );
178172}
179173
180174TEST (RangeSupportTest, EndOnEmptyOptional) {
@@ -186,10 +180,10 @@ TEST(RangeSupportTest, EndOnEmptyOptional) {
186180 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
187181 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
188182
189- CONSTEXPR_EXPECT_EQ (opt.end (), iterator ());
183+ constexpr_expect_eq (opt.end (), iterator ());
190184
191185 const auto & const_opt = opt;
192- CONSTEXPR_EXPECT_EQ (const_opt.end (), const_iterator ());
186+ constexpr_expect_eq (const_opt.end (), const_iterator ());
193187 };
194188
195189 test (beman::optional::optional<int >{});
@@ -198,9 +192,10 @@ TEST(RangeSupportTest, EndOnEmptyOptional) {
198192 test (beman::optional::optional<no_default_ctor>{});
199193 test (beman::optional::optional<base>{});
200194 test (beman::optional::optional<derived>{});
195+ return true ;
201196 };
202- static_assert ( (lambda (), true ));
203- lambda ();
197+ EXPECT_TRUE ( constify (lambda ()));
198+ EXPECT_TRUE ( lambda () );
204199}
205200
206201TEST (RangeSupportTest, EndOnNonEmptyOptional) {
@@ -212,10 +207,10 @@ TEST(RangeSupportTest, EndOnNonEmptyOptional) {
212207 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
213208 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
214209
215- CONSTEXPR_EXPECT_EQ (opt.end (), iterator (&*opt + 1 ));
210+ constexpr_expect_eq (opt.end (), iterator (&*opt + 1 ));
216211
217212 const auto & const_opt = opt;
218- CONSTEXPR_EXPECT_EQ (const_opt.end (), const_iterator (&*opt + 1 ));
213+ constexpr_expect_eq (const_opt.end (), const_iterator (&*opt + 1 ));
219214 };
220215
221216 test (beman::optional::optional<int >{26 });
@@ -226,12 +221,14 @@ TEST(RangeSupportTest, EndOnNonEmptyOptional) {
226221 test (beman::optional::optional<no_default_ctor>{no_default_ctor{empty{}}});
227222 test (beman::optional::optional<base>{base{}});
228223 test (beman::optional::optional<derived>{derived{}});
224+ return true ;
229225 };
230- static_assert ( (lambda (), true ));
231- lambda ();
226+ EXPECT_TRUE ( constify (lambda ()));
227+ EXPECT_TRUE ( lambda () );
232228}
233229
234- #if ((__GNUC__ >= 15) && (__GNUC_MINOR__ >= 1) && (__GNUC_PATCHLEVEL__ >= 1)) || ((__GNUC__ >= 16))
230+ #if (__cplusplus >= 202302L) && \
231+ (((__GNUC__ >= 15 ) && (__GNUC_MINOR__ >= 1 ) && (__GNUC_PATCHLEVEL__ >= 1 )) || ((__GNUC__ >= 16 )))
235232static_assert (std::format_kind<beman::optional::optional<int >> == std::range_format::disabled);
236233#endif
237234
@@ -258,70 +255,89 @@ TEST(RangeSupportTest, FormatOptionalIsStillDisabled) {
258255#endif
259256}
260257
258+ template <typename U>
259+ auto gtest_assert_true (U&& val1) {
260+ ASSERT_TRUE (std::forward<U>(val1));
261+ }
262+
263+ template <typename U>
264+ constexpr auto constexpr_assert (U&& val1) {
265+ if (::std::is_constant_evaluated ()) {
266+ if (!(val1))
267+ std::abort ();
268+ } else {
269+ gtest_assert_true (std::forward<U>(val1));
270+ }
271+ }
272+
261273TEST (RangeSupportTest, LoopOverEmptyRange) {
262- auto lambda = [&] {
274+ auto lambda = [&]() -> bool {
263275 beman::optional::optional<int > empty;
264- CONSTEXPR_ASSERT_FALSE ( empty.has_value ());
276+ constexpr_assert (! empty.has_value ());
265277
266278 for ([[maybe_unused]] auto _ : empty) {
267- CONSTEXPR_ASSERT_TRUE (false ) << " Should not be reached: expected not to loop over empty optional" ;
279+ constexpr_assert (false ); // << "Should not be reached: expected not to loop over empty optional";
268280 }
281+ return true ;
269282 };
270- static_assert ( (lambda (), true ));
271- lambda ();
283+ EXPECT_TRUE ( constify (lambda ()));
284+ EXPECT_TRUE ( lambda () );
272285}
273286
274287TEST (RangeSupportTest, LoopOverNonEmptyRange) {
275288 auto lambda = [&] {
276289 const int expected_value = 0xCAFEBABE ;
277290 beman::optional::optional<int > empty{expected_value};
278- CONSTEXPR_ASSERT_TRUE (empty.has_value ());
291+ constexpr_assert (empty.has_value ());
279292
280293 bool entered_loop = false ;
281294 for (auto i : empty) {
282- CONSTEXPR_EXPECT_EQ (i, expected_value);
295+ constexpr_expect_eq (i, expected_value);
283296 entered_loop = true ;
284297 }
285- CONSTEXPR_EXPECT_TRUE (entered_loop);
298+ constexpr_expect_eq (entered_loop, true );
299+ return true ;
286300 };
287- static_assert ( (lambda (), true ));
288- lambda ();
301+ EXPECT_TRUE ( constify (lambda ()));
302+ EXPECT_TRUE ( lambda () );
289303}
290304
291305TEST (RangeSupportTest, LoopOptionalAccess) {
292306 auto lambda = [&] {
293307 // Example from P3168R2: should access the value from an optional object.
294308 const int expected_value = 0xCAFEBABE ;
295309 const auto get_optional = [&]() -> beman::optional::optional<int > { return expected_value; };
296- CONSTEXPR_ASSERT_TRUE (get_optional ().has_value ());
310+ constexpr_assert (get_optional ().has_value ());
297311
298312 for (auto && opt : get_optional ()) {
299- CONSTEXPR_EXPECT_EQ (opt, expected_value); // usage of opt here is safe
313+ constexpr_expect_eq (opt, expected_value); // usage of opt here is safe
300314 }
315+ return true ;
301316 };
302- static_assert ( (lambda (), true ));
303- lambda ();
317+ EXPECT_TRUE ( constify (lambda ()));
318+ EXPECT_TRUE ( lambda () );
304319}
305320
306321TEST (RangeSupportTest, LoopOptionalAssignment) {
307- auto lambda = [& ] {
322+ constexpr auto lambda = [] {
308323 // Example from P3168R2: should mutate the value from an optional object.
309- const int initial_expected_value = 0xCAFEBABE ;
310- const int expected_value = 0xDEADBEEF ;
311- const auto get_optional = [& ]() -> beman::optional::optional<int > { return initial_expected_value; };
312- CONSTEXPR_ASSERT_TRUE (get_optional ().has_value ());
313- CONSTEXPR_ASSERT_TRUE (get_optional ().value () == initial_expected_value);
324+ constexpr int initial_expected_value = 0xCAFEBABE ;
325+ constexpr int expected_value = 0xDEADBEEF ;
326+ constexpr auto get_optional = [= ]() -> beman::optional::optional<int > { return initial_expected_value; };
327+ constexpr_assert (get_optional ().has_value ());
328+ constexpr_assert (get_optional ().value () == initial_expected_value);
314329
315330 auto opt_int = get_optional ();
316331 for (auto && opt : opt_int) {
317- CONSTEXPR_EXPECT_EQ (opt, initial_expected_value);
332+ constexpr_expect_eq (opt, initial_expected_value);
318333 opt = expected_value; // usage of opt here is safe
319334 }
320- CONSTEXPR_ASSERT_TRUE (opt_int.has_value ());
321- CONSTEXPR_EXPECT_EQ (opt_int.value (), expected_value);
335+ constexpr_assert (opt_int.has_value ());
336+ constexpr_expect_eq (opt_int.value (), expected_value);
337+ return true ;
322338 };
323- static_assert ( (lambda (), true ));
324- lambda ();
339+ EXPECT_TRUE ( constify (lambda ()));
340+ EXPECT_TRUE ( lambda () );
325341}
326342
327343TEST (RangeSupportTest, RangeChainExample) {
@@ -407,13 +423,14 @@ TEST(RangeSupportTest, PythagoreanTriples) {
407423 };
408424 constexpr const std::tuple k100th_triple = {
409425 26 , 168 , 170 }; // The 100th Pythagorean triple with x, y, z <= 200.
410- ASSERT_EQ (bruteforce_generate_nth (100 , 200 ), k100th_triple);
426+ EXPECT_EQ (bruteforce_generate_nth (100 , 200 ), k100th_triple);
411427
412428 // Generate the 100th Pythagorean triple with ranges.
413429 auto && r = triples | std::views::drop (99 ) | std::views::take (1 );
414430 EXPECT_TRUE (std::ranges::equal (r, std::vector{k100th_triple}));
415431 }
432+ return true ;
416433 };
417- static_assert ( (lambda (), true ));
418- lambda ();
434+ EXPECT_TRUE ( constify (lambda ()));
435+ EXPECT_TRUE ( lambda () );
419436}
0 commit comments