[libcxx][ranges] Add `random_access_{iterator,range}`.
authorzoecarver <z.zoelec2@gmail.com>
Sat, 24 Apr 2021 00:11:44 +0000 (17:11 -0700)
committerzoecarver <z.zoelec2@gmail.com>
Wed, 5 May 2021 04:42:55 +0000 (21:42 -0700)
Differential Revision: https://reviews.llvm.org/D101316

35 files changed:
libcxx/include/__iterator/concepts.h
libcxx/include/__ranges/concepts.h
libcxx/include/iterator
libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.random.access/subsumption.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.bidir/subsumption.compile.pass.cpp
libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/ranges/range.refinements/random_access_range.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/ranges/range.refinements/subsumption.compile.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/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp
libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp

index c83fd92..0dd8a72 100644 (file)
@@ -137,7 +137,22 @@ concept bidirectional_iterator =
     { __i-- } -> same_as<_Ip>;
   };
 
-  // clang-format on
+template<class _Ip>
+concept random_access_iterator =
+  bidirectional_iterator<_Ip> &&
+  derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> &&
+  totally_ordered<_Ip> &&
+  sized_sentinel_for<_Ip, _Ip> &&
+  requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) {
+    { __i += __n } -> same_as<_Ip&>;
+    { __j +  __n } -> same_as<_Ip>;
+    { __n +  __j } -> same_as<_Ip>;
+    { __i -= __n } -> same_as<_Ip&>;
+    { __j -  __n } -> same_as<_Ip>;
+    {  __j[__n]  } -> same_as<iter_reference_t<_Ip>>;
+  };
+
+// clang-format on
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
 
index 578b153..8c28df3 100644 (file)
@@ -62,6 +62,10 @@ namespace ranges {
 
   template <class _Tp>
   concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp> >;
+
+  template <class _Tp>
+  concept random_access_range =
+      bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp> >;
 } // namespace ranges
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
index 97677fe..ad98d8c 100644 (file)
@@ -87,6 +87,10 @@ template<class I>
 template<class I>
   concept bidirectional_iterator = see below;              // since C++20
 
+// [iterator.concept.random.access], concept random_access_iterator
+template<class I>
+  concept random_access_iterator = see below;              // since C++20
+
 template<class Category, class T, class Distance = ptrdiff_t,
          class Pointer = T*, class Reference = T&>
 struct iterator
diff --git a/libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.random.access/subsumption.compile.pass.cpp b/libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.random.access/subsumption.compile.pass.cpp
new file mode 100644 (file)
index 0000000..4730307
--- /dev/null
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 T>
+// concept random_access_iterator;
+
+#include <iterator>
+
+#include <concepts>
+
+template<std::bidirectional_iterator I>
+requires std::derived_from<std::_ITER_CONCEPT<I>, std::random_access_iterator_tag>
+constexpr bool check_subsumption() {
+  return false;
+}
+
+template<std::random_access_iterator>
+constexpr bool check_subsumption() {
+  return true;
+}
+
+static_assert(check_subsumption<int*>());
index 1f2707a..c74dcfa 100644 (file)
@@ -23,6 +23,7 @@ using const_reverse_iterator = std::map<int, int>::const_reverse_iterator;
 using value_type = std::pair<const int, int>;
 
 static_assert(std::bidirectional_iterator<iterator>);
+static_assert(!std::random_access_iterator<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(!std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index cd2b299..8cf2edc 100644 (file)
@@ -24,8 +24,10 @@ static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
 static_assert(stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
+static_assert(!stdr::random_access_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
 static_assert(stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
+static_assert(!stdr::random_access_range<range const>);
index 1f223d9..21a612a 100644 (file)
@@ -23,6 +23,7 @@ using const_reverse_iterator = std::multimap<int, int>::const_reverse_iterator;
 using value_type = std::pair<const int, int>;
 
 static_assert(std::bidirectional_iterator<iterator>);
+static_assert(!std::random_access_iterator<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(!std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index 46975cd..8113a79 100644 (file)
@@ -24,8 +24,10 @@ static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
 static_assert(stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
+static_assert(!stdr::random_access_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
 static_assert(stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
+static_assert(!stdr::random_access_range<range const>);
index f09efa6..6c89f2d 100644 (file)
@@ -23,6 +23,7 @@ using const_reverse_iterator = std::multiset<int>::const_reverse_iterator;
 using value_type = int;
 
 static_assert(std::bidirectional_iterator<iterator>);
+static_assert(!std::random_access_iterator<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(!std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
index 40db2fe..549b081 100644 (file)
@@ -24,8 +24,10 @@ static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
 static_assert(stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
+static_assert(!stdr::random_access_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
 static_assert(stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
+static_assert(!stdr::random_access_range<range const>);
index 662bf74..f33771f 100644 (file)
@@ -23,6 +23,7 @@ using const_reverse_iterator = std::set<int>::const_reverse_iterator;
 using value_type = int;
 
 static_assert(std::bidirectional_iterator<iterator>);
+static_assert(!std::random_access_iterator<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(!std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index 30bae62..987d46b 100644 (file)
@@ -21,11 +21,15 @@ using range = std::set<int>;
 namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
+static_assert(stdr::bidirectional_range<range>);
+static_assert(!stdr::random_access_range<range>);
 static_assert(stdr::common_range<range>);
 static_assert(stdr::input_range<range>);
 static_assert(!stdr::view<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
+static_assert(stdr::bidirectional_range<range const>);
+static_assert(!stdr::random_access_range<range const>);
 static_assert(stdr::common_range<range const>);
 static_assert(stdr::input_range<range>);
 static_assert(!stdr::view<range const>);
index 2816cd2..3010bd3 100644 (file)
@@ -21,7 +21,7 @@ using const_iterator = std::array<int, 10>::const_iterator;
 using reverse_iterator = std::array<int, 10>::reverse_iterator;
 using const_reverse_iterator = std::array<int, 10>::const_reverse_iterator;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -32,7 +32,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
-static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, int>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index 7794dfe..e62c086 100644 (file)
 using range = std::array<int, 10>;
 namespace stdr = std::ranges;
 
+static_assert(!stdr::view<range>);
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
-static_assert(stdr::bidirectional_range<range>);
-static_assert(!stdr::view<range>);
+static_assert(stdr::random_access_range<range>);
+
 
+static_assert(!stdr::view<range const>);
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
-static_assert(stdr::bidirectional_range<range const>);
-static_assert(!stdr::view<range const>);
+static_assert(stdr::random_access_range<range const>);
index f301f4d..7954320 100644 (file)
@@ -22,7 +22,7 @@ using reverse_iterator = std::deque<int>::reverse_iterator;
 using const_reverse_iterator = std::deque<int>::const_reverse_iterator;
 using value_type = int;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -33,7 +33,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
-static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index bece152..22be606 100644 (file)
@@ -22,10 +22,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
-static_assert(stdr::bidirectional_range<range>);
+static_assert(stdr::random_access_range<range>);
 static_assert(!stdr::view<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
-static_assert(stdr::bidirectional_range<range const>);
+static_assert(stdr::random_access_range<range const>);
 static_assert(!stdr::view<range const>);
index 3acaa34..fe3e148 100644 (file)
@@ -23,6 +23,7 @@ using const_reverse_iterator = std::list<int>::const_reverse_iterator;
 using value_type = int;
 
 static_assert(std::bidirectional_iterator<iterator>);
+static_assert(!std::random_access_iterator<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(!std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index 1996609..76b73c7 100644 (file)
@@ -24,8 +24,10 @@ static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
 static_assert(stdr::bidirectional_range<range>);
 static_assert(!stdr::view<range>);
+static_assert(!stdr::random_access_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
 static_assert(stdr::bidirectional_range<range const>);
 static_assert(!stdr::view<range const>);
+static_assert(!stdr::random_access_range<range const>);
index 1fc5f5d..06770fc 100644 (file)
@@ -22,7 +22,8 @@ using reverse_iterator = std::vector<bool>::reverse_iterator;
 using const_reverse_iterator = std::vector<bool>::const_reverse_iterator;
 using value_type = bool;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
+static_assert(std::random_access_iterator<reverse_iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -33,7 +34,8 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
-static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_reverse_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index b6f3268..57200cd 100644 (file)
@@ -22,10 +22,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
-static_assert(stdr::bidirectional_range<range>);
+static_assert(stdr::random_access_range<range>);
 static_assert(!stdr::view<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
-static_assert(stdr::bidirectional_range<range const>);
+static_assert(stdr::random_access_range<range const>);
 static_assert(!stdr::view<range const>);
index c8a7647..148d686 100644 (file)
@@ -22,7 +22,8 @@ using reverse_iterator = std::vector<int>::reverse_iterator;
 using const_reverse_iterator = std::vector<int>::const_reverse_iterator;
 using value_type = int;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
+static_assert(std::random_access_iterator<reverse_iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -33,7 +34,8 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
-static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_reverse_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index 50620b2..ecd1346 100644 (file)
@@ -22,10 +22,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
-static_assert(stdr::bidirectional_range<range>);
+static_assert(stdr::random_access_range<range>);
 static_assert(!stdr::view<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
 static_assert(stdr::common_range<range const>);
-static_assert(stdr::bidirectional_range<range const>);
+static_assert(stdr::random_access_range<range const>);
 static_assert(!stdr::view<range const>);
index d0c4663..b4fa79f 100644 (file)
@@ -22,10 +22,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
-static_assert(stdr::bidirectional_range<range>);
+static_assert(stdr::random_access_range<range>);
 static_assert(!stdr::view<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::iterator>);
 static_assert(stdr::common_range<range const>);
-static_assert(stdr::bidirectional_range<range const>);
+static_assert(stdr::random_access_range<range const>);
 static_assert(!stdr::view<range const>);
index 355ece6..0e147c7 100644 (file)
@@ -20,7 +20,7 @@ using iterator = std::span<int>::iterator;
 using reverse_iterator = std::span<int>::reverse_iterator;
 using value_type = int;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sentinel_for<iterator, reverse_iterator>);
index 31a7070..7868994 100644 (file)
@@ -23,8 +23,10 @@ static_assert(std::same_as<stdr::iterator_t<fs::path>, fs::path::iterator>);
 static_assert(stdr::common_range<fs::path>);
 static_assert(stdr::bidirectional_range<fs::path>);
 static_assert(!stdr::view<fs::path>);
+static_assert(!stdr::random_access_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>);
 static_assert(stdr::bidirectional_range<fs::path const>);
 static_assert(!stdr::view<fs::path const>);
+static_assert(!stdr::random_access_range<fs::path const>);
index b3d0e9c..aefe415 100644 (file)
 #include <concepts>
 
 template<std::forward_iterator I>
-[[nodiscard]] constexpr bool check_subsumption() {
+constexpr bool check_subsumption() {
   return false;
 }
 
 template<std::bidirectional_iterator>
-[[nodiscard]] constexpr bool check_subsumption() {
+constexpr bool check_subsumption() {
   return true;
 }
 
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp
new file mode 100644 (file)
index 0000000..976af9d
--- /dev/null
@@ -0,0 +1,218 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 T>
+// concept random_access_iterator;
+
+#include <iterator>
+
+#include "test_iterators.h"
+#include "test_macros.h"
+
+static_assert(!std::random_access_iterator<cpp17_input_iterator<int*> >);
+static_assert(!std::random_access_iterator<cpp20_input_iterator<int*> >);
+static_assert(!std::random_access_iterator<forward_iterator<int*> >);
+static_assert(!std::random_access_iterator<bidirectional_iterator<int*> >);
+static_assert( std::random_access_iterator<random_access_iterator<int*> >);
+static_assert( std::random_access_iterator<contiguous_iterator<int*> >);
+
+static_assert(std::random_access_iterator<int*>);
+static_assert(std::random_access_iterator<int const*>);
+static_assert(std::random_access_iterator<int volatile*>);
+static_assert(std::random_access_iterator<int const volatile*>);
+
+struct wrong_iterator_category {
+    typedef std::bidirectional_iterator_tag iterator_category;
+    typedef int                             value_type;
+    typedef std::ptrdiff_t                  difference_type;
+    typedef int*                            pointer;
+    typedef int&                            reference;
+    typedef wrong_iterator_category         self;
+
+    reference operator*() const;
+    pointer operator->() const;
+    friend bool operator==(const self&, const self&);
+    friend bool operator< (const self&, const self&);
+    friend bool operator<=(const self&, const self&);
+    friend bool operator> (const self&, const self&);
+    friend bool operator>=(const self&, const self&);
+
+    self& operator++();
+    self operator++(int);
+
+    self& operator--();
+    self operator--(int);
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert(std::bidirectional_iterator<wrong_iterator_category>);
+static_assert(!std::random_access_iterator<wrong_iterator_category>);
+
+template<class Child>
+struct common_base {
+    typedef std::random_access_iterator_tag iterator_category;
+    typedef int                             value_type;
+    typedef std::ptrdiff_t                  difference_type;
+    typedef int*                            pointer;
+    typedef int&                            reference;
+    typedef Child                           self;
+
+    reference operator*() const;
+    pointer operator->() const;
+    friend bool operator==(const self&, const self&);
+    friend bool operator< (const self&, const self&);
+    friend bool operator<=(const self&, const self&);
+    friend bool operator> (const self&, const self&);
+    friend bool operator>=(const self&, const self&);
+
+    self& operator++();
+    self operator++(int);
+
+    self& operator--();
+    self operator--(int);
+};
+
+struct simple_random_access_iterator
+  : common_base<simple_random_access_iterator> {
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert(std::bidirectional_iterator<simple_random_access_iterator>);
+static_assert(std::random_access_iterator<simple_random_access_iterator>);
+
+struct no_plus_equals
+  : common_base<no_plus_equals> {
+
+ /* self& operator+=(difference_type n); */
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert( std::bidirectional_iterator<no_plus_equals>);
+static_assert(!std::random_access_iterator<no_plus_equals>);
+
+struct no_plus_difference_type
+  : common_base<no_plus_difference_type> {
+
+    self& operator+=(difference_type n);
+ /* self operator+(difference_type n) const; */
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert( std::bidirectional_iterator<no_plus_difference_type>);
+static_assert(!std::random_access_iterator<no_plus_difference_type>);
+
+struct difference_type_no_plus
+  : common_base<difference_type_no_plus> {
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+ /* friend self operator+(difference_type n, self x); */
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert( std::bidirectional_iterator<difference_type_no_plus>);
+static_assert(!std::random_access_iterator<difference_type_no_plus>);
+
+struct no_minus_equals
+  : common_base<no_minus_equals> {
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+ /* self& operator-=(difference_type n); */
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert( std::bidirectional_iterator<no_minus_equals>);
+static_assert(!std::random_access_iterator<no_minus_equals>);
+
+struct no_minus
+  : common_base<no_minus> {
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+ /* self operator-(difference_type n) const; */
+    difference_type operator-(const self&) const;
+
+    reference operator[](difference_type n) const;
+};
+static_assert( std::bidirectional_iterator<no_minus>);
+static_assert(!std::random_access_iterator<no_minus>);
+
+struct not_sized_sentinel
+  : common_base<not_sized_sentinel> {
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+ /* difference_type operator-(const self&) const; */
+
+    reference operator[](difference_type n) const;
+};
+static_assert( std::bidirectional_iterator<not_sized_sentinel>);
+static_assert(!std::random_access_iterator<not_sized_sentinel>);
+
+struct no_subscript
+  : common_base<no_subscript> {
+
+    self& operator+=(difference_type n);
+    self operator+(difference_type n) const;
+    friend self operator+(difference_type n, self x);
+
+    self& operator-=(difference_type n);
+    self operator-(difference_type n) const;
+    difference_type operator-(const self&) const;
+
+ /* reference operator[](difference_type n) const; */
+};
+static_assert( std::bidirectional_iterator<no_subscript>);
+static_assert(!std::random_access_iterator<no_subscript>);
index dac2c4d..3165caf 100644 (file)
@@ -28,14 +28,15 @@ template<class I1>
 using reverse_bidirectional_iterator = std::reverse_iterator<bidirectional_iterator<int*>>;
 static_assert(common_reverse_iterator_checks<reverse_bidirectional_iterator>());
 static_assert(std::bidirectional_iterator<reverse_bidirectional_iterator>);
+static_assert(!std::random_access_iterator<reverse_bidirectional_iterator>);
 static_assert(!std::sized_sentinel_for<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
 
 using reverse_random_access_iterator = std::reverse_iterator<random_access_iterator<int*>>;
 static_assert(common_reverse_iterator_checks<reverse_random_access_iterator>());
-static_assert(std::bidirectional_iterator<reverse_random_access_iterator>);
+static_assert(std::random_access_iterator<reverse_random_access_iterator>);
 static_assert(std::sized_sentinel_for<reverse_random_access_iterator, reverse_random_access_iterator>);
 
 using reverse_contiguous_iterator = std::reverse_iterator<contiguous_iterator<int*>>;
 static_assert(common_reverse_iterator_checks<reverse_contiguous_iterator>());
-static_assert(std::bidirectional_iterator<reverse_contiguous_iterator>);
+static_assert(std::random_access_iterator<reverse_contiguous_iterator>);
 static_assert(std::sized_sentinel_for<reverse_contiguous_iterator, reverse_contiguous_iterator>);
diff --git a/libcxx/test/std/ranges/range.refinements/random_access_range.compile.pass.cpp b/libcxx/test/std/ranges/range.refinements/random_access_range.compile.pass.cpp
new file mode 100644 (file)
index 0000000..5a28207
--- /dev/null
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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<range _Rp>
+// concept random_access_range;
+
+#include <ranges>
+
+#include "test_range.h"
+#include "test_iterators.h"
+
+namespace ranges = std::ranges;
+
+template <template <class...> class I>
+constexpr bool check_range() {
+  constexpr bool result = ranges::random_access_range<test_range<I> >;
+  static_assert(ranges::random_access_range<test_range<I> const> == result);
+  static_assert(ranges::random_access_range<test_non_const_common_range<I> > == result);
+  static_assert(ranges::random_access_range<test_non_const_range<I> > == result);
+  static_assert(ranges::random_access_range<test_common_range<I> > == result);
+  static_assert(ranges::random_access_range<test_common_range<I> const> == result);
+  static_assert(!ranges::random_access_range<test_non_const_common_range<I> const>);
+  static_assert(!ranges::random_access_range<test_non_const_range<I> const>);
+  return result;
+}
+
+static_assert(!check_range<cpp20_input_iterator>());
+static_assert(!check_range<forward_iterator>());
+static_assert(!check_range<bidirectional_iterator>());
+static_assert(check_range<random_access_iterator>());
+static_assert(check_range<contiguous_iterator>());
index c0896e0..4b33d00 100644 (file)
@@ -71,3 +71,17 @@ requires true
 // clang-format on
 
 static_assert(check_bidirectional_range_subsumption<range>());
+
+template<std::ranges::bidirectional_range R>
+requires std::random_access_iterator<std::ranges::iterator_t<R> >
+constexpr bool check_random_access_range_subsumption() {
+  return false;
+}
+
+template<std::ranges::random_access_range>
+requires true
+constexpr bool check_random_access_range_subsumption() {
+  return true;
+}
+
+static_assert(check_random_access_range_subsumption<range>());
index 044acfc..764d79b 100644 (file)
@@ -21,10 +21,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<std::cmatch>, std::cmatch::iterator>);
 static_assert(stdr::common_range<std::cmatch>);
-static_assert(stdr::bidirectional_range<std::cmatch>);
+static_assert(stdr::random_access_range<std::cmatch>);
 static_assert(!stdr::view<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>);
-static_assert(stdr::bidirectional_range<std::cmatch const>);
+static_assert(stdr::random_access_range<std::cmatch const>);
 static_assert(!stdr::view<std::cmatch const>);
index 46b26bc..7d926ac 100644 (file)
@@ -21,10 +21,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<std::string>, std::string::iterator>);
 static_assert(stdr::common_range<std::string>);
-static_assert(stdr::bidirectional_range<std::string>);
+static_assert(stdr::random_access_range<std::string>);
 static_assert(!stdr::view<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>);
-static_assert(stdr::bidirectional_range<std::string const>);
+static_assert(stdr::random_access_range<std::string const>);
 static_assert(!stdr::view<std::string const>);
index 5aa1b60..7cf6015 100644 (file)
@@ -22,7 +22,7 @@ using reverse_iterator = std::string::reverse_iterator;
 using const_reverse_iterator = std::string::const_reverse_iterator;
 using value_type = char;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -33,7 +33,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
-static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
index 8f9da5a..b30f6b4 100644 (file)
@@ -21,10 +21,10 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<std::string_view>, std::string_view::iterator>);
 static_assert(stdr::common_range<std::string_view>);
-static_assert(stdr::bidirectional_range<std::string_view>);
+static_assert(stdr::random_access_range<std::string_view>);
 static_assert(!stdr::view<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>);
-static_assert(stdr::bidirectional_range<std::string_view const>);
+static_assert(stdr::random_access_range<std::string_view const>);
 static_assert(!stdr::view<std::string_view const>);
index f86f491..cd6b379 100644 (file)
@@ -21,7 +21,7 @@ using const_iterator = std::string_view::const_iterator;
 using reverse_iterator = std::string_view::reverse_iterator;
 using const_reverse_iterator = std::string_view::const_reverse_iterator;
 
-static_assert(std::bidirectional_iterator<iterator>);
+static_assert(std::random_access_iterator<iterator>);
 static_assert(!std::indirectly_writable<iterator, char>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
@@ -32,7 +32,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
 
-static_assert(std::bidirectional_iterator<const_iterator>);
+static_assert(std::random_access_iterator<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, char>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);