diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -80,11 +80,11 @@ movable<_Tp> && enable_view<_Tp>; - template + template concept __simple_view = view<_Range> && range && same_as, iterator_t> && - same_as, iterator_t>; + same_as, sentinel_t>; // [range.refinements], other range refinements template 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 @@ -39,7 +39,14 @@ sentinel_wrapper end() const; }; +struct WrongConstSentinel : std::ranges::view_base { + int *begin() const; + sentinel_wrapper end(); + sentinel_wrapper end() const; +}; + static_assert( std::ranges::__simple_view); static_assert(!std::ranges::__simple_view); static_assert(!std::ranges::__simple_view); -static_assert(!std::ranges::__simple_view); +static_assert( std::ranges::__simple_view); +static_assert(!std::ranges::__simple_view); diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp @@ -19,11 +19,31 @@ #include #include "test_macros.h" +#include "test_iterators.h" #include "types.h" template concept BeginInvocable = requires(std::ranges::drop_view t) { t.begin(); }; +struct SimpleView : std::ranges::view_base { + bool non_const_begin_called{false}; + constexpr int* begin() { + non_const_begin_called = true; + return nullptr; + } + constexpr int* begin() const { return nullptr; } + constexpr int* end() const { return nullptr; } + constexpr std::size_t size() const { return 0u; } +}; + +struct NonSimpleView : std::ranges::view_base { + int* begin(); + const int* begin() const; + int* end(); + const int* end() const; + std::size_t size() const; +}; + constexpr bool test() { // random_access_range && sized_range std::ranges::drop_view dropView1(MoveOnlyView(), 4); @@ -62,6 +82,20 @@ static_assert(!BeginInvocable); + // simple_view && random_access_range && sized_range + { + std::ranges::drop_view dropView(SimpleView{}, 4); + dropView.begin(); + assert(!dropView.base().non_const_begin_called); + } + + // !simple_view && random_access_range && sized_range + { + using DropView = std::ranges::drop_view; + static_assert(std::same_as().begin()), int*>); + static_assert(std::same_as().begin()), const int*>); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp @@ -19,6 +19,11 @@ #include "test_macros.h" #include "types.h" +struct SimpleParentView : std::ranges::view_base { + const ChildView* begin() const; + const ChildView* end() const; +}; + constexpr bool test() { int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}}; @@ -86,6 +91,20 @@ assert(*jv.begin() == 1111); } + // !simple-view + { + using WithNonSimpleBase = std::ranges::join_view>; + static_assert(!std::same_as().begin()), + decltype(std::declval().begin())>); + } + + // simple-view && is_reference_v>; + { + using WithSimpleBase = std::ranges::join_view; + static_assert(std::same_as().begin()), + decltype(std::declval().begin())>); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp @@ -21,6 +21,14 @@ #include "test_range.h" #include "types.h" +struct NonCommonSimpleView : std::ranges::view_base { + int* begin() const; + sentinel_wrapper end() const; + + // non const so that size_range is false + size_t size(); +}; + constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; @@ -63,6 +71,14 @@ ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator); } + // __simple_view && sized_range && !size_range + { + using TakeNonSimpleView = std::ranges::take_view; + ASSERT_SAME_TYPE(decltype(std::declval().begin()), std::counted_iterator); + // the optimal result should be int* but according to the c++20 standard, + // it returns std::counted_iterator + } + return true; }