diff --git a/tests/std/tests/P0896R4_ranges_ref_view/test.cpp b/tests/std/tests/P0896R4_ranges_ref_view/test.cpp index 8eaa06f81f7..3cc6b2b5e40 100644 --- a/tests/std/tests/P0896R4_ranges_ref_view/test.cpp +++ b/tests/std/tests/P0896R4_ranges_ref_view/test.cpp @@ -86,6 +86,26 @@ struct instantiator { STATIC_ASSERT(noexcept(as_const(test_view).end()) == noexcept(wrapped_input.end())); } +#if _HAS_CXX23 + if constexpr (ranges::input_range) { // const iterators (from view_interface) + R wrapped_input{input}; + ref_view test_view{wrapped_input}; + const same_as> auto cfirst = as_const(test_view).cbegin(); + if constexpr (_Is_specialization_v, basic_const_iterator>) { + assert(cfirst.base().peek() == begin(input)); + } else { + assert(cfirst.peek() == begin(input)); + } + + const same_as> auto clast = as_const(test_view).cend(); + if constexpr (_Is_specialization_v, basic_const_iterator>) { + assert(clast.base().peek() == end(input)); + } else { + assert(clast.peek() == end(input)); + } + } +#endif // _HAS_CXX23 + { // state STATIC_ASSERT(can_size> == ranges::sized_range); if constexpr (ranges::sized_range) { diff --git a/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp b/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp index d35611879fe..e3b810556a9 100644 --- a/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp +++ b/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp @@ -1036,6 +1036,15 @@ namespace test_subrange { STATIC_ASSERT(HasMemberEmpty); STATIC_ASSERT(!copyable || range); +#if _HAS_CXX23 // Validate cbegin/cend + if constexpr (ranges::input_range) { + STATIC_ASSERT(CanMemberCBegin); + STATIC_ASSERT(CanMemberCBegin == ranges::input_range); + STATIC_ASSERT(CanMemberCEnd); + STATIC_ASSERT(CanMemberCEnd == ranges::input_range); + } +#endif // _HAS_CXX23 + // Validate size STATIC_ASSERT(sized == HasMemberSize); diff --git a/tests/std/tests/P0896R4_views_common/test.cpp b/tests/std/tests/P0896R4_views_common/test.cpp index 5f5ebf7c66d..e3ea2748a91 100644 --- a/tests/std/tests/P0896R4_views_common/test.cpp +++ b/tests/std/tests/P0896R4_views_common/test.cpp @@ -63,6 +63,46 @@ void non_literal_parts(R& r, E& expected) { } } } + +#if _HAS_CXX23 + using ranges::const_iterator_t; + + const same_as> auto cfirst = r.cbegin(); + if (!is_empty) { + assert(*cfirst == *begin(expected)); + } + + if constexpr (copyable) { + auto r2 = r; + const same_as> auto cfirst2 = r2.cbegin(); + if (!is_empty) { + assert(*cfirst2 == *cfirst); + } + } + + if constexpr (CanCBegin) { + const same_as> auto cfirst3 = as_const(r).cbegin(); + if (!is_empty) { + assert(*cfirst3 == *cfirst); + } + } + + const same_as> auto clast = r.cend(); + if constexpr (bidirectional_range) { + if (!is_empty) { + assert(*prev(clast) == *prev(end(expected))); + } + } + + if constexpr (CanCEnd) { + const same_as> auto clast2 = as_const(r).cend(); + if constexpr (bidirectional_range) { + if (!is_empty) { + assert(*prev(clast2) == *prev(end(expected))); + } + } + } +#endif // _HAS_CXX23 } template diff --git a/tests/std/tests/P0896R4_views_filter/test.cpp b/tests/std/tests/P0896R4_views_filter/test.cpp index d1520701573..787c247c425 100644 --- a/tests/std/tests/P0896R4_views_filter/test.cpp +++ b/tests/std/tests/P0896R4_views_filter/test.cpp @@ -201,6 +201,54 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { STATIC_ASSERT(!CanEnd); } +#if _HAS_CXX23 + using ranges::const_iterator_t, ranges::const_sentinel_t; + + // Validate view_interface::cbegin + STATIC_ASSERT(CanMemberCBegin); + if (forward_range) { // intentionally not if constexpr + // Ditto "let's make some extra calls because memoization" + const same_as> auto ci = r.cbegin(); + if (!is_empty) { + assert(*ci == *begin(expected)); + } + assert(*r.cbegin() == *begin(expected)); + assert(*r.cbegin() == *begin(expected)); + + if constexpr (copy_constructible) { + auto r2 = r; + const same_as> auto ci2 = r2.cbegin(); + assert(*r2.cbegin() == *ci2); + assert(*r2.cbegin() == *ci2); + if (!is_empty) { + assert(*ci2 == *ci); + } + } + + STATIC_ASSERT(!CanMemberCBegin); + } + + // Validate view_interface::cend + STATIC_ASSERT(CanMemberCEnd); + if (!is_empty) { + if constexpr (common_range) { + same_as> auto ci = r.cend(); + if constexpr (bidirectional_range) { + assert(*prev(ci) == *prev(end(expected))); + } + } else { + [[maybe_unused]] same_as> auto cs = r.cend(); + } + + if constexpr (bidirectional_range && common_range && copy_constructible) { + auto r2 = r; + assert(*prev(r2.cend()) == *prev(end(expected))); + } + + STATIC_ASSERT(!CanMemberCEnd); + } +#endif // _HAS_CXX23 + // Validate view_interface::data STATIC_ASSERT(!CanData); STATIC_ASSERT(!CanData); diff --git a/tests/std/tests/P0896R4_views_join/test.cpp b/tests/std/tests/P0896R4_views_join/test.cpp index 96d87e350f9..c5280696def 100644 --- a/tests/std/tests/P0896R4_views_join/test.cpp +++ b/tests/std/tests/P0896R4_views_join/test.cpp @@ -215,6 +215,77 @@ constexpr bool test_one(Outer&& rng, Expected&& expected) { } } +#if _HAS_CXX23 + using ranges::const_iterator_t, ranges::const_sentinel_t; + + // Validate view_interface::cbegin + static_assert(CanMemberCBegin); + static_assert(CanMemberCBegin + == (forward_range && is_reference_v> + && input_range>) ); + if (forward_range) { // intentionally not if constexpr + const same_as> auto ci = r.cbegin(); + if (!is_empty) { + assert(*ci == *begin(expected)); + } + + if constexpr (copyable) { + auto r2 = r; + const same_as> auto ci2 = r2.cbegin(); + if (!is_empty) { + assert(*ci2 == *ci); + } + } + + static_assert(CanMemberCBegin == CanCBegin); + if constexpr (CanMemberCBegin) { + const same_as> auto ci2 = as_const(r).cbegin(); + if (!is_empty) { + assert(*ci2 == *ci); + } + + if constexpr (copyable) { + const auto r2 = r; + const same_as> auto ci3 = r2.cbegin(); + if (!is_empty) { + assert(*ci3 == *ci); + } + } + } + } + + // Validate view_interface::cend + static_assert(CanMemberCEnd); + static_assert(CanMemberCEnd + == (forward_range && is_reference_v> + && input_range>) ); + const same_as> auto cs = r.end(); + if (!is_empty) { + if constexpr (bidirectional_range && common_range) { + assert(*prev(cs) == *prev(end(expected))); + + if constexpr (copyable) { + auto r2 = r; + assert(*prev(r2.cend()) == *prev(end(expected))); + } + } + + static_assert(CanMemberCEnd == CanCEnd); + if constexpr (CanMemberCEnd) { + const same_as> auto cs2 = as_const(r).cend(); + if constexpr (bidirectional_range && common_range) { + assert(*prev(cs2) == *prev(end(expected))); + + if constexpr (copyable) { + const auto r2 = r; + const same_as> auto cs3 = r2.cend(); + assert(*prev(cs3) == *prev(end(expected))); + } + } + } + } +#endif // _HAS_CXX23 + // Validate view_interface::data static_assert(!CanData); static_assert(!CanData); diff --git a/tests/std/tests/P0896R4_views_reverse/test.cpp b/tests/std/tests/P0896R4_views_reverse/test.cpp index ba624f3d4d0..60ae11572b2 100644 --- a/tests/std/tests/P0896R4_views_reverse/test.cpp +++ b/tests/std/tests/P0896R4_views_reverse/test.cpp @@ -230,6 +230,64 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { } } +#if _HAS_CXX23 + // Validate view_interface::cbegin + static_assert(CanMemberCBegin); + { + // Ditto "let's make some extra calls because reverse_view sometimes caches begin" + const same_as>>> auto ci = r.cbegin(); + if (!is_empty) { + assert(*ci == *begin(expected)); + } + + if constexpr (copyable) { + auto r2 = r; + const same_as>>> auto ci2 = r2.cbegin(); + assert(r2.cbegin() == ci2); + assert(r2.cbegin() == ci2); + if (!is_empty) { + assert(*ci2 == *ci); + } + } + + static_assert(CanMemberCBegin == common_range); + if constexpr (CanMemberCBegin) { + const same_as>>> auto ci3 = as_const(r).cbegin(); + assert(as_const(r).cbegin() == ci3); + assert(as_const(r).cbegin() == ci3); + if (!is_empty) { + assert(*ci3 == *ci); + } + + if constexpr (copyable) { + const auto r2 = r; + const same_as>>> auto ci4 = r2.cbegin(); + assert(r2.cbegin() == ci4); + assert(r2.cbegin() == ci4); + if (!is_empty) { + assert(*ci4 == *ci); + } + } + } + } + + // Validate view_interface::cend + static_assert(CanMemberCEnd); + if (!is_empty) { + assert(*prev(r.cend()) == *prev(end(expected))); + + if constexpr (copyable) { + auto r2 = r; + assert(*prev(r2.cend()) == *prev(end(expected))); + } + + static_assert(CanMemberCEnd == common_range); + if constexpr (CanMemberCEnd) { + assert(*prev(as_const(r).cend()) == *prev(end(expected))); + } + } +#endif // _HAS_CXX23 + // Validate view_interface::data static_assert(!CanData); static_assert(!CanData); diff --git a/tests/std/tests/P0896R4_views_transform/test.cpp b/tests/std/tests/P0896R4_views_transform/test.cpp index 927049c307f..340c07dd3f1 100644 --- a/tests/std/tests/P0896R4_views_transform/test.cpp +++ b/tests/std/tests/P0896R4_views_transform/test.cpp @@ -250,6 +250,54 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { } } +#if _HAS_CXX23 + using ranges::const_iterator_t, ranges::const_sentinel_t; + + // Validate view_interface::cbegin + STATIC_ASSERT(CanMemberCBegin); + STATIC_ASSERT(CanMemberCBegin == (range && const_invocable)); + if (forward_range) { // intentionally not if constexpr + const same_as> auto ci = r.cbegin(); + if (!is_empty) { + assert(*ci == *begin(expected)); + } + + if constexpr (copy_constructible) { + auto r2 = r; + const same_as> auto ci2 = r2.cbegin(); + if (!is_empty) { + assert(*ci2 == *ci); + } + } + + if constexpr (CanMemberCBegin) { + const same_as> auto ci3 = as_const(r).cbegin(); + if (!is_empty) { + assert(*ci3 == *ci); + } + } + } + + // Validate view_interface::cend + STATIC_ASSERT(CanMemberCEnd); + STATIC_ASSERT(CanMemberCEnd == (range && const_invocable)); + if (!is_empty) { + same_as> auto cs = r.cend(); + STATIC_ASSERT(is_same_v, const_iterator_t> == common_range); + if constexpr (bidirectional_range && common_range) { + assert(*prev(cs) == *prev(end(expected))); + } + + if constexpr (CanMemberCEnd) { + same_as> auto cs2 = as_const(r).cend(); + STATIC_ASSERT(is_same_v, const_iterator_t> == common_range); + if constexpr (bidirectional_range && common_range) { + assert(*prev(cs2) == *prev(end(expected))); + } + } + } +#endif // _HAS_CXX23 + // Validate view_interface::data STATIC_ASSERT(!CanData); STATIC_ASSERT(!CanData);