diff --git a/stl/inc/iterator b/stl/inc/iterator index 8486fbee1d..1da5cfd10e 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -213,6 +213,23 @@ public: return _Last; } + using _Prevent_inheriting_unwrap = move_sentinel; + + // clang-format off + _NODISCARD constexpr move_sentinel<_Unwrapped_t> _Unwrapped() const& + noexcept(noexcept(move_sentinel<_Unwrapped_t>{_Last._Unwrapped()})) + requires _RANGES _Weakly_unwrappable_sentinel<_Se> { + // clang-format on + return move_sentinel<_Unwrapped_t>{_Last._Unwrapped()}; + } + // clang-format off + _NODISCARD constexpr move_sentinel<_Unwrapped_t<_Se>> _Unwrapped() && + noexcept(noexcept(move_sentinel<_Unwrapped_t<_Se>>{_STD move(_Last)._Unwrapped()})) + requires _RANGES _Weakly_unwrappable_sentinel<_Se> { + // clang-format on + return move_sentinel<_Unwrapped_t<_Se>>{_STD move(_Last)._Unwrapped()}; + } + private: _Se _Last{}; }; diff --git a/stl/inc/xutility b/stl/inc/xutility index 0b329812b7..5128eb4ed3 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1846,13 +1846,30 @@ namespace ranges { template using sentinel_t = decltype(_RANGES end(_STD declval<_Rng&>())); + template + concept _Weakly_unwrappable = + same_as::_Prevent_inheriting_unwrap, remove_cvref_t<_Wrapped>> // + && requires(_Wrapped&& _Wr) { + _STD forward<_Wrapped>(_Wr)._Unwrapped(); + }; + + // clang-format off + template + concept _Weakly_unwrappable_sentinel = _Weakly_unwrappable&>; + // clang-format on + + template + concept _Weakly_unwrappable_iterator = // + _Weakly_unwrappable<_Iter> // + && requires(_Iter&& _It, remove_cvref_t<_Iter>& _MutIt) { + _MutIt._Seek_to(_STD forward<_Iter>(_It)._Unwrapped()); + }; + template concept _Unwrappable_sentinel_for = // - same_as::_Prevent_inheriting_unwrap, remove_cvref_t<_Sent>> // - && same_as::_Prevent_inheriting_unwrap, remove_cvref_t<_Iter>> // - && requires(_Iter&& _It, remove_cvref_t<_Iter>& _MutIt, const remove_reference_t<_Sent>& _Se) { - _STD forward<_Iter>(_It)._Unwrapped(); - _MutIt._Seek_to(_STD forward<_Iter>(_It)._Unwrapped()); + _Weakly_unwrappable_sentinel<_Sent> // + && _Weakly_unwrappable_iterator<_Iter> // + && requires(_Iter&& _It, const remove_reference_t<_Sent>& _Se) { { _Se._Unwrapped() } -> sentinel_for(_It)._Unwrapped())>; }; diff --git a/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp b/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp index 6cf4e16307..5f6598a3ff 100644 --- a/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp +++ b/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -39,8 +40,11 @@ void test_algorithms(Rng& rng) { } } -template -void test_unwrappable_pair() { +template +void test_unwrappable_range() { + using It = ranges::iterator_t; + using Se = ranges::sentinel_t; + constexpr bool is_const_unwrappable = requires(const It& ci) { ci._Unwrapped(); }; @@ -70,12 +74,15 @@ void test_unwrappable_pair() { noexcept(ranges::_Unwrap_sent(declval())) == noexcept(declval()._Unwrapped())); // instantiate without calling - void (*p)(ranges::subrange&) = test_algorithms>; + void (*p)(Rng&) = test_algorithms; (void) p; } -template -void test_not_unwrappable_pair() { +template +void test_not_unwrappable_range() { + using It = ranges::iterator_t; + using Se = ranges::sentinel_t; + STATIC_ASSERT(!ranges::_Unwrappable_sentinel_for); STATIC_ASSERT(same_as, It>); STATIC_ASSERT(same_as, It>); @@ -90,14 +97,14 @@ void test_not_unwrappable_pair() { STATIC_ASSERT(noexcept(ranges::_Unwrap_sent(declval()))); // instantiate without calling - void (*p)(ranges::subrange&) = test_algorithms>; + void (*p)(Rng&) = test_algorithms; (void) p; } template void test_classic_range() { - test_unwrappable_pair, ranges::sentinel_t>(); - test_unwrappable_pair, ranges::sentinel_t>(); + test_unwrappable_range(); + test_unwrappable_range(); } void test_classic_ranges() { test_classic_range(); @@ -113,6 +120,10 @@ void test_classic_ranges() { test_classic_range>(); test_classic_range>(); test_classic_range(); + +#if _HAS_CXX23 + test_classic_range>(); +#endif } struct Nontrivial { @@ -130,23 +141,45 @@ struct Nontrivial { bool operator==(const Nontrivial&) const noexcept = default; }; +template +void test_unwrappable_views() { + using R = ranges::subrange; + + test_unwrappable_range(); + +#if _HAS_CXX23 + test_unwrappable_range>(); +#endif +} + +template +void test_not_unwrappable_views() { + using R = ranges::subrange; + + test_not_unwrappable_range(); + +#if _HAS_CXX23 + test_not_unwrappable_range>(); +#endif +} + void test_both_unwrappable() { using test::contiguous, test::random, test::bidi, test::fwd, test::input; using sent_int = test::sentinel; using sent_nt = test::sentinel; - test_unwrappable_pair, sent_int>(); - test_unwrappable_pair, sent_int>(); - test_unwrappable_pair, sent_int>(); - test_unwrappable_pair, sent_int>(); - test_unwrappable_pair, sent_int>(); - - test_unwrappable_pair, sent_nt>(); - test_unwrappable_pair, sent_nt>(); - test_unwrappable_pair, sent_nt>(); - test_unwrappable_pair, sent_nt>(); - test_unwrappable_pair, sent_nt>(); + test_unwrappable_views, sent_int>(); + test_unwrappable_views, sent_int>(); + test_unwrappable_views, sent_int>(); + test_unwrappable_views, sent_int>(); + test_unwrappable_views, sent_int>(); + + test_unwrappable_views, sent_nt>(); + test_unwrappable_views, sent_nt>(); + test_unwrappable_views, sent_nt>(); + test_unwrappable_views, sent_nt>(); + test_unwrappable_views, sent_nt>(); } void test_iter_unwrappable() { @@ -155,17 +188,17 @@ void test_iter_unwrappable() { using sent_int = test::sentinel; using sent_nt = test::sentinel; - test_not_unwrappable_pair, sent_int>(); - test_not_unwrappable_pair, sent_int>(); - test_not_unwrappable_pair, sent_int>(); - test_not_unwrappable_pair, sent_int>(); - test_not_unwrappable_pair, sent_int>(); - - test_not_unwrappable_pair, sent_nt>(); - test_not_unwrappable_pair, sent_nt>(); - test_not_unwrappable_pair, sent_nt>(); - test_not_unwrappable_pair, sent_nt>(); - test_not_unwrappable_pair, sent_nt>(); + test_not_unwrappable_views, sent_int>(); + test_not_unwrappable_views, sent_int>(); + test_not_unwrappable_views, sent_int>(); + test_not_unwrappable_views, sent_int>(); + test_not_unwrappable_views, sent_int>(); + + test_not_unwrappable_views, sent_nt>(); + test_not_unwrappable_views, sent_nt>(); + test_not_unwrappable_views, sent_nt>(); + test_not_unwrappable_views, sent_nt>(); + test_not_unwrappable_views, sent_nt>(); } void test_sent_unwrappable() { @@ -174,17 +207,17 @@ void test_sent_unwrappable() { using sent_int = test::sentinel; using sent_nt = test::sentinel; - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); } void test_neither_unwrappable() { @@ -193,17 +226,17 @@ void test_neither_unwrappable() { using sent_int = test::sentinel; using sent_nt = test::sentinel; - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_int>(); - - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); - test_not_unwrappable_pair::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_int>(); + + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); + test_not_unwrappable_views::unwrapping_ignorant, sent_nt>(); } int main() {} // COMPILE-ONLY