[libcxx-commits] [libcxx] 3001b48 - [libc++] Implement views::all_t and ranges::viewable_range

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 15 04:54:44 PDT 2021


Author: Louis Dionne
Date: 2021-07-15T07:54:33-04:00
New Revision: 3001b48d76bcf10063286efc722a8479522f4c50

URL: https://github.com/llvm/llvm-project/commit/3001b48d76bcf10063286efc722a8479522f4c50
DIFF: https://github.com/llvm/llvm-project/commit/3001b48d76bcf10063286efc722a8479522f4c50.diff

LOG: [libc++] Implement views::all_t and ranges::viewable_range

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

Added: 
    libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp
    libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp

Modified: 
    libcxx/docs/Status/RangesPaper.csv
    libcxx/include/__ranges/all.h
    libcxx/include/__ranges/concepts.h
    libcxx/include/__ranges/drop_view.h
    libcxx/include/__ranges/transform_view.h
    libcxx/include/ranges
    libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp
    libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp
    libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp

Removed: 
    libcxx/test/std/ranges/range.adaptors/range.all.pass.cpp


################################################################################
diff  --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv
index 29c38f3540c3..4ee8d0d74b1d 100644
--- a/libcxx/docs/Status/RangesPaper.csv
+++ b/libcxx/docs/Status/RangesPaper.csv
@@ -119,8 +119,8 @@ Section,Description,Dependencies,Assignee,Complete
 | `ranges::bidirectional_range <https://llvm.org/D100278>`_
 | `ranges::random_access_range <https://llvm.org/D101316>`_
 | ranges::contiguous_range
-| `ranges::common_range <https://llvm.org/D100269>`_
-| ranges::viewable_range",[range.range],Christopher Di Bella,In progress
+| `ranges::common_range <https://llvm.org/D100269>`_",[range.range],Christopher Di Bella,✅
+`[range.refinements]`_,`ranges::viewable_range <https://reviews.llvm.org/D105816>`_,[range.range],Louis Dionne,✅
 `[range.utility.helpers] <http://wg21.link/range.utility.helpers>`_,"| *simple-view*
 | *has-arrow*
 | *not-same-as*","| [range.range]

diff  --git a/libcxx/include/__ranges/all.h b/libcxx/include/__ranges/all.h
index d1312d1a213d..6cfe3b8358ec 100644
--- a/libcxx/include/__ranges/all.h
+++ b/libcxx/include/__ranges/all.h
@@ -17,6 +17,7 @@
 #include <__ranges/ref_view.h>
 #include <__ranges/subrange.h>
 #include <__utility/__decay_copy.h>
+#include <__utility/declval.h>
 #include <__utility/forward.h>
 #include <type_traits>
 
@@ -68,6 +69,9 @@ inline namespace __cpo {
   inline constexpr auto all = __all::__fn{};
 } // namespace __cpo
 
+template<ranges::viewable_range _Range>
+using all_t = decltype(views::all(declval<_Range>()));
+
 } // namespace views
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)

diff  --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h
index 364275da813b..f314685e3dc9 100644
--- a/libcxx/include/__ranges/concepts.h
+++ b/libcxx/include/__ranges/concepts.h
@@ -112,6 +112,13 @@ namespace ranges {
 
   template <class _Tp>
   concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp> >;
+
+  template<class _Tp>
+  concept viewable_range =
+    range<_Tp> && (
+      (view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) ||
+      (!view<remove_cvref_t<_Tp>> && borrowed_range<_Tp>)
+    );
 } // namespace ranges
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)

diff  --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h
index 38c101a8fb56..fe5b80330e25 100644
--- a/libcxx/include/__ranges/drop_view.h
+++ b/libcxx/include/__ranges/drop_view.h
@@ -140,9 +140,7 @@ namespace ranges {
   };
 
   template<class _Range>
-  drop_view(_Range&&, range_
diff erence_t<_Range>)
-  // TODO: this is just recreating all_t.
-    -> drop_view<decltype(views::all(std::declval<_Range>()))>;
+  drop_view(_Range&&, range_
diff erence_t<_Range>) -> drop_view<views::all_t<_Range>>;
 
   template<class _Tp>
   inline constexpr bool enable_borrowed_range<drop_view<_Tp>> = enable_borrowed_range<_Tp>;

diff  --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
index e059cbf3b18c..b86cdd3e94d4 100644
--- a/libcxx/include/__ranges/transform_view.h
+++ b/libcxx/include/__ranges/transform_view.h
@@ -10,10 +10,11 @@
 #define _LIBCPP___RANGES_TRANSFORM_VIEW_H
 
 #include <__config>
-#include <__iterator/iterator_traits.h>
 #include <__iterator/concepts.h>
 #include <__iterator/iter_swap.h>
+#include <__iterator/iterator_traits.h>
 #include <__ranges/access.h>
+#include <__ranges/all.h>
 #include <__ranges/concepts.h>
 #include <__ranges/copyable_box.h>
 #include <__ranges/empty.h>
@@ -93,10 +94,8 @@ class transform_view : public view_interface<transform_view<_View, _Fn>> {
   constexpr auto size() const requires sized_range<const _View> { return ranges::size(__base_); }
 };
 
-// TODO: replace the decltype with all_t when that's implemented.
 template<class _Range, class _Fn>
-transform_view(_Range&&, _Fn)
-  -> transform_view<decltype(views::all(std::declval<_Range>())), _Fn>;
+transform_view(_Range&&, _Fn) -> transform_view<views::all_t<_Range>, _Fn>;
 
 template<class _View>
 struct __transform_view_iterator_concept { using type = input_iterator_tag; };

diff  --git a/libcxx/include/ranges b/libcxx/include/ranges
index 90711cb7d05c..d662e2604e98 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -50,7 +50,7 @@ namespace std::ranges {
   template<range R>
     using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
 
-  // [range.sized]
+  // [range.sized], sized ranges
   template<class>
     inline constexpr bool disable_sized_range = false;
 
@@ -85,6 +85,9 @@ namespace std::ranges {
   template <class _Tp>
     concept common_range = see below;
 
+  template<class T>
+  concept viewable_range = see below;
+
   // [view.interface], class template view_interface
   template<class D>
     requires is_class_v<D> && same_as<D, remove_cv_t<D>>
@@ -95,6 +98,21 @@ namespace std::ranges {
     requires is_object_v<T>
   class empty_view;
 
+  // [range.all], all view
+  namespace views {
+    inline constexpr unspecified all = unspecified;
+
+    template<viewable_range R>
+      using all_t = decltype(all(declval<R>()));
+  }
+
+  template<range R>
+    requires is_object_v<R>
+  class ref_view;
+
+  template<class T>
+    inline constexpr bool enable_borrowed_range<ref_view<T>> = true;
+
   // [range.drop], drop view
   template<view V>
     class drop_view;

diff  --git a/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp
index 0b3204c9d775..b098f05e2764 100644
--- a/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::view<range>);
 static_assert(!stdr::random_access_range<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::view<range const>);
 static_assert(!stdr::random_access_range<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp
index 9b0b9fc995ca..9362e25faf40 100644
--- a/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::view<range>);
 static_assert(!stdr::random_access_range<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::view<range const>);
 static_assert(!stdr::random_access_range<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp
index f95952c8bba6..417e19dc0c4d 100644
--- a/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::view<range>);
 static_assert(!stdr::random_access_range<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::view<range const>);
 static_assert(!stdr::random_access_range<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp
index a2150558e016..caf6ba28ff68 100644
--- a/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp
@@ -28,6 +28,7 @@ static_assert(stdr::input_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::bidirectional_range<range const>);
@@ -37,3 +38,4 @@ static_assert(stdr::input_range<range>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp
index f70af72c9bd3..cfe01e7f745a 100644
--- a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(stdr::random_access_range<range>);
 static_assert(stdr::contiguous_range<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(!stdr::view<range const>);
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
@@ -35,3 +36,4 @@ static_assert(stdr::random_access_range<range const>);
 static_assert(stdr::contiguous_range<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp
index 7b248e9846ed..df9f6e8cae3f 100644
--- a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::contiguous_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::contiguous_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp
index af237700f943..142dc96c0a94 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(!stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(!stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp
index bbe6020603e6..75c6d34fa756 100644
--- a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::view<range>);
 static_assert(!stdr::random_access_range<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::view<range const>);
 static_assert(!stdr::random_access_range<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp
index 9981d65fd80d..fb028d0b3931 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::contiguous_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::contiguous_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp
index 117c36b6e1a6..c47413ec262e 100644
--- a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(stdr::contiguous_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(stdr::contiguous_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp
index 450705c3417c..71a72212f59c 100644
--- a/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp
index c98d7b85c4e7..e18627241df8 100644
--- a/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp
index 64332c422ba7..29789d05210d 100644
--- a/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp
index 922ca43e1242..bd48bbab3d21 100644
--- a/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp
index 50fdc6a09119..c850c50976e9 100644
--- a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp
@@ -27,6 +27,7 @@ static_assert(stdr::contiguous_range<range>);
 static_assert(stdr::view<range> && stdr::enable_view<range>);
 static_assert(stdr::sized_range<range>);
 static_assert(stdr::borrowed_range<range>);
+static_assert(stdr::viewable_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::iterator>);
 static_assert(stdr::common_range<range const>);
@@ -35,3 +36,4 @@ static_assert(stdr::contiguous_range<range const>);
 static_assert(!stdr::view<range const> && !stdr::enable_view<range const>);
 static_assert(stdr::sized_range<range const>);
 static_assert(stdr::borrowed_range<range const>);
+static_assert(stdr::viewable_range<range const>);

diff  --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp
index 80445f28e25c..ff79c8bd699e 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp
@@ -26,6 +26,7 @@ static_assert(stdr::input_range<fs::directory_iterator>);
 static_assert(!stdr::view<fs::directory_iterator>);
 static_assert(!stdr::sized_range<fs::directory_iterator>);
 static_assert(!stdr::borrowed_range<fs::directory_iterator>);
+static_assert(!stdr::viewable_range<fs::directory_iterator>);
 
 static_assert(std::same_as<stdr::iterator_t<fs::directory_iterator const>, fs::directory_iterator>);
 static_assert(stdr::common_range<fs::directory_iterator const>);
@@ -33,6 +34,7 @@ static_assert(stdr::input_range<fs::directory_iterator const>);
 static_assert(!stdr::view<fs::directory_iterator const>);
 static_assert(!stdr::sized_range<fs::directory_iterator const>);
 static_assert(!stdr::borrowed_range<fs::directory_iterator const>);
+static_assert(!stdr::viewable_range<fs::directory_iterator const>);
 
 static_assert(std::same_as<stdr::iterator_t<fs::recursive_directory_iterator>, fs::recursive_directory_iterator>);
 static_assert(stdr::common_range<fs::recursive_directory_iterator>);
@@ -40,6 +42,7 @@ static_assert(stdr::input_range<fs::recursive_directory_iterator>);
 static_assert(!stdr::view<fs::recursive_directory_iterator>);
 static_assert(!stdr::sized_range<fs::recursive_directory_iterator>);
 static_assert(!stdr::borrowed_range<fs::recursive_directory_iterator>);
+static_assert(!stdr::viewable_range<fs::recursive_directory_iterator>);
 
 static_assert(std::same_as<stdr::iterator_t<fs::recursive_directory_iterator const>, fs::recursive_directory_iterator>);
 static_assert(stdr::common_range<fs::recursive_directory_iterator const>);
@@ -47,3 +50,4 @@ static_assert(stdr::input_range<fs::recursive_directory_iterator const>);
 static_assert(!stdr::view<fs::recursive_directory_iterator const>);
 static_assert(!stdr::sized_range<fs::recursive_directory_iterator const>);
 static_assert(!stdr::borrowed_range<fs::recursive_directory_iterator const>);
+static_assert(!stdr::viewable_range<fs::recursive_directory_iterator const>);

diff  --git a/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp
index 47cec87ffac6..b9b70d0725f7 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp
@@ -26,6 +26,7 @@ static_assert(!stdr::view<fs::path>);
 static_assert(!stdr::random_access_range<fs::path>);
 static_assert(!stdr::sized_range<fs::path>);
 static_assert(!stdr::borrowed_range<fs::path>);
+static_assert(!stdr::viewable_range<fs::path>);
 
 static_assert(std::same_as<stdr::iterator_t<fs::path const>, fs::path::const_iterator>);
 static_assert(stdr::common_range<fs::path const>);
@@ -34,3 +35,4 @@ static_assert(!stdr::view<fs::path const>);
 static_assert(!stdr::random_access_range<fs::path const>);
 static_assert(!stdr::sized_range<fs::path const>);
 static_assert(!stdr::borrowed_range<fs::path const>);
+static_assert(!stdr::viewable_range<fs::path const>);

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.all.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp
similarity index 100%
rename from libcxx/test/std/ranges/range.adaptors/range.all.pass.cpp
rename to libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp

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
new file mode 100644
index 000000000000..5aaf03c5a2b4
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<viewable_range R>
+// using all_t = decltype(views::all(declval<R>()));
+
+#include <ranges>
+
+#include "test_iterators.h"
+#include "test_range.h"
+
+struct View : test_range<cpp20_input_iterator>, std::ranges::view_base { };
+struct Range : test_range<cpp20_input_iterator> { };
+struct BorrowableRange : test_range<forward_iterator> { };
+template<>
+inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true;
+
+// When T is a view, returns decay-copy(T)
+ASSERT_SAME_TYPE(std::views::all_t<View>, View);
+ASSERT_SAME_TYPE(std::views::all_t<View&>, View);
+ASSERT_SAME_TYPE(std::views::all_t<View const>, View);
+ASSERT_SAME_TYPE(std::views::all_t<View const&>, View);
+
+// Otherwise, when T is a reference to a range, returns ref_view<T>
+ASSERT_SAME_TYPE(std::views::all_t<Range&>, std::ranges::ref_view<Range>);
+ASSERT_SAME_TYPE(std::views::all_t<Range const&>, std::ranges::ref_view<Range const>);
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange&>, std::ranges::ref_view<BorrowableRange>);
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange const&>, std::ranges::ref_view<BorrowableRange const>);
+
+// Otherwise, returns subrange<iterator_t<T>, sentinel_t<R>>
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange>, std::ranges::subrange<forward_iterator<int*>, sentinel>);
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange const>, std::ranges::subrange<forward_iterator<int const*>, sentinel>);

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp
index 5baf128e8800..9278bd086093 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp
@@ -10,7 +10,9 @@
 // UNSUPPORTED: libcpp-no-concepts
 // UNSUPPORTED: gcc-10
 
-// std::ranges::ref_view
+// template<range R>
+//  requires is_object_v<R>
+// class ref_view;
 
 #include <ranges>
 

diff  --git a/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp
new file mode 100644
index 000000000000..3cef347a98c2
--- /dev/null
+++ b/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp
@@ -0,0 +1,133 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class R>
+// concept viewable_range;
+
+#include <ranges>
+#include <type_traits>
+
+#include "test_iterators.h"
+#include "test_range.h"
+
+// The constraints we have in viewable_range are:
+//  range<T>
+//  view<remove_cvref_t<T>>
+//  constructible_from<remove_cvref_t<T>, T>
+//  borrowed_range<T>
+//
+// We test all the relevant combinations of satisfying/not satisfying those constraints.
+
+// viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, borrowed_range=*)
+struct T1 { };
+static_assert(!std::ranges::range<T1>);
+
+static_assert(!std::ranges::viewable_range<T1>);
+static_assert(!std::ranges::viewable_range<T1&>);
+static_assert(!std::ranges::viewable_range<T1 const>);
+static_assert(!std::ranges::viewable_range<T1 const&>);
+
+// viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=true)
+struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base {
+  T2(T2 const&) = default;
+};
+template<> constexpr bool std::ranges::enable_borrowed_range<T2> = true;
+static_assert(std::ranges::range<T2>);
+static_assert(std::ranges::view<T2>);
+static_assert(std::constructible_from<T2, T2>);
+static_assert(std::ranges::borrowed_range<T2>);
+
+static_assert(std::ranges::viewable_range<T2>);
+static_assert(std::ranges::viewable_range<T2&>);
+static_assert(std::ranges::viewable_range<T2 const>);
+static_assert(std::ranges::viewable_range<T2 const&>);
+
+// viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=false)
+struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base {
+  T3(T3 const&) = default;
+};
+template<> constexpr bool std::ranges::enable_borrowed_range<T3> = false;
+static_assert(std::ranges::range<T3>);
+static_assert(std::ranges::view<T3>);
+static_assert(std::constructible_from<T3, T3>);
+static_assert(!std::ranges::borrowed_range<T3>);
+
+static_assert(std::ranges::viewable_range<T3>);
+static_assert(std::ranges::viewable_range<T3&>);
+static_assert(std::ranges::viewable_range<T3 const>);
+static_assert(std::ranges::viewable_range<T3 const&>);
+
+// viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, borrowed_range=true)
+struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base {
+  T4(T4 const&) = delete;
+  T4(T4&&) = default;             // necessary to model view
+  T4& operator=(T4&&) = default;  // necessary to model view
+};
+static_assert(std::ranges::range<T4 const&>);
+static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>);
+static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>);
+static_assert(std::ranges::borrowed_range<T4 const&>);
+
+static_assert(!std::ranges::viewable_range<T4 const&>);
+
+// A type that satisfies (range=true, view=true, constructible_from=false, borrowed_range=false) can't be formed
+
+// viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true)
+struct T5 : test_range<cpp20_input_iterator> { };
+template<> constexpr bool std::ranges::enable_borrowed_range<T5> = true;
+static_assert(std::ranges::range<T5>);
+static_assert(!std::ranges::view<T5>);
+static_assert(std::constructible_from<T5, T5>);
+static_assert(std::ranges::borrowed_range<T5>);
+
+static_assert(std::ranges::viewable_range<T5>);
+
+// viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false)
+struct T6 : test_range<cpp20_input_iterator> { };
+template<> constexpr bool std::ranges::enable_borrowed_range<T6> = false;
+static_assert(std::ranges::range<T6>);
+static_assert(!std::ranges::view<T6>);
+static_assert(std::constructible_from<T6, T6>);
+static_assert(!std::ranges::borrowed_range<T6>);
+
+static_assert(!std::ranges::viewable_range<T6>);
+
+// viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true)
+struct T7 : test_range<cpp20_input_iterator> {
+  T7(T7 const&) = delete;
+};
+static_assert(std::ranges::range<T7&>);
+static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>);
+static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>);
+static_assert(std::ranges::borrowed_range<T7&>);
+
+static_assert(std::ranges::viewable_range<T7&>);
+
+// A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed
+struct T8 : test_range<cpp20_input_iterator> {
+  T8(T8 const&) = delete;
+};
+static_assert(std::ranges::range<T8>);
+static_assert(!std::ranges::view<T8>);
+static_assert(!std::constructible_from<T8, T8>);
+static_assert(!std::ranges::borrowed_range<T8>);
+
+static_assert(!std::ranges::viewable_range<T8>);
+
+// Test with a few degenerate types
+static_assert(!std::ranges::viewable_range<void>);
+static_assert(!std::ranges::viewable_range<int>);
+static_assert(!std::ranges::viewable_range<int (*)(char)>);
+static_assert(!std::ranges::viewable_range<int[]>);
+static_assert(!std::ranges::viewable_range<int[10]>);
+static_assert(!std::ranges::viewable_range<int(&)[]>); // unbounded array is not a range
+static_assert( std::ranges::viewable_range<int(&)[10]>);

diff  --git a/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp
index de92ca20a71c..741b1ad0bcbb 100644
--- a/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp
@@ -26,6 +26,7 @@ static_assert(stdr::contiguous_range<std::cmatch>);
 static_assert(!stdr::view<std::cmatch>);
 static_assert(stdr::sized_range<std::cmatch>);
 static_assert(!stdr::borrowed_range<std::cmatch>);
+static_assert(!stdr::viewable_range<std::cmatch>);
 
 static_assert(std::same_as<stdr::iterator_t<std::cmatch const>, std::cmatch::const_iterator>);
 static_assert(stdr::common_range<std::cmatch const>);
@@ -34,3 +35,4 @@ static_assert(stdr::contiguous_range<std::cmatch const>);
 static_assert(!stdr::view<std::cmatch const>);
 static_assert(stdr::sized_range<std::cmatch const>);
 static_assert(!stdr::borrowed_range<std::cmatch const>);
+static_assert(!stdr::viewable_range<std::cmatch const>);

diff  --git a/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp
index 398549696f53..fb1e6765c900 100644
--- a/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp
@@ -26,6 +26,7 @@ static_assert(stdr::contiguous_range<std::string>);
 static_assert(!stdr::view<std::string>);
 static_assert(stdr::sized_range<std::string>);
 static_assert(!stdr::borrowed_range<std::string>);
+static_assert(!stdr::viewable_range<std::string>);
 
 static_assert(std::same_as<stdr::iterator_t<std::string const>, std::string::const_iterator>);
 static_assert(stdr::common_range<std::string const>);
@@ -34,3 +35,4 @@ static_assert(stdr::contiguous_range<std::string const>);
 static_assert(!stdr::view<std::string const>);
 static_assert(stdr::sized_range<std::string const>);
 static_assert(!stdr::borrowed_range<std::string const>);
+static_assert(!stdr::viewable_range<std::string const>);

diff  --git a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp
index 78a803e14f59..860de80eb981 100644
--- a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp
@@ -26,6 +26,7 @@ static_assert(stdr::contiguous_range<std::string_view>);
 static_assert(stdr::view<std::string_view> && stdr::enable_view<std::string_view>);
 static_assert(stdr::sized_range<std::string_view>);
 static_assert(stdr::borrowed_range<std::string_view>);
+static_assert(stdr::viewable_range<std::string_view>);
 
 static_assert(std::same_as<stdr::iterator_t<std::string_view const>, std::string_view::const_iterator>);
 static_assert(stdr::common_range<std::string_view const>);
@@ -34,3 +35,4 @@ static_assert(stdr::contiguous_range<std::string_view const>);
 static_assert(!stdr::view<std::string_view const> && !stdr::enable_view<std::string_view const>);
 static_assert(stdr::sized_range<std::string_view const>);
 static_assert(stdr::borrowed_range<std::string_view const>);
+static_assert(stdr::viewable_range<std::string_view const>);


        


More information about the libcxx-commits mailing list