[libcxx][iterator][ranges] adds `input_iterator` and `input_range`
authorChristopher Di Bella <cjdb@google.com>
Sun, 11 Apr 2021 19:04:52 +0000 (19:04 +0000)
committerChristopher Di Bella <cjdb@google.com>
Fri, 30 Apr 2021 22:49:06 +0000 (22:49 +0000)
Implements parts of:
    * P0896R4 The One Ranges Proposal`

Depends on D100269.

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

61 files changed:
libcxx/include/__iterator/concepts.h
libcxx/include/__ranges/concepts.h
libcxx/include/iterator
libcxx/include/ranges
libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.input/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/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/containers/sequences/forwardlist/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/unord/unord.map/iterator_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/iterator_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/iterator_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/iterator_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/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_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/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/input_iterator.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/ranges/range.refinements/input_range.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/ranges/range.refinements/subsumption.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.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
libcxx/test/support/test_iterators.h
libcxx/test/support/test_macros.h
libcxx/test/support/test_range.h

index 445a88f..df94cf6 100644 (file)
@@ -111,6 +111,14 @@ concept sized_sentinel_for =
     { __i - __s } -> same_as<iter_difference_t<_Ip> >;
   };
 
+// [iterator.concept.input]
+template<class _Ip>
+concept input_iterator =
+  input_or_output_iterator<_Ip> &&
+  indirectly_readable<_Ip> &&
+  requires { typename _ITER_CONCEPT<_Ip>; } &&
+  derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>;
+
 // clang-format on
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
index aeed55c..bccb8f6 100644 (file)
@@ -52,6 +52,9 @@ namespace ranges {
 
   // [range.refinements], other range refinements
   template <class _Tp>
+  concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp> >;
+
+  template <class _Tp>
   concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp> >;
 } // namespace ranges
 
index 5be87e1..d759eae 100644 (file)
@@ -75,6 +75,10 @@ template<class S, class I>
 template<class S, class I>
   concept sized_sentinel_for = see below;
 
+// [iterator.concept.input], concept input_iterator
+template<class I>
+  concept input_iterator = see below;                      // since C++20
+
 template<class Category, class T, class Distance = ptrdiff_t,
          class Pointer = T*, class Reference = T&>
 struct iterator
index a4eda8d..ca9f648 100644 (file)
@@ -48,6 +48,9 @@ namespace std::ranges {
     using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
 
   // [range.refinements], other range refinements
+  template<class T>
+    concept input_range = see below;
+
   template <class _Tp>
     concept common_range = see below;
 }
diff --git a/libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp b/libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp
new file mode 100644 (file)
index 0000000..73520d9
--- /dev/null
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// XFAIL: msvc && clang
+
+// template<class T>
+// concept input_iterator;
+
+#include <iterator>
+
+#include <concepts>
+
+// clang-format off
+template<std::input_or_output_iterator I>
+requires std::indirectly_readable<I> &&
+         std::derived_from<std::_ITER_CONCEPT<I>, std::input_iterator_tag>
+[[nodiscard]] constexpr bool check_subsumption() {
+  return false;
+}
+
+template<std::input_iterator>
+[[nodiscard]] constexpr bool check_subsumption() {
+  return true;
+}
+// clang-format on
+
+static_assert(check_subsumption<int*>());
index c205496..82fd0fd 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 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::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
index 4918db1..e778d81 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index 18b5f79..d020d7d 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 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::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
index 9443d3f..d0c0e38 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index 62f287d..0f86ddf 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 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::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
index ae1745d..c6a2e13 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index f702f3d..bf62926 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 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::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
index 8ba25cb..7e0fdf6 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range>);
index 958864b..58ac42d 100644 (file)
@@ -47,3 +47,4 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index a44354d..f2762d4 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index c40267d..4de9eb9 100644 (file)
@@ -48,3 +48,4 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index 50e94f7..c9bdb9e 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index 88a5d60..c00151f 100644 (file)
@@ -29,6 +29,7 @@ static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
+static_assert(std::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -38,3 +39,4 @@ static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(std::sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index 32bc9fa..c412813 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index d468744..a1c0885 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 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::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -48,3 +49,4 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index b958ce6..f567d2a 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index dc06fff..1c1d95b 100644 (file)
@@ -48,3 +48,4 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index 8127962..7647ab5 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index a0ba9b2..eca4830 100644 (file)
@@ -48,3 +48,4 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index 4c807fe..e384a44 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index 343d296..e694881 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -48,6 +49,7 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
 static_assert(!std::indirectly_writable<local_iterator, value_type>);
@@ -61,6 +63,7 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
@@ -74,3 +77,4 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_local_iterator>);
index c5abbae..acbdcc9 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index c4580f2..d0c61cf 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -48,6 +49,7 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
 static_assert(!std::indirectly_writable<local_iterator, value_type>);
@@ -61,6 +63,7 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
@@ -74,3 +77,4 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_local_iterator>);
index 9de4684..98b6a07 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index 4da0711..c9990e3 100644 (file)
@@ -35,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<iterator, const_local_iterator>);
+static_assert(std::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -48,6 +49,7 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
 static_assert(!std::indirectly_writable<local_iterator, value_type>);
@@ -61,6 +63,7 @@ static_assert(!std::sized_sentinel_for<local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
@@ -74,3 +77,4 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
 static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_local_iterator>);
index 45b7a66..128aa00 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index e731e8b..607f992 100644 (file)
@@ -31,6 +31,7 @@ static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sentinel_for<iterator, const_iterator>);
 static_assert(!std::sentinel_for<iterator, local_iterator>);
 static_assert(!std::sentinel_for<iterator, const_local_iterator>);
+static_assert(std::input_iterator<iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
@@ -38,6 +39,7 @@ static_assert(std::incrementable<const_iterator>);
 static_assert(std::sentinel_for<const_iterator, iterator>);
 static_assert(!std::sentinel_for<const_iterator, local_iterator>);
 static_assert(!std::sentinel_for<const_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
 static_assert(std::incrementable<local_iterator>);
@@ -46,6 +48,7 @@ static_assert(!std::sentinel_for<local_iterator, iterator>);
 static_assert(!std::sentinel_for<local_iterator, const_iterator>);
 static_assert(std::sentinel_for<local_iterator, local_iterator>);
 static_assert(std::sentinel_for<local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
@@ -55,3 +58,4 @@ static_assert(!std::sentinel_for<const_local_iterator, iterator>);
 static_assert(!std::sentinel_for<const_local_iterator, const_iterator>);
 static_assert(std::sentinel_for<const_local_iterator, local_iterator>);
 static_assert(std::sentinel_for<const_local_iterator, const_local_iterator>);
+static_assert(std::input_iterator<const_local_iterator>);
index 4c84bbf..d266fdd 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_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::input_range<range const>);
index 696ee6a..cb26ed6 100644 (file)
@@ -23,6 +23,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
 static_assert(stdr::common_range<range>);
+static_assert(stdr::input_range<range>);
 
 static_assert(std::same_as<stdr::iterator_t<range const>, range::iterator>);
 static_assert(stdr::common_range<range const>);
+static_assert(stdr::input_range<range const>);
index ba500b7..0c6aa7d 100644 (file)
@@ -29,3 +29,4 @@ static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sentinel_for<iterator, reverse_iterator>);
 static_assert(std::sized_sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
+static_assert(std::input_iterator<iterator>);
index af1ce0f..c142915 100644 (file)
@@ -26,6 +26,7 @@ static_assert(!std::incrementable<fs::directory_iterator>);
 static_assert(std::input_or_output_iterator<fs::directory_iterator>);
 static_assert(std::sentinel_for<fs::directory_iterator, fs::directory_iterator>);
 static_assert(!std::sized_sentinel_for<fs::directory_iterator, fs::directory_iterator>);
+static_assert(std::input_iterator<fs::directory_iterator>);
 
 static_assert(std::indirectly_readable<fs::recursive_directory_iterator>);
 static_assert(!std::indirectly_writable<fs::recursive_directory_iterator, value_type>);
@@ -34,3 +35,4 @@ static_assert(!std::incrementable<fs::recursive_directory_iterator>);
 static_assert(std::input_or_output_iterator<fs::recursive_directory_iterator>);
 static_assert(std::sentinel_for<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
 static_assert(!std::sized_sentinel_for<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
+static_assert(std::input_iterator<fs::recursive_directory_iterator>);
index 27e96a7..8b80681 100644 (file)
@@ -22,12 +22,16 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<fs::directory_iterator>, fs::directory_iterator>);
 static_assert(stdr::common_range<fs::directory_iterator>);
+static_assert(stdr::input_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>);
+static_assert(stdr::input_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>);
+static_assert(stdr::input_range<fs::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>);
+static_assert(stdr::input_range<fs::directory_iterator const>);
index 163130b..9db60e4 100644 (file)
@@ -22,6 +22,8 @@ namespace stdr = std::ranges;
 
 static_assert(std::same_as<stdr::iterator_t<fs::path>, fs::path::iterator>);
 static_assert(stdr::common_range<fs::path>);
+static_assert(stdr::input_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::input_range<fs::path const>);
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/input_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/input_iterator.compile.pass.cpp
new file mode 100644 (file)
index 0000000..59c64f4
--- /dev/null
@@ -0,0 +1,125 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// XFAIL: msvc && clang
+
+// template<class T>
+// concept input_iterator;
+
+#include <iterator>
+
+#include "test_iterators.h"
+
+static_assert(std::input_iterator<input_iterator<int*> >);
+static_assert(std::input_iterator<cpp20_input_iterator<int*> >);
+
+struct no_explicit_iter_concept {
+  using value_type = int;
+  using difference_type = std::ptrdiff_t;
+
+  no_explicit_iter_concept() = default;
+
+  no_explicit_iter_concept(no_explicit_iter_concept&&) = default;
+  no_explicit_iter_concept& operator=(no_explicit_iter_concept&&) = default;
+
+  no_explicit_iter_concept(no_explicit_iter_concept const&) = delete;
+  no_explicit_iter_concept& operator=(no_explicit_iter_concept const&) = delete;
+
+  value_type operator*() const;
+
+  no_explicit_iter_concept& operator++();
+  void operator++(int);
+};
+// ITER-CONCEPT is `random_access_iterator_tag` >:(
+static_assert(std::input_iterator<no_explicit_iter_concept>);
+
+static_assert(std::input_iterator<int*>);
+static_assert(std::input_iterator<int const*>);
+static_assert(std::input_iterator<int volatile*>);
+static_assert(std::input_iterator<int const volatile*>);
+
+struct not_weakly_incrementable {
+  using difference_type = std::ptrdiff_t;
+  using iterator_concept = std::input_iterator_tag;
+
+  not_weakly_incrementable() = default;
+
+  not_weakly_incrementable(not_weakly_incrementable&&) = default;
+  not_weakly_incrementable& operator=(not_weakly_incrementable&&) = default;
+
+  not_weakly_incrementable(not_weakly_incrementable const&) = delete;
+  not_weakly_incrementable& operator=(not_weakly_incrementable const&) = delete;
+
+  int operator*() const;
+
+  not_weakly_incrementable& operator++();
+};
+static_assert(!std::input_or_output_iterator<not_weakly_incrementable> &&
+              !std::input_iterator<not_weakly_incrementable>);
+
+struct not_indirectly_readable {
+  using difference_type = std::ptrdiff_t;
+  using iterator_concept = std::input_iterator_tag;
+
+  not_indirectly_readable() = default;
+
+  not_indirectly_readable(not_indirectly_readable&&) = default;
+  not_indirectly_readable& operator=(not_indirectly_readable&&) = default;
+
+  not_indirectly_readable(not_indirectly_readable const&) = delete;
+  not_indirectly_readable& operator=(not_indirectly_readable const&) = delete;
+
+  int operator*() const;
+
+  not_indirectly_readable& operator++();
+  void operator++(int);
+};
+static_assert(!std::indirectly_readable<not_indirectly_readable> && !std::input_iterator<not_indirectly_readable>);
+
+struct bad_iterator_category {
+  using value_type = int;
+  using difference_type = std::ptrdiff_t;
+  using iterator_category = void;
+
+  bad_iterator_category() = default;
+
+  bad_iterator_category(bad_iterator_category&&) = default;
+  bad_iterator_category& operator=(bad_iterator_category&&) = default;
+
+  bad_iterator_category(bad_iterator_category const&) = delete;
+  bad_iterator_category& operator=(bad_iterator_category const&) = delete;
+
+  value_type operator*() const;
+
+  bad_iterator_category& operator++();
+  void operator++(int);
+};
+static_assert(!std::input_iterator<bad_iterator_category>);
+
+struct bad_iterator_concept {
+  using value_type = int;
+  using difference_type = std::ptrdiff_t;
+  using iterator_concept = void*;
+
+  bad_iterator_concept() = default;
+
+  bad_iterator_concept(bad_iterator_concept&&) = default;
+  bad_iterator_concept& operator=(bad_iterator_concept&&) = default;
+
+  bad_iterator_concept(bad_iterator_concept const&) = delete;
+  bad_iterator_concept& operator=(bad_iterator_concept const&) = delete;
+
+  value_type operator*() const;
+
+  bad_iterator_concept& operator++();
+  void operator++(int);
+};
+static_assert(!std::input_iterator<bad_iterator_concept>);
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp
new file mode 100644 (file)
index 0000000..3a18b8a
--- /dev/null
@@ -0,0 +1 @@
+// Due to the need to check _ITER_CONCEPT, this test  is located in `test/libcxx/iterators/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp`.
index f5b9082..4df9058 100644 (file)
@@ -23,6 +23,7 @@ static_assert(std::incrementable<iterator>);
 static_assert(std::input_or_output_iterator<iterator>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(std::sized_sentinel_for<iterator, iterator>);
+static_assert(std::input_iterator<iterator>);
 
 using other_iterator = std::reverse_iterator<float*>;
 static_assert(std::sentinel_for<iterator, other_iterator>);
index 6db8603..514ba41 100644 (file)
@@ -24,3 +24,4 @@ static_assert(std::incrementable<iterator>);
 static_assert(std::input_or_output_iterator<iterator>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
+static_assert(std::input_iterator<iterator>);
index 2cbe4e0..70da029 100644 (file)
@@ -26,3 +26,4 @@ static_assert(!std::incrementable<iterator>);
 static_assert(std::input_or_output_iterator<iterator>);
 static_assert(std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
+static_assert(std::input_iterator<iterator>);
index efe5a17..c0fe917 100644 (file)
@@ -24,3 +24,4 @@ static_assert(!std::weakly_incrementable<iterator>);
 static_assert(!std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
+static_assert(!std::input_iterator<iterator>);
index fc28ce9..86abbc0 100644 (file)
@@ -25,3 +25,4 @@ static_assert(!std::weakly_incrementable<iterator>);
 static_assert(!std::input_or_output_iterator<iterator>);
 static_assert(!std::sentinel_for<iterator, iterator>);
 static_assert(!std::sized_sentinel_for<iterator, iterator>);
+static_assert(!std::input_iterator<iterator>);
diff --git a/libcxx/test/std/ranges/range.refinements/input_range.compile.pass.cpp b/libcxx/test/std/ranges/range.refinements/input_range.compile.pass.cpp
new file mode 100644 (file)
index 0000000..8ca8885
--- /dev/null
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// XFAIL: msvc && clang
+
+// template<range _Rp>
+// concept input_range;
+
+#include <ranges>
+
+#include "test_range.h"
+
+namespace stdr = std::ranges;
+
+static_assert(stdr::input_range<test_range<input_iterator> >);
+static_assert(stdr::input_range<test_range<input_iterator> const>);
+
+static_assert(stdr::input_range<test_range<cpp20_input_iterator> >);
+static_assert(stdr::input_range<test_range<cpp20_input_iterator> const>);
+
+static_assert(stdr::input_range<test_non_const_range<input_iterator> >);
+static_assert(stdr::input_range<test_non_const_range<cpp20_input_iterator> >);
+
+static_assert(!stdr::input_range<test_non_const_range<input_iterator> const>);
+static_assert(!stdr::input_range<test_non_const_range<cpp20_input_iterator> const>);
+
+static_assert(stdr::input_range<test_common_range<input_iterator> >);
+static_assert(!stdr::input_range<test_common_range<cpp20_input_iterator> >);
+
+static_assert(stdr::input_range<test_common_range<input_iterator> const>);
+static_assert(!stdr::input_range<test_common_range<cpp20_input_iterator> const>);
+
+static_assert(stdr::input_range<test_non_const_common_range<input_iterator> >);
+static_assert(!stdr::input_range<test_non_const_common_range<cpp20_input_iterator> >);
+
+static_assert(!stdr::input_range<test_non_const_common_range<input_iterator> const>);
+static_assert(!stdr::input_range<test_non_const_common_range<cpp20_input_iterator> const>);
diff --git a/libcxx/test/std/ranges/range.refinements/subsumption.compile.pass.cpp b/libcxx/test/std/ranges/range.refinements/subsumption.compile.pass.cpp
new file mode 100644 (file)
index 0000000..681146b
--- /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
+// XFAIL: msvc && clang
+
+// template<class T>
+// concept input_iterator;
+
+#include <ranges>
+
+#include <iterator>
+
+struct range {
+  int* begin();
+  int* end();
+};
+
+// clang-format off
+template<std::ranges::range R>
+requires std::input_iterator<std::ranges::iterator_t<R> >
+[[nodiscard]] constexpr bool check_input_range_subsumption() {
+  return false;
+}
+
+template<std::ranges::input_range>
+requires true
+[[nodiscard]] constexpr bool check_input_range_subsumption() {
+  return true;
+}
+// clang-format on
+
+static_assert(check_input_range_subsumption<range>());
index 897e744..19caf08 100644 (file)
@@ -23,3 +23,4 @@ static_assert(std::incrementable<std::cregex_iterator>);
 static_assert(std::input_or_output_iterator<std::cregex_iterator>);
 static_assert(std::sentinel_for<std::cregex_iterator, std::cregex_iterator>);
 static_assert(!std::sized_sentinel_for<std::cregex_iterator, std::cregex_iterator>);
+static_assert(std::input_iterator<std::cregex_iterator>);
index f94382f..17a49fe 100644 (file)
@@ -23,3 +23,4 @@ static_assert(std::incrementable<std::cregex_token_iterator>);
 static_assert(std::input_or_output_iterator<std::cregex_token_iterator>);
 static_assert(std::sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>);
 static_assert(!std::sized_sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>);
+static_assert(std::input_iterator<std::cregex_token_iterator>);
index 10f48a9..22eb3b4 100644 (file)
@@ -22,6 +22,8 @@ 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::input_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>);
+static_assert(stdr::input_range<std::cmatch const>);
index c352dda..2d07397 100644 (file)
@@ -22,6 +22,8 @@ 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::input_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>);
+static_assert(stdr::input_range<std::string const>);
index 616fdf6..cae5720 100644 (file)
@@ -47,3 +47,4 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index 595a12f..7fbafdc 100644 (file)
@@ -22,6 +22,8 @@ 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::input_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>);
+static_assert(stdr::input_range<std::string_view const>);
index 409f197..adb21bc 100644 (file)
@@ -47,3 +47,4 @@ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
 static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
 static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+static_assert(std::input_iterator<const_iterator>);
index cc5d018..cea849f 100644 (file)
@@ -632,6 +632,43 @@ template <typename T>
 bool operator!= (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
 {   return !a.operator==(b); }
 
+#ifdef TEST_SUPPORTS_RANGES
+
+template <class I>
+struct cpp20_input_iterator {
+  using value_type = std::iter_value_t<I>;
+  using difference_type = std::iter_difference_t<I>;
+  using iterator_concept = std::input_iterator_tag;
+
+  cpp20_input_iterator() = default;
+
+  cpp20_input_iterator(cpp20_input_iterator&&) = default;
+  cpp20_input_iterator& operator=(cpp20_input_iterator&&) = default;
+
+  cpp20_input_iterator(cpp20_input_iterator const&) = delete;
+  cpp20_input_iterator& operator=(cpp20_input_iterator const&) = delete;
+
+  explicit constexpr cpp20_input_iterator(I base) : base_(std::move(base)) {}
+
+  constexpr decltype(auto) operator*() const { return *base_; }
+
+  cpp20_input_iterator& operator++() {
+    ++base_;
+    return *this;
+  }
+
+  void operator++(int) { ++base_; }
+
+  [[nodiscard]] I const& base() const& { return base_; }
+
+  [[nodiscard]] I base() && { return std::move(base_); }
+
+private:
+  I base_ = I();
+};
+
+#endif // TEST_STD_VER > 17 && defined(__cpp_lib_concepts)
+
 #undef DELETE_FUNCTION
 
 #endif // ITERATORS_H
index 82a8511..c39e79b 100644 (file)
 #define LIBCPP_ONLY(...) ((void)0)
 #endif
 
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+#define TEST_SUPPORTS_RANGES
+#endif
+
 #define TEST_IGNORE_NODISCARD (void)
 
 namespace test_macros_detail {
index 3e9c94a..1b13dea 100644 (file)
@@ -18,7 +18,7 @@
 #endif
 
 struct sentinel {
-  bool operator==(std::input_or_output_iterator auto) const;
+  bool operator==(std::input_or_output_iterator auto const&) const;
 };
 
 // clang-format off