diff --git a/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp --- a/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp @@ -36,7 +36,7 @@ struct DifferentSentinel : std::ranges::view_base { int *begin() const; - sentinel_wrapper end() const; + sentinel end() const; }; static_assert( std::ranges::__simple_view); diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp @@ -83,7 +83,7 @@ constexpr void check_forward(std::ptrdiff_t n, expected_t expected, range_t& range) { using Difference = std::iter_difference_t; auto current = stride_counting_iterator(It(range.begin())); - Difference const result = std::ranges::advance(current, n, sentinel_wrapper(It(range.end()))); + Difference const result = std::ranges::advance(current, n, sentinel(It(range.end()))); assert(current.base().base() == expected.coordinate); assert(result == expected.result); assert(current.stride_count() == n - result); diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp @@ -74,7 +74,7 @@ auto range = range_t{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; auto first = stride_counting_iterator(It(range.begin())); auto const last = It(range.begin() + n); - std::ranges::advance(first, sentinel_wrapper(last)); + std::ranges::advance(first, sentinel(last)); assert(first.base() == last); assert(first.stride_count() == n); } diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.next/iterator_sentinel.pass.cpp @@ -94,7 +94,7 @@ auto n = (last.base() - it.base()); { - auto sent = sentinel_wrapper(last); + auto sent = sentinel(last); It result = std::ranges::next(std::move(it), sent); assert(&*result == expected); } @@ -102,7 +102,7 @@ // Count operations { auto strided_it = stride_counting_iterator(it); - auto sent = sentinel_wrapper(stride_counting_iterator(last)); + auto sent = sentinel(stride_counting_iterator(last)); stride_counting_iterator result = std::ranges::next(std::move(strided_it), sent); assert(&*result == expected); assert(result.stride_count() == n); // must have used ++ until it hit the sentinel diff --git a/libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp b/libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp --- a/libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp +++ b/libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp @@ -46,7 +46,7 @@ struct BadReturnType { BadReturnType empty() { return {}; } }; -static_assert(!std::is_invocable_v); +static_assert(!std::is_invocable_v); struct BoolConvertible { constexpr operator bool() noexcept(false) { return true; } @@ -54,7 +54,6 @@ struct BoolConvertibleReturnType { constexpr BoolConvertible empty() noexcept { return {}; } }; - static_assert(!noexcept(std::ranges::empty(BoolConvertibleReturnType()))); constexpr bool testEmptyMember() { @@ -91,79 +90,40 @@ return true; } -struct other_forward_iterator : forward_iterator { }; - -struct sentinel { - constexpr bool operator==(std::input_or_output_iterator auto) const { return true; } -}; - struct BeginEndNotSizedSentinel { - friend constexpr forward_iterator begin(BeginEndNotSizedSentinel) { return {}; } - friend constexpr sentinel end(BeginEndNotSizedSentinel) { return {}; } -}; -static_assert(!std::is_invocable_v); - -struct InvalidMinusBeginEnd { - friend constexpr random_access_iterator begin(InvalidMinusBeginEnd) { return {}; } - friend constexpr sentinel end(InvalidMinusBeginEnd) { return {}; } -}; - -// Int is integer-like, but it is not other_forward_iterator's difference_type. -constexpr short operator-(sentinel, random_access_iterator) { return 2; } -constexpr short operator-(random_access_iterator, sentinel) { return 2; } -static_assert(!std::is_invocable_v); - -// This type will use ranges::size. -struct IntPtrBeginAndEnd { - int buff[8]; - constexpr int* begin() { return buff; } - constexpr int* end() { return buff + 8; } + constexpr int *begin() const { return nullptr; } + constexpr auto end() const { return sentinel(nullptr); } }; -static_assert(std::is_invocable_v); +static_assert( std::ranges::forward_range); +static_assert(!std::ranges::sized_range); -// size is disabled here, and it isn't sized_sentinel_for, so we have to compare begin -// and end again. +// size is disabled here, so we have to compare begin and end. struct DisabledSizeRangeWithBeginEnd { - friend constexpr forward_iterator begin(DisabledSizeRangeWithBeginEnd) { return {}; } - friend constexpr sentinel end(DisabledSizeRangeWithBeginEnd) { return {}; } - constexpr size_t size() const { return 1; } + constexpr int *begin() const { return {}; } + constexpr sentinel end() const { return {}; } + size_t size() const; }; - -template <> +template<> inline constexpr bool std::ranges::disable_sized_range = true; -static_assert(!std::is_invocable_v); +static_assert(std::ranges::contiguous_range); +static_assert(!std::ranges::sized_range); struct BeginEndAndEmpty { - int* begin(); - int* end(); - constexpr bool empty() { return true; } -}; - -struct BeginEndAndConstEmpty { - int* begin(); - int* end(); - constexpr bool empty() const { return true; } + constexpr int *begin() const { return nullptr; } + constexpr int *end() const { return nullptr; } + constexpr bool empty() { return false; } }; constexpr bool testBeginEqualsEnd() { BeginEndNotSizedSentinel a; assert(std::ranges::empty(a) == true); - InvalidMinusBeginEnd b; - assert(std::ranges::empty(b) == true); - - IntPtrBeginAndEnd c; - assert(std::ranges::empty(c) == false); - DisabledSizeRangeWithBeginEnd d; assert(std::ranges::empty(d) == true); BeginEndAndEmpty e; - assert(std::ranges::empty(e) == true); - - BeginEndAndConstEmpty f; - assert(std::ranges::empty(f) == true); - assert(std::ranges::empty(std::as_const(f)) == true); + assert(std::ranges::empty(e) == false); // using begin()==end() + assert(std::ranges::empty(std::as_const(e)) == true); // using empty() return true; } diff --git a/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp b/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp --- a/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp +++ b/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp @@ -30,8 +30,7 @@ struct SizeMember { constexpr size_t size() { return 42; } }; - -static_assert(!std::is_invocable_v); +static_assert(!std::is_invocable_v); struct SizeFunction { friend constexpr size_t size(SizeFunction) { return 42; } @@ -41,18 +40,12 @@ friend constexpr std::ptrdiff_t size(SizeFunctionSigned) { return 42; } }; -struct sentinel { - bool operator==(std::input_or_output_iterator auto) const { return true; } -}; - -struct RandomAccesslRange { - constexpr random_access_iterator begin() { return {}; } - constexpr sentinel end() { return {}; } +int globalBuff[2]; +struct SizedSentinelRange { + constexpr int *begin() { return globalBuff; } + constexpr auto end() { return sized_sentinel(globalBuff + 2); } }; -constexpr std::ptrdiff_t operator-(const sentinel, const random_access_iterator) { return 2; } -constexpr std::ptrdiff_t operator-(const random_access_iterator, const sentinel) { return 2; } - struct ShortUnsignedReturnType { constexpr unsigned short size() { return 42; } }; @@ -75,7 +68,7 @@ assert(std::ranges::ssize(SizeFunctionSigned()) == 42); ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunctionSigned())), std::ptrdiff_t); - RandomAccesslRange b; + SizedSentinelRange b; assert(std::ranges::ssize(b) == 2); ASSERT_SAME_TYPE(decltype(std::ranges::ssize(b)), std::ptrdiff_t); diff --git a/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp @@ -37,5 +37,5 @@ ASSERT_SAME_TYPE(std::views::all_t, std::ranges::ref_view); // Otherwise, returns subrange, sentinel_t> -ASSERT_SAME_TYPE(std::views::all_t, std::ranges::subrange, sentinel>); -ASSERT_SAME_TYPE(std::views::all_t, std::ranges::subrange, sentinel>); +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::subrange, sentinel>>); +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::subrange, sentinel>>); diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp @@ -24,7 +24,7 @@ struct MutableView : std::ranges::view_base { int* begin(); - sentinel_wrapper end(); + sentinel end(); }; template @@ -66,22 +66,17 @@ { SizedForwardView view{buf, buf + 8}; std::ranges::common_view common(view); - using CommonIter = std::common_iterator>; - std::same_as auto begin = common.begin(); - assert(begin == std::ranges::begin(view)); - } - { - SizedForwardView view{buf, buf + 8}; - std::ranges::common_view const common(view); - using CommonIter = std::common_iterator>; + using CommonIter = std::common_iterator>; std::same_as auto begin = common.begin(); assert(begin == std::ranges::begin(view)); + std::same_as auto cbegin = std::as_const(common).begin(); + assert(cbegin == std::ranges::begin(view)); } { MoveOnlyView view{buf, buf + 8}; std::ranges::common_view common(std::move(view)); - using CommonIter = std::common_iterator>; + using CommonIter = std::common_iterator>; std::same_as auto begin = common.begin(); assert(begin == std::ranges::begin(view)); } @@ -89,7 +84,7 @@ { CopyableView view{buf, buf + 8}; std::ranges::common_view const common(view); - using CommonIter = std::common_iterator>; + using CommonIter = std::common_iterator>; std::same_as auto begin = common.begin(); assert(begin == std::ranges::begin(view)); } diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/borrowing.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.common.view/borrowing.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.common.view/borrowing.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/borrowing.compile.pass.cpp @@ -20,12 +20,12 @@ struct View : std::ranges::view_base { int *begin() const; - sentinel_wrapper end() const; + sentinel end() const; }; struct BorrowableView : std::ranges::view_base { int *begin() const; - sentinel_wrapper end() const; + sentinel end() const; }; template<> inline constexpr bool std::ranges::enable_borrowed_range = true; diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.common.view/ctad.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.common.view/ctad.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/ctad.compile.pass.cpp @@ -20,17 +20,17 @@ struct View : std::ranges::view_base { int *begin() const; - sentinel_wrapper end() const; + sentinel end() const; }; struct Range { int *begin() const; - sentinel_wrapper end() const; + sentinel end() const; }; struct BorrowedRange { int *begin() const; - sentinel_wrapper end() const; + sentinel end() const; }; template<> inline constexpr bool std::ranges::enable_borrowed_range = true; @@ -55,6 +55,6 @@ static_assert(std::same_as< decltype(std::ranges::common_view(std::move(br))), std::ranges::common_view, std::ranges::subrange_kind::unsized>> + int *, sentinel, std::ranges::subrange_kind::unsized>> >); } diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp @@ -51,8 +51,8 @@ { int buf[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - using CommonForwardIter = std::common_iterator>; - using CommonIntIter = std::common_iterator>; + using CommonForwardIter = std::common_iterator>; + using CommonIntIter = std::common_iterator>; { SizedForwardView view{buf, buf + 8}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h b/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h @@ -18,7 +18,7 @@ int* end_ = nullptr; explicit DefaultConstructibleView() = default; constexpr int *begin() const { return begin_; } - constexpr auto end() const { return sentinel_wrapper(end_); } + constexpr auto end() const { return sentinel(end_); } }; static_assert(std::ranges::view); static_assert(std::default_initializable); @@ -30,7 +30,7 @@ constexpr MoveOnlyView(MoveOnlyView&&) = default; constexpr MoveOnlyView& operator=(MoveOnlyView&&) = default; constexpr int *begin() const { return begin_; } - constexpr auto end() const { return sentinel_wrapper(end_); } + constexpr auto end() const { return sentinel(end_); } }; static_assert( std::ranges::view); static_assert( std::ranges::contiguous_range); @@ -41,7 +41,7 @@ int* end_; constexpr explicit CopyableView(int* b, int* e) : begin_(b), end_(e) { } constexpr int *begin() const { return begin_; } - constexpr auto end() const { return sentinel_wrapper(end_); } + constexpr auto end() const { return sentinel(end_); } }; static_assert(std::ranges::view); static_assert(std::copyable); @@ -52,15 +52,8 @@ int* end_; constexpr explicit SizedForwardView(int* b, int* e) : begin_(b), end_(e) { } constexpr auto begin() const { return forward_iterator(begin_); } - constexpr auto end() const { return sentinel_wrapper>(forward_iterator(end_)); } + constexpr auto end() const { return sized_sentinel>(forward_iterator(end_)); } }; -// Required to make SizedForwardView a sized view. -constexpr auto operator-(sentinel_wrapper sent, ForwardIter iter) { - return sent.base().base() - iter.base(); -} -constexpr auto operator-(ForwardIter iter, sentinel_wrapper sent) { - return iter.base() - sent.base().base(); -} static_assert(std::ranges::view); static_assert(std::ranges::forward_range); static_assert(std::ranges::sized_range); @@ -71,15 +64,8 @@ int* end_; constexpr explicit SizedRandomAccessView(int* b, int* e) : begin_(b), end_(e) { } constexpr auto begin() const { return random_access_iterator(begin_); } - constexpr auto end() const { return sentinel_wrapper>(random_access_iterator(end_)); } + constexpr auto end() const { return sized_sentinel>(random_access_iterator(end_)); } }; -// Required to make SizedRandomAccessView a sized view. -constexpr auto operator-(sentinel_wrapper sent, RandomAccessIter iter) { - return sent.base().base() - iter.base(); -} -constexpr auto operator-(RandomAccessIter iter, sentinel_wrapper sent) { - return iter.base() - sent.base().base(); -} static_assert(std::ranges::view); static_assert(std::ranges::random_access_range); static_assert(std::ranges::sized_range); @@ -99,7 +85,7 @@ int* end_; constexpr explicit NonCommonView(int* b, int* e) : begin_(b), end_(e) { } constexpr int *begin() const { return begin_; } - constexpr auto end() const { return sentinel_wrapper(end_); } + constexpr auto end() const { return sentinel(end_); } }; static_assert( std::ranges::view); static_assert(!std::ranges::common_range); diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/end.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.drop/end.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/end.pass.cpp @@ -27,7 +27,7 @@ // !simple-view std::ranges::drop_view dropView2(InputView(), 4); - assert(dropView2.end() == globalBuff + 8); + assert(base(base(dropView2.end())) == globalBuff + 8); // range const std::ranges::drop_view dropView3(MoveOnlyView(), 0); @@ -35,7 +35,7 @@ // !simple-view const std::ranges::drop_view dropView4(InputView(), 2); - assert(dropView4.end() == globalBuff + 8); + assert(base(base(dropView4.end())) == globalBuff + 8); // range std::ranges::drop_view dropView5(MoveOnlyView(), 10); diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/types.h b/libcxx/test/std/ranges/range.adaptors/range.drop/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.drop/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/types.h @@ -76,12 +76,9 @@ inline constexpr bool std::ranges::enable_borrowed_range = true; struct InputView : std::ranges::view_base { - constexpr cpp20_input_iterator begin() const { return cpp20_input_iterator(globalBuff); } - constexpr int* end() const { return globalBuff + 8; } + constexpr auto begin() const { return cpp20_input_iterator(globalBuff); } + constexpr auto end() const { return sentinel>(cpp20_input_iterator(globalBuff + 8)); } }; -// TODO: remove these bogus operators -constexpr bool operator==(const cpp20_input_iterator &lhs, int* rhs) { return lhs.base() == rhs; } -constexpr bool operator==(int* lhs, const cpp20_input_iterator &rhs) { return rhs.base() == lhs; } struct Range { int *begin() const; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp @@ -22,24 +22,24 @@ // All friends here are defined to prevent GCC warnings. friend T* begin(View&) { return nullptr; } friend T* begin(View const&) { return nullptr; } - friend sentinel_wrapper end(View&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(View const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(View&) { return sentinel(nullptr); } + friend sentinel end(View const&) { return sentinel(nullptr); } }; template struct Range { friend T* begin(Range&) { return nullptr; } friend T* begin(Range const&) { return nullptr; } - friend sentinel_wrapper end(Range&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(Range const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(Range&) { return sentinel(nullptr); } + friend sentinel end(Range const&) { return sentinel(nullptr); } }; template struct BorrowedRange { friend T* begin(BorrowedRange&) { return nullptr; } friend T* begin(BorrowedRange const&) { return nullptr; } - friend sentinel_wrapper end(BorrowedRange&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(BorrowedRange const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(BorrowedRange&) { return sentinel(nullptr); } + friend sentinel end(BorrowedRange const&) { return sentinel(nullptr); } }; template<> @@ -66,7 +66,7 @@ static_assert(std::same_as< decltype(std::ranges::join_view(std::move(br))), std::ranges::join_view *, - sentinel_wrapper *>, + sentinel *>, std::ranges::subrange_kind::unsized>> >); } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp b/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp @@ -23,8 +23,8 @@ struct Range { friend T* begin(Range&) { return nullptr; } friend T* begin(Range const&) { return nullptr; } - friend sentinel_wrapper end(Range&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(Range const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(Range&) { return sentinel(nullptr); } + friend sentinel end(Range const&) { return sentinel(nullptr); } }; void testExplicitCTAD() { diff --git a/libcxx/test/std/ranges/range.adaptors/range.reverse/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.reverse/begin.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.reverse/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.reverse/begin.pass.cpp @@ -57,13 +57,13 @@ auto begin() { return CountedIter(begin_); } auto begin() const { return CountedIter(begin_); } - auto end() { return sentinel_wrapper(CountedIter(end_)); } - auto end() const { return sentinel_wrapper(CountedIter(end_)); } + auto end() { return sentinel(CountedIter(end_)); } + auto end() const { return sentinel(CountedIter(end_)); } }; struct RASentRange : std::ranges::view_base { - using sent_t = sentinel_wrapper>; - using sent_const_t = sentinel_wrapper>; + using sent_t = sentinel>; + using sent_const_t = sentinel>; int* begin_; int* end_; diff --git a/libcxx/test/std/ranges/range.adaptors/range.reverse/borrowing.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.reverse/borrowing.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.reverse/borrowing.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.reverse/borrowing.compile.pass.cpp @@ -21,15 +21,15 @@ struct View : std::ranges::view_base { friend int* begin(View&); friend int* begin(View const&); - friend sentinel_wrapper end(View&); - friend sentinel_wrapper end(View const&); + friend sentinel end(View&); + friend sentinel end(View const&); }; struct BorrowableView : std::ranges::view_base { friend int* begin(BorrowableView&); friend int* begin(BorrowableView const&); - friend sentinel_wrapper end(BorrowableView&); - friend sentinel_wrapper end(BorrowableView const&); + friend sentinel end(BorrowableView&); + friend sentinel end(BorrowableView const&); }; template<> diff --git a/libcxx/test/std/ranges/range.adaptors/range.reverse/ctad.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.reverse/ctad.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.reverse/ctad.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.reverse/ctad.pass.cpp @@ -23,22 +23,22 @@ struct View : std::ranges::view_base { friend int* begin(View&) { return nullptr; } friend int* begin(View const&) { return nullptr; } - friend sentinel_wrapper end(View&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(View const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(View&) { return sentinel(nullptr); } + friend sentinel end(View const&) { return sentinel(nullptr); } }; struct Range { friend int* begin(Range&) { return nullptr; } friend int* begin(Range const&) { return nullptr; } - friend sentinel_wrapper end(Range&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(Range const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(Range&) { return sentinel(nullptr); } + friend sentinel end(Range const&) { return sentinel(nullptr); } }; struct BorrowedRange { friend int* begin(BorrowedRange&) { return nullptr; } friend int* begin(BorrowedRange const&) { return nullptr; } - friend sentinel_wrapper end(BorrowedRange&) { return sentinel_wrapper(nullptr); } - friend sentinel_wrapper end(BorrowedRange const&) { return sentinel_wrapper(nullptr); } + friend sentinel end(BorrowedRange&) { return sentinel(nullptr); } + friend sentinel end(BorrowedRange const&) { return sentinel(nullptr); } }; template<> @@ -63,7 +63,7 @@ (void)x; } { - using Subrange = std::ranges::subrange, std::ranges::subrange_kind::unsized>; + using Subrange = std::ranges::subrange, std::ranges::subrange_kind::unsized>; std::same_as> auto x = std::ranges::reverse_view(std::move(br)); (void)x; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.reverse/types.h b/libcxx/test/std/ranges/range.adaptors/range.reverse/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.reverse/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.reverse/types.h @@ -31,8 +31,8 @@ enum CopyCategory { MoveOnly, Copyable }; template struct BidirSentRange : std::ranges::view_base { - using sent_t = sentinel_wrapper>; - using sent_const_t = sentinel_wrapper>; + using sent_t = sentinel>; + using sent_const_t = sentinel>; int* begin_; int* end_; diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/borrowing.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/borrowing.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/borrowing.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/borrowing.compile.pass.cpp @@ -21,15 +21,15 @@ struct View : std::ranges::view_base { friend int* begin(View&); friend int* begin(View const&); - friend sentinel_wrapper end(View&); - friend sentinel_wrapper end(View const&); + friend sentinel end(View&); + friend sentinel end(View const&); }; struct BorrowableView : std::ranges::view_base { friend int* begin(BorrowableView&); friend int* begin(BorrowableView const&); - friend sentinel_wrapper end(BorrowableView&); - friend sentinel_wrapper end(BorrowableView const&); + friend sentinel end(BorrowableView&); + friend sentinel end(BorrowableView const&); }; template<> diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/ctad.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/ctad.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/ctad.compile.pass.cpp @@ -22,22 +22,22 @@ struct View : std::ranges::view_base { friend int* begin(View&); friend int* begin(View const&); - friend sentinel_wrapper end(View&); - friend sentinel_wrapper end(View const&); + friend sentinel end(View&); + friend sentinel end(View const&); }; struct Range { friend int* begin(Range&); friend int* begin(Range const&); - friend sentinel_wrapper end(Range&); - friend sentinel_wrapper end(Range const&); + friend sentinel end(Range&); + friend sentinel end(Range const&); }; struct BorrowedRange { friend int* begin(BorrowedRange&); friend int* begin(BorrowedRange const&); - friend sentinel_wrapper end(BorrowedRange&); - friend sentinel_wrapper end(BorrowedRange const&); + friend sentinel end(BorrowedRange&); + friend sentinel end(BorrowedRange const&); }; template<> @@ -63,6 +63,6 @@ static_assert(std::same_as< decltype(std::ranges::take_view(std::move(br), 0)), std::ranges::take_view, std::ranges::subrange_kind::unsized>> + int *, sentinel, std::ranges::subrange_kind::unsized>> >); } diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/base.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/base.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/base.pass.cpp @@ -24,20 +24,13 @@ constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - auto sw = sentinel_wrapper(buffer + 8); // Note: not 4, but that's OK. - { - const std::ranges::take_view tv(MoveOnlyView{buffer}, 4); - assert(tv.end().base().base() == sw.base()); - ASSERT_SAME_TYPE(decltype(tv.end().base()), sentinel_wrapper); + std::ranges::take_view tv(MoveOnlyView(buffer), 4); + std::same_as> auto sw1 = tv.end().base(); + assert(base(sw1) == buffer + 8); + std::same_as> auto sw2 = std::as_const(tv).end().base(); + assert(base(sw2) == buffer + 8); } - - { - std::ranges::take_view tv(MoveOnlyView{buffer}, 4); - assert(tv.end().base().base() == sw.base()); - ASSERT_SAME_TYPE(decltype(tv.end().base()), sentinel_wrapper); - } - return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/ctor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/ctor.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/ctor.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/sentinel/ctor.pass.cpp @@ -27,27 +27,39 @@ { // Test the default ctor. - std::ranges::take_view tv(MoveOnlyView{buffer}, 4); - assert(decltype(tv.end()){} == std::ranges::next(tv.begin(), 4)); + using TakeView = std::ranges::take_view; + using Sentinel = std::ranges::sentinel_t; + Sentinel s; + TakeView tv = TakeView(MoveOnlyView(buffer), 4); + assert(tv.begin() + 4 == s); } { - std::ranges::take_view nonConst(MoveOnlyView{buffer}, 5); - const std::ranges::take_view tvConst(MoveOnlyView{buffer}, 5); - auto sent1 = nonConst.end(); - // Convert to const. Note, we cannot go the other way. - std::remove_cv_t sent2 = sent1; - - assert(sent1 == std::ranges::next(tvConst.begin(), 5)); - assert(sent2 == std::ranges::next(tvConst.begin(), 5)); + // Test the conversion from "sentinel" to "sentinel-to-const". + using TakeView = std::ranges::take_view; + using Sentinel = std::ranges::sentinel_t; + using ConstSentinel = std::ranges::sentinel_t; + static_assert(std::is_convertible_v); + TakeView tv = TakeView(MoveOnlyView(buffer), 4); + Sentinel s = tv.end(); + ConstSentinel cs = s; + cs = s; // test assignment also + assert(tv.begin() + 4 == s); + assert(tv.begin() + 4 == cs); + assert(std::as_const(tv).begin() + 4 == s); + assert(std::as_const(tv).begin() + 4 == cs); } { - std::ranges::take_view tv(CopyableView{buffer}, 6); - auto sw = sentinel_wrapper(buffer + 6); - using Sent = decltype(tv.end()); - Sent sent = Sent(sw); - assert(sent.base().base() == sw.base()); + // Test the constructor from "base-sentinel" to "sentinel". + using TakeView = std::ranges::take_view; + using Sentinel = std::ranges::sentinel_t; + sentinel sw1 = MoveOnlyView(buffer).end(); + static_assert( std::is_constructible_v>); + static_assert(!std::is_convertible_v, Sentinel>); + auto s = Sentinel(sw1); + std::same_as> auto sw2 = s.base(); + assert(base(sw2) == base(sw1)); } return true; diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/types.h b/libcxx/test/std/ranges/range.adaptors/range.take/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.take/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.take/types.h @@ -15,7 +15,7 @@ MoveOnlyView& operator=(MoveOnlyView&&) = default; constexpr int* begin() const {return ptr_;} - constexpr sentinel_wrapper end() const {return sentinel_wrapper{ptr_ + 8};} + constexpr sentinel end() const {return sentinel{ptr_ + 8};} }; static_assert( std::ranges::view); static_assert( std::ranges::contiguous_range); @@ -26,7 +26,7 @@ constexpr explicit CopyableView(int* ptr) : ptr_(ptr) {} constexpr int* begin() const {return ptr_;} - constexpr sentinel_wrapper end() const {return sentinel_wrapper{ptr_ + 8};} + constexpr sentinel end() const {return sentinel{ptr_ + 8};} }; static_assert(std::ranges::view); static_assert(std::ranges::contiguous_range); @@ -37,15 +37,8 @@ int *ptr_; constexpr explicit SizedForwardView(int* ptr) : ptr_(ptr) {} constexpr auto begin() const { return ForwardIter(ptr_); } - constexpr auto end() const { return sentinel_wrapper(ForwardIter(ptr_ + 8)); } + constexpr auto end() const { return sized_sentinel(ForwardIter(ptr_ + 8)); } }; -// Required to make SizedForwardView a sized view. -constexpr auto operator-(sentinel_wrapper sent, ForwardIter iter) { - return sent.base().base() - iter.base(); -} -constexpr auto operator-(ForwardIter iter, sentinel_wrapper sent) { - return iter.base() - sent.base().base(); -} static_assert(std::ranges::view); static_assert(std::ranges::forward_range); static_assert(std::ranges::sized_range); @@ -55,15 +48,8 @@ int *ptr_; constexpr explicit SizedRandomAccessView(int* ptr) : ptr_(ptr) {} constexpr auto begin() const { return RandomAccessIter(ptr_); } - constexpr auto end() const { return sentinel_wrapper(RandomAccessIter(ptr_ + 8)); } + constexpr auto end() const { return sized_sentinel(RandomAccessIter(ptr_ + 8)); } }; -// Required to make SizedRandomAccessView a sized view. -constexpr auto operator-(sentinel_wrapper sent, RandomAccessIter iter) { - return sent.base().base() - iter.base(); -} -constexpr auto operator-(RandomAccessIter iter, sentinel_wrapper sent) { - return iter.base() - sent.base().base(); -} static_assert(std::ranges::view); static_assert(std::ranges::random_access_range); static_assert(std::ranges::sized_range); diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/end.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.transform/end.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/end.pass.cpp @@ -32,37 +32,54 @@ constexpr bool test() { { - std::ranges::transform_view transformView(MoveOnlyView{}, PlusOneMutable{}); - assert(transformView.end().base() == globalBuff + 8); + using TransformView = std::ranges::transform_view; + static_assert(std::ranges::common_range); + TransformView tv; + auto end = tv.end(); + ASSERT_SAME_TYPE(decltype(end.base()), std::ranges::sentinel_t); + assert(base(end.base()) == globalBuff + 8); + static_assert(!EndInvocable); // because PlusOneMutable } - { - std::ranges::transform_view transformView(ForwardView{}, PlusOneMutable{}); - assert(transformView.end().base().base() == globalBuff + 8); + using TransformView = std::ranges::transform_view; + static_assert(!std::ranges::common_range); + TransformView tv; + auto end = tv.end(); + ASSERT_SAME_TYPE(decltype(end.base()), std::ranges::sentinel_t); + assert(base(base(end.base())) == globalBuff + 8); + static_assert(!EndInvocable); // because PlusOneMutable } - { - std::ranges::transform_view transformView(InputView{}, PlusOneMutable{}); - assert(transformView.end().base() == globalBuff + 8); + using TransformView = std::ranges::transform_view; + static_assert(!std::ranges::common_range); + TransformView tv; + auto end = tv.end(); + ASSERT_SAME_TYPE(decltype(end.base()), std::ranges::sentinel_t); + assert(base(base(end.base())) == globalBuff + 8); + auto cend = std::as_const(tv).end(); + ASSERT_SAME_TYPE(decltype(cend.base()), std::ranges::sentinel_t); + assert(base(base(cend.base())) == globalBuff + 8); } - { - const std::ranges::transform_view transformView(MoveOnlyView{}, PlusOne{}); - assert(transformView.end().base() == globalBuff + 8); + using TransformView = std::ranges::transform_view; + static_assert(std::ranges::common_range); + TransformView tv; + auto end = tv.end(); + ASSERT_SAME_TYPE(decltype(end.base()), std::ranges::sentinel_t); + assert(end.base() == globalBuff + 8); + static_assert(!EndInvocable); // because PlusOneMutable + } + { + using TransformView = std::ranges::transform_view; + static_assert(std::ranges::common_range); + TransformView tv; + auto end = tv.end(); + ASSERT_SAME_TYPE(decltype(end.base()), std::ranges::sentinel_t); + assert(end.base() == globalBuff + 8); + auto cend = std::as_const(tv).end(); + ASSERT_SAME_TYPE(decltype(cend.base()), std::ranges::sentinel_t); + assert(cend.base() == globalBuff + 8); } - - static_assert(!EndInvocable>); - static_assert( EndInvocable< std::ranges::transform_view>); - static_assert( EndInvocable>); - static_assert(!EndInvocable>); - static_assert( EndInvocable< std::ranges::transform_view>); - static_assert( EndInvocable>); - - static_assert(!EndIsIter>); - static_assert(!EndIsIter< std::ranges::transform_view>); - static_assert( EndIsIter>); - static_assert( EndIsIter< std::ranges::transform_view>); - return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/base.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/base.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/base.pass.cpp @@ -17,30 +17,29 @@ #include "test_macros.h" #include "../types.h" -template -concept BaseInvocable = requires(std::ranges::iterator_t> iter) { - iter.base(); +template +concept BaseInvocable = requires(It it) { + it.base(); }; constexpr bool test() { { - std::ranges::transform_view transformView; - auto iter = std::move(transformView).begin(); - ASSERT_SAME_TYPE(int*, decltype(iter.base())); - assert(iter.base() == globalBuff); - ASSERT_SAME_TYPE(int*, decltype(std::move(iter).base())); - assert(std::move(iter).base() == globalBuff); + using TransformView = std::ranges::transform_view; + TransformView tv; + auto begin = tv.begin(); + ASSERT_SAME_TYPE(decltype(begin.base()), int*); + assert(begin.base() == globalBuff); + ASSERT_SAME_TYPE(decltype(std::move(begin).base()), int*); + assert(std::move(begin).base() == globalBuff); } - { - std::ranges::transform_view transformView; - auto iter = transformView.begin(); - assert(std::move(iter).base() == globalBuff); - ASSERT_SAME_TYPE(cpp20_input_iterator, decltype(std::move(iter).base())); + using TransformView = std::ranges::transform_view; + TransformView tv; + auto begin = tv.begin(); + static_assert(!BaseInvocable); + std::same_as> auto it = std::move(begin).base(); + assert(base(it) == globalBuff); } - - static_assert(!BaseInvocable); - return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/size.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/size.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.transform/size.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/size.pass.cpp @@ -34,8 +34,8 @@ static_assert(!SizeInvocable>); - static_assert(SizeInvocable>); - static_assert(!SizeInvocable>); + static_assert(SizeInvocable>); + static_assert(!SizeInvocable>); return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h @@ -85,33 +85,28 @@ struct InputView : std::ranges::view_base { int *ptr_; constexpr explicit InputView(int* ptr = globalBuff) : ptr_(ptr) {} - constexpr cpp20_input_iterator begin() const { return cpp20_input_iterator(ptr_); } - constexpr int *end() const { return ptr_ + 8; } + constexpr auto begin() const { return cpp20_input_iterator(ptr_); } + constexpr auto end() const { return sentinel>(cpp20_input_iterator(ptr_ + 8)); } }; -// TODO: remove these bogus operators -constexpr bool operator==(const cpp20_input_iterator &lhs, int* rhs) { return lhs.base() == rhs; } -constexpr bool operator==(int* lhs, const cpp20_input_iterator &rhs) { return rhs.base() == lhs; } +static_assert( std::ranges::view); +static_assert(!std::ranges::sized_range); struct SizedSentinelView : std::ranges::view_base { int count_; constexpr explicit SizedSentinelView(int count = 8) : count_(count) {} - constexpr auto begin() const { return RandomAccessIter(globalBuff); } - constexpr int *end() const { return globalBuff + count_; } + constexpr int *begin() const { return globalBuff; } + constexpr auto end() const { return sized_sentinel(globalBuff + count_); } }; -// TODO: remove these bogus operators -constexpr auto operator- (const RandomAccessIter &lhs, int* rhs) { return lhs.base() - rhs; } -constexpr auto operator- (int* lhs, const RandomAccessIter &rhs) { return lhs - rhs.base(); } -constexpr bool operator==(const RandomAccessIter &lhs, int* rhs) { return lhs.base() == rhs; } -constexpr bool operator==(int* lhs, const RandomAccessIter &rhs) { return rhs.base() == lhs; } -struct SizedSentinelNotConstView : std::ranges::view_base { - ForwardIter begin() const; - int *end() const; +struct NonConstSizedView : std::ranges::view_base { + forward_iterator begin() const; + forward_iterator end() const; size_t size(); }; -// TODO: remove these bogus operators -bool operator==(const ForwardIter &lhs, int* rhs); -bool operator==(int* lhs, const ForwardIter &rhs); +static_assert( std::ranges::view); +static_assert( std::ranges::sized_range); +static_assert( std::ranges::range); +static_assert(!std::ranges::sized_range); struct Range { int *begin() const; diff --git a/libcxx/test/std/ranges/range.req/range.range/helper_aliases.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.range/helper_aliases.compile.pass.cpp --- a/libcxx/test/std/ranges/range.req/range.range/helper_aliases.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.range/helper_aliases.compile.pass.cpp @@ -24,14 +24,11 @@ #include -#include - -#include "test_iterators.h" -#include "test_range.h" - - - -static_assert(std::same_as >, std::iter_difference_t >); -static_assert(std::same_as >, std::iter_value_t >); -static_assert(std::same_as >, std::iter_reference_t >); -static_assert(std::same_as >, std::iter_rvalue_reference_t >); +struct Range { + int *begin(); + int *end(); +}; +static_assert(std::same_as, std::ptrdiff_t>); +static_assert(std::same_as, int>); +static_assert(std::same_as, int&>); +static_assert(std::same_as, int&&>); diff --git a/libcxx/test/std/ranges/range.req/range.range/iterator_t.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.range/iterator_t.compile.pass.cpp --- a/libcxx/test/std/ranges/range.req/range.range/iterator_t.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.range/iterator_t.compile.pass.cpp @@ -10,23 +10,47 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: libcpp-has-no-incomplete-ranges -// template -// using iterator_t = decltype(ranges::begin(declval())); +// template +// using iterator_t = decltype(ranges::begin(declval<_Rp&>())); #include -#include - -#include "test_range.h" - - - -static_assert(std::same_as >, cpp17_input_iterator >); -static_assert(std::same_as const>, cpp17_input_iterator >); - -static_assert(std::same_as >, cpp17_input_iterator >); - -static_assert(std::same_as >, cpp17_input_iterator >); -static_assert(std::same_as const>, cpp17_input_iterator >); - -static_assert(std::same_as >, cpp17_input_iterator >); +#include "test_iterators.h" + +template +concept HasIteratorT = requires { + typename std::ranges::iterator_t; +}; + +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); + +struct Range { + char *begin() &; + sentinel end() &; + short *begin() &&; + sentinel end() &&; + int *begin() const&; + sentinel end() const&; + long *begin() const&&; + sentinel end() const&&; +}; +static_assert(std::same_as, char*>); +static_assert(std::same_as, char*>); +static_assert(std::same_as, char*>); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); + +struct NonConstRange { + int *begin(); + int *end(); +}; +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(!HasIteratorT); +static_assert(!HasIteratorT); +static_assert(!HasIteratorT); diff --git a/libcxx/test/std/ranges/range.req/range.range/sentinel_t.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.range/sentinel_t.compile.pass.cpp --- a/libcxx/test/std/ranges/range.req/range.range/sentinel_t.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.range/sentinel_t.compile.pass.cpp @@ -15,16 +15,42 @@ #include -#include - #include "test_iterators.h" -#include "test_range.h" - - -static_assert(std::same_as >, sentinel>); -static_assert(std::same_as const>, sentinel>); -static_assert(std::same_as >, sentinel>); -static_assert(std::same_as >, cpp17_input_iterator >); -static_assert(std::same_as const>, cpp17_input_iterator >); -static_assert(std::same_as >, cpp17_input_iterator >); +template +concept HasSentinelT = requires { + typename std::ranges::sentinel_t; +}; + +static_assert(!HasSentinelT); +static_assert(!HasSentinelT); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); + +struct Range { + char *begin() &; + sentinel end() &; + short *begin() &&; + sentinel end() &&; + int *begin() const&; + sentinel end() const&; + long *begin() const&&; + sentinel end() const&&; +}; +static_assert(std::same_as, sentinel>); +static_assert(std::same_as, sentinel>); +static_assert(std::same_as, sentinel>); +static_assert(std::same_as, sentinel>); +static_assert(std::same_as, sentinel>); +static_assert(std::same_as, sentinel>); + +struct NonConstRange { + int *begin(); + int *end(); +}; +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(std::same_as, int*>); +static_assert(!HasSentinelT); +static_assert(!HasSentinelT); +static_assert(!HasSentinelT); diff --git a/libcxx/test/std/ranges/range.req/range.refinements/output_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/output_range.compile.pass.cpp --- a/libcxx/test/std/ranges/range.req/range.refinements/output_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/output_range.compile.pass.cpp @@ -14,17 +14,16 @@ // concept output_range; #include - #include + #include "test_iterators.h" -#include "test_range.h" struct T { }; // Satisfied when it's a range and has the right iterator struct GoodRange { output_iterator begin(); - sentinel end(); + sentinel> end(); }; static_assert(std::ranges::range); static_assert(std::output_iterator, T>); @@ -40,8 +39,8 @@ // Not satisfied when the iterator is not an output_iterator struct RangeWithBadIterator { - cpp17_input_iterator begin(); - sentinel end(); + cpp17_input_iterator begin(); + sentinel> end(); }; static_assert( std::ranges::range); static_assert(!std::output_iterator, T>); diff --git a/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp b/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp --- a/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp @@ -20,4 +20,4 @@ static_assert(ranges::borrowed_range>); static_assert(ranges::borrowed_range>); -static_assert(ranges::borrowed_range, ranges::subrange_kind::unsized>>); +static_assert(ranges::borrowed_range, ranges::subrange_kind::unsized>>); diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -657,6 +657,8 @@ constexpr I base() && { return std::move(base_); } + friend constexpr I base(const cpp20_input_iterator& it) { return it.base_; } + template void operator,(T const &) = delete; @@ -862,62 +864,30 @@ requires std::equality_comparable_with; }; -template -class sentinel_wrapper { +template +class sentinel { public: - sentinel_wrapper() = default; - constexpr explicit sentinel_wrapper(I base) : base_(std::move(base)) {} - - constexpr bool operator==(const I& other) const requires std::equality_comparable { - return base_ == other; - } - - constexpr const I& base() const& { return base_; } - constexpr I base() && { return std::move(base_); } - - template - requires sentinel_for_base - constexpr bool operator==(const I2& other) const { - return base_ == other.base(); - } - + sentinel() = default; + constexpr explicit sentinel(const It& it) : base_(base(it)) {} + constexpr bool operator==(const It& other) const { return base_ == base(other); } + friend constexpr auto base(const sentinel& s) { return It(s.base_); } private: - I base_ = I(); + decltype(base(std::declval())) base_; }; -template +template class sized_sentinel { public: - sized_sentinel() = default; - constexpr explicit sized_sentinel(I base) : base_(std::move(base)) {} - - constexpr bool operator==(const I& other) const requires std::equality_comparable { - return base_ == other; - } - - constexpr const I& base() const& { return base_; } - constexpr I base() && { return std::move(base_); } - - template - requires sentinel_for_base - constexpr bool operator==(const I2& other) const { - return base_ == other.base(); - } - + explicit sized_sentinel() = default; + constexpr explicit sized_sentinel(const It& it) : base_(base(it)) {} + constexpr bool operator==(const It& other) const { return base_ == base(other); } + friend constexpr auto operator-(const sized_sentinel& s, const It& i) { return s.base_ - base(i); } + friend constexpr auto operator-(const It& i, const sized_sentinel& s) { return base(i) - s.base_; } + friend constexpr auto base(const sized_sentinel& s) { return It(s.base_); } private: - I base_ = I(); + decltype(base(std::declval())) base_; }; -template -constexpr auto operator-(sized_sentinel sent, std::input_or_output_iterator auto iter) { - return sent.base() - iter; -} - -template -constexpr auto operator-(std::input_or_output_iterator auto iter, sized_sentinel sent) { - return iter - sent.base(); -} - template class three_way_contiguous_iterator { diff --git a/libcxx/test/support/test_range.h b/libcxx/test/support/test_range.h --- a/libcxx/test/support/test_range.h +++ b/libcxx/test/support/test_range.h @@ -17,24 +17,20 @@ #error "test/support/test_range.h" can only be included in builds supporting ranges #endif -struct sentinel { - bool operator==(std::input_or_output_iterator auto const&) const; -}; - template