[libcxx-commits] [libcxx] 597b90e - [libc++] Fix __simple_view concept in std::ranges

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 14 09:55:38 PST 2022


Author: Hui Xie
Date: 2022-01-14T12:55:34-05:00
New Revision: 597b90ebacafad94082c0010b74bcf2ac1a23b4f

URL: https://github.com/llvm/llvm-project/commit/597b90ebacafad94082c0010b74bcf2ac1a23b4f
DIFF: https://github.com/llvm/llvm-project/commit/597b90ebacafad94082c0010b74bcf2ac1a23b4f.diff

LOG: [libc++] Fix __simple_view concept in std::ranges

Differential Revision: https://reviews.llvm.org/D116808

Added: 
    

Modified: 
    libcxx/include/__ranges/concepts.h
    libcxx/test/libcxx/ranges/range.utility.helpers/simple_view.compile.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.take/begin.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h
index fa31074ab6581..a9cb15f9f17ce 100644
--- a/libcxx/include/__ranges/concepts.h
+++ b/libcxx/include/__ranges/concepts.h
@@ -83,11 +83,11 @@ namespace ranges {
     movable<_Tp> &&
     enable_view<_Tp>;
 
-  template<class _Range>
+  template <class _Range>
   concept __simple_view =
     view<_Range> && range<const _Range> &&
     same_as<iterator_t<_Range>, iterator_t<const _Range>> &&
-    same_as<sentinel_t<_Range>, iterator_t<const _Range>>;
+    same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
 
   // [range.refinements], other range refinements
   template <class _Rp, class _Tp>

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
index 7aef1bab92a56..fd7427f25900d 100644
--- 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 @@ struct DifferentSentinel : std::ranges::view_base {
   sentinel_wrapper<int*> end() const;
 };
 
+struct WrongConstSentinel : std::ranges::view_base {
+  int *begin() const;
+  sentinel_wrapper<int*> end();
+  sentinel_wrapper<const int*> end() const;
+};
+
 static_assert( std::ranges::__simple_view<SimpleView>);
 static_assert(!std::ranges::__simple_view<WrongConstView>);
 static_assert(!std::ranges::__simple_view<NoConstView>);
-static_assert(!std::ranges::__simple_view<DifferentSentinel>);
+static_assert( std::ranges::__simple_view<DifferentSentinel>);
+static_assert(!std::ranges::__simple_view<WrongConstSentinel>);

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
index ca19ef2ba8023..2455eeeb47f38 100644
--- 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,32 @@
 #include <ranges>
 
 #include "test_macros.h"
+#include "test_iterators.h"
 #include "types.h"
 
 template<class T>
 concept BeginInvocable = requires(std::ranges::drop_view<T> t) { t.begin(); };
 
+template <bool IsSimple>
+struct MaybeSimpleView : std::ranges::view_base {
+  int* num_of_non_const_begin_calls;
+  int* num_of_const_begin_calls;
+
+  constexpr int* begin() {
+    ++(*num_of_non_const_begin_calls);
+    return nullptr;
+  }
+  constexpr std::conditional_t<IsSimple, int*, const int*> begin() const {
+    ++(*num_of_const_begin_calls);
+    return nullptr;
+  }
+  constexpr int* end() const { return nullptr; }
+  constexpr size_t size() const { return 0; }
+};
+
+using SimpleView = MaybeSimpleView<true>;
+using NonSimpleView = MaybeSimpleView<false>;
+
 constexpr bool test() {
   // random_access_range<const V> && sized_range<const V>
   std::ranges::drop_view dropView1(MoveOnlyView(), 4);
@@ -62,6 +83,36 @@ constexpr bool test() {
 
   static_assert(!BeginInvocable<const ForwardView>);
 
+  {
+    static_assert(std::ranges::random_access_range<const SimpleView>);
+    static_assert(std::ranges::sized_range<const SimpleView>);
+    LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleView>);
+    int non_const_calls = 0;
+    int const_calls = 0;
+    std::ranges::drop_view dropView(SimpleView{{}, &non_const_calls, &const_calls}, 4);
+    assert(dropView.begin() == nullptr);
+    assert(non_const_calls == 0);
+    assert(const_calls == 1);
+    assert(std::as_const(dropView).begin() == nullptr);
+    assert(non_const_calls == 0);
+    assert(const_calls == 2);
+  }
+
+  {
+    static_assert(std::ranges::random_access_range<const NonSimpleView>);
+    static_assert(std::ranges::sized_range<const NonSimpleView>);
+    LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleView>);
+    int non_const_calls = 0;
+    int const_calls = 0;
+    std::ranges::drop_view dropView(NonSimpleView{{}, &non_const_calls, &const_calls}, 4);
+    assert(dropView.begin() == nullptr);
+    assert(non_const_calls == 1);
+    assert(const_calls == 0);
+    assert(std::as_const(dropView).begin() == nullptr);
+    assert(non_const_calls == 1);
+    assert(const_calls == 1);
+  }
+
   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
index 2441f6787f2ba..25785644b10a2 100644
--- 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,17 @@
 #include "test_macros.h"
 #include "types.h"
 
+struct NonSimpleParentView : std::ranges::view_base {
+  ChildView* begin() { return nullptr; }
+  const ChildView* begin() const;
+  const ChildView* end() const;
+};
+
+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 +97,20 @@ constexpr bool test() {
     assert(*jv.begin() == 1111);
   }
 
+  // !simple-view<V>
+  {
+    std::ranges::join_view<NonSimpleParentView> jv;
+    static_assert(!std::same_as<decltype(jv.begin()),
+                                decltype(std::as_const(jv).begin())>);
+  }
+
+  // simple-view<V> && is_reference_v<range_reference_t<V>>;
+  {
+    std::ranges::join_view<SimpleParentView> jv;
+    static_assert(std::same_as<decltype(jv.begin()),
+                               decltype(std::as_const(jv).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
index 056817f1e7f45..909212841e44d 100644
--- 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<int*> end() const;
+  size_t size() { return 0; }  // deliberately non-const
+};
+static_assert(std::ranges::sized_range<NonCommonSimpleView>);
+static_assert(!std::ranges::sized_range<const NonCommonSimpleView>);
+
 constexpr bool test() {
   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
 
@@ -63,6 +71,13 @@ constexpr bool test() {
     ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<int*>);
   }
 
+  // __simple_view<V> && sized_range<V> && !size_range<!V>
+  {
+    std::ranges::take_view<NonCommonSimpleView> tv{};
+    ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<int*>);
+    ASSERT_SAME_TYPE(decltype(std::as_const(tv).begin()), std::counted_iterator<int*>);
+  }
+
   return true;
 }
 


        


More information about the libcxx-commits mailing list