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)
39-
4030#define CONSTEXPR_EXPECT_TRUE (val ) \
4131 if (::std::is_constant_evaluated()) { \
4232 if (!(val)) { \
4535 } else \
4636 EXPECT_TRUE (val)
4737
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)
38+ template <typename U, typename V>
39+ auto gtest_expect_eq(U&& val1, V&& val2) {
40+ EXPECT_EQ (std::forward<U>(val1), std::forward<V>(val2));
41+ }
5542
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)
43+ template <typename U, typename V>
44+ constexpr auto constexpr_expect_eq (U&& val1, V&& val2) {
45+ if (::std::is_constant_evaluated ()) {
46+ if (!(val1 == val2))
47+ std::abort ();
48+ } else {
49+ gtest_expect_eq (std::forward<U>(val1), std::forward<V>(val2));
50+ }
51+ }
6352
6453using namespace beman ::optional::tests;
6554
@@ -132,10 +121,10 @@ TEST(RangeSupportTest, BeginOnEmptyOptional) {
132121 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
133122 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
134123
135- CONSTEXPR_EXPECT_EQ (opt. begin (), iterator ());
124+ constexpr_expect_eq ( iterator (), opt. begin ());
136125
137126 const auto & const_opt = opt;
138- CONSTEXPR_EXPECT_EQ (const_opt. begin (), const_iterator ());
127+ constexpr_expect_eq ( const_iterator (), const_opt. begin ());
139128 };
140129
141130 test (beman::optional::optional<int >{});
@@ -144,9 +133,11 @@ TEST(RangeSupportTest, BeginOnEmptyOptional) {
144133 test (beman::optional::optional<no_default_ctor>{});
145134 test (beman::optional::optional<base>{});
146135 test (beman::optional::optional<derived>{});
136+ return true ;
147137 };
148- static_assert ((lambda (), true ));
149- lambda ();
138+ using beman::optional::tests::constify;
139+ EXPECT_TRUE (constify (lambda ()));
140+ EXPECT_TRUE (lambda ());
150141}
151142
152143TEST (RangeSupportTest, BeginOnNonEmptyOptional) {
@@ -158,10 +149,10 @@ TEST(RangeSupportTest, BeginOnNonEmptyOptional) {
158149 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
159150 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
160151
161- CONSTEXPR_EXPECT_EQ (opt.begin (), iterator (&*opt));
152+ constexpr_expect_eq (opt.begin (), iterator (&*opt));
162153
163154 const auto & const_opt = opt;
164- CONSTEXPR_EXPECT_EQ (const_opt.begin (), const_iterator (&*opt));
155+ constexpr_expect_eq (const_opt.begin (), const_iterator (&*opt));
165156 };
166157
167158 test (beman::optional::optional<int >{26 });
@@ -172,9 +163,10 @@ TEST(RangeSupportTest, BeginOnNonEmptyOptional) {
172163 test (beman::optional::optional<no_default_ctor>{no_default_ctor{empty{}}});
173164 test (beman::optional::optional<base>{base{}});
174165 test (beman::optional::optional<derived>{derived{}});
166+ return true ;
175167 };
176- static_assert ( (lambda (), true ));
177- lambda ();
168+ EXPECT_TRUE ( constify (lambda ()));
169+ EXPECT_TRUE ( lambda () );
178170}
179171
180172TEST (RangeSupportTest, EndOnEmptyOptional) {
@@ -186,10 +178,10 @@ TEST(RangeSupportTest, EndOnEmptyOptional) {
186178 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
187179 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
188180
189- CONSTEXPR_EXPECT_EQ (opt.end (), iterator ());
181+ constexpr_expect_eq (opt.end (), iterator ());
190182
191183 const auto & const_opt = opt;
192- CONSTEXPR_EXPECT_EQ (const_opt.end (), const_iterator ());
184+ constexpr_expect_eq (const_opt.end (), const_iterator ());
193185 };
194186
195187 test (beman::optional::optional<int >{});
@@ -198,9 +190,10 @@ TEST(RangeSupportTest, EndOnEmptyOptional) {
198190 test (beman::optional::optional<no_default_ctor>{});
199191 test (beman::optional::optional<base>{});
200192 test (beman::optional::optional<derived>{});
193+ return true ;
201194 };
202- static_assert ( (lambda (), true ));
203- lambda ();
195+ EXPECT_TRUE ( constify (lambda ()));
196+ EXPECT_TRUE ( lambda () );
204197}
205198
206199TEST (RangeSupportTest, EndOnNonEmptyOptional) {
@@ -212,10 +205,10 @@ TEST(RangeSupportTest, EndOnNonEmptyOptional) {
212205 // e.g. const_iterator = optional<T>::const_iterator if opt is optional<T>
213206 using const_iterator = typename std::remove_reference_t <decltype (opt)>::const_iterator;
214207
215- CONSTEXPR_EXPECT_EQ (opt.end (), iterator (&*opt + 1 ));
208+ constexpr_expect_eq (opt.end (), iterator (&*opt + 1 ));
216209
217210 const auto & const_opt = opt;
218- CONSTEXPR_EXPECT_EQ (const_opt.end (), const_iterator (&*opt + 1 ));
211+ constexpr_expect_eq (const_opt.end (), const_iterator (&*opt + 1 ));
219212 };
220213
221214 test (beman::optional::optional<int >{26 });
@@ -226,12 +219,14 @@ TEST(RangeSupportTest, EndOnNonEmptyOptional) {
226219 test (beman::optional::optional<no_default_ctor>{no_default_ctor{empty{}}});
227220 test (beman::optional::optional<base>{base{}});
228221 test (beman::optional::optional<derived>{derived{}});
222+ return true ;
229223 };
230- static_assert ( (lambda (), true ));
231- lambda ();
224+ EXPECT_TRUE ( constify (lambda ()));
225+ EXPECT_TRUE ( lambda () );
232226}
233227
234- #if ((__GNUC__ >= 15) && (__GNUC_MINOR__ >= 1) && (__GNUC_PATCHLEVEL__ >= 1)) || ((__GNUC__ >= 16))
228+ #if (__cplusplus >= 202302L) && \
229+ (((__GNUC__ >= 15 ) && (__GNUC_MINOR__ >= 1 ) && (__GNUC_PATCHLEVEL__ >= 1 )) || ((__GNUC__ >= 16 )))
235230static_assert (std::format_kind<beman::optional::optional<int >> == std::range_format::disabled);
236231#endif
237232
@@ -258,70 +253,89 @@ TEST(RangeSupportTest, FormatOptionalIsStillDisabled) {
258253#endif
259254}
260255
256+ template <typename U>
257+ auto gtest_assert_true (U&& val1) {
258+ ASSERT_TRUE (std::forward<U>(val1));
259+ }
260+
261+ template <typename U>
262+ constexpr auto constexpr_assert (U&& val1) {
263+ if (::std::is_constant_evaluated ()) {
264+ if (!(val1))
265+ std::abort ();
266+ } else {
267+ gtest_assert_true (std::forward<U>(val1));
268+ }
269+ }
270+
261271TEST (RangeSupportTest, LoopOverEmptyRange) {
262- auto lambda = [&] {
272+ auto lambda = [&]() -> bool {
263273 beman::optional::optional<int > empty;
264- CONSTEXPR_ASSERT_FALSE ( empty.has_value ());
274+ constexpr_assert (! empty.has_value ());
265275
266276 for ([[maybe_unused]] auto _ : empty) {
267- CONSTEXPR_ASSERT_TRUE (false ) << " Should not be reached: expected not to loop over empty optional" ;
277+ constexpr_assert (false ); // << "Should not be reached: expected not to loop over empty optional";
268278 }
279+ return true ;
269280 };
270- static_assert ( (lambda (), true ));
271- lambda ();
281+ EXPECT_TRUE ( constify (lambda ()));
282+ EXPECT_TRUE ( lambda () );
272283}
273284
274285TEST (RangeSupportTest, LoopOverNonEmptyRange) {
275286 auto lambda = [&] {
276287 const int expected_value = 0xCAFEBABE ;
277288 beman::optional::optional<int > empty{expected_value};
278- CONSTEXPR_ASSERT_TRUE (empty.has_value ());
289+ constexpr_assert (empty.has_value ());
279290
280291 bool entered_loop = false ;
281292 for (auto i : empty) {
282- CONSTEXPR_EXPECT_EQ (i, expected_value);
293+ constexpr_expect_eq (i, expected_value);
283294 entered_loop = true ;
284295 }
285- CONSTEXPR_EXPECT_TRUE (entered_loop);
296+ constexpr_expect_eq (entered_loop, true );
297+ return true ;
286298 };
287- static_assert ( (lambda (), true ));
288- lambda ();
299+ EXPECT_TRUE ( constify (lambda ()));
300+ EXPECT_TRUE ( lambda () );
289301}
290302
291303TEST (RangeSupportTest, LoopOptionalAccess) {
292304 auto lambda = [&] {
293305 // Example from P3168R2: should access the value from an optional object.
294306 const int expected_value = 0xCAFEBABE ;
295307 const auto get_optional = [&]() -> beman::optional::optional<int > { return expected_value; };
296- CONSTEXPR_ASSERT_TRUE (get_optional ().has_value ());
308+ constexpr_assert (get_optional ().has_value ());
297309
298310 for (auto && opt : get_optional ()) {
299- CONSTEXPR_EXPECT_EQ (opt, expected_value); // usage of opt here is safe
311+ constexpr_expect_eq (opt, expected_value); // usage of opt here is safe
300312 }
313+ return true ;
301314 };
302- static_assert ( (lambda (), true ));
303- lambda ();
315+ EXPECT_TRUE ( constify (lambda ()));
316+ EXPECT_TRUE ( lambda () );
304317}
305318
306319TEST (RangeSupportTest, LoopOptionalAssignment) {
307- auto lambda = [& ] {
320+ constexpr auto lambda = [] {
308321 // 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);
322+ constexpr int initial_expected_value = 0xCAFEBABE ;
323+ constexpr int expected_value = 0xDEADBEEF ;
324+ constexpr auto get_optional = [= ]() -> beman::optional::optional<int > { return initial_expected_value; };
325+ constexpr_assert (get_optional ().has_value ());
326+ constexpr_assert (get_optional ().value () == initial_expected_value);
314327
315328 auto opt_int = get_optional ();
316329 for (auto && opt : opt_int) {
317- CONSTEXPR_EXPECT_EQ (opt, initial_expected_value);
330+ constexpr_expect_eq (opt, initial_expected_value);
318331 opt = expected_value; // usage of opt here is safe
319332 }
320- CONSTEXPR_ASSERT_TRUE (opt_int.has_value ());
321- CONSTEXPR_EXPECT_EQ (opt_int.value (), expected_value);
333+ constexpr_assert (opt_int.has_value ());
334+ constexpr_expect_eq (opt_int.value (), expected_value);
335+ return true ;
322336 };
323- static_assert ( (lambda (), true ));
324- lambda ();
337+ EXPECT_TRUE ( constify (lambda ()));
338+ EXPECT_TRUE ( lambda () );
325339}
326340
327341TEST (RangeSupportTest, RangeChainExample) {
@@ -407,13 +421,14 @@ TEST(RangeSupportTest, PythagoreanTriples) {
407421 };
408422 constexpr const std::tuple k100th_triple = {
409423 26 , 168 , 170 }; // The 100th Pythagorean triple with x, y, z <= 200.
410- ASSERT_EQ (bruteforce_generate_nth (100 , 200 ), k100th_triple);
424+ EXPECT_EQ (bruteforce_generate_nth (100 , 200 ), k100th_triple);
411425
412426 // Generate the 100th Pythagorean triple with ranges.
413427 auto && r = triples | std::views::drop (99 ) | std::views::take (1 );
414428 EXPECT_TRUE (std::ranges::equal (r, std::vector{k100th_triple}));
415429 }
430+ return true ;
416431 };
417- static_assert ( (lambda (), true ));
418- lambda ();
432+ EXPECT_TRUE ( constify (lambda ()));
433+ EXPECT_TRUE ( lambda () );
419434}
0 commit comments