diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -84,6 +84,21 @@ { __i++ } -> same_as<_Ip>; }; +// [iterator.concept.iterator] +template<class _Ip> +concept input_or_output_iterator = + requires(_Ip __i) { + { *__i } -> __referenceable; + } && + weakly_incrementable<_Ip>; + +// [iterator.concept.sentinel] +template<class _Sp, class _Ip> +concept sentinel_for = + semiregular<_Sp> && + input_or_output_iterator<_Ip> && + __weakly_equality_comparable_with<_Sp, _Ip>; + // clang-format on #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -60,6 +60,14 @@ template<class I> concept incrementable = see below; // since C++20 +// [iterator.concept.iterator], concept input_Âor_Âoutput_Âiterator + template<class I> + concept input_or_output_iterator = see below; // since C++20 + +// [iterator.concept.sentinel], concept sentinel_Âfor +template<class S, class I> + concept sentinel_for = 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/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::map<int, int>::iterator; using const_iterator = std::map<int, int>::const_iterator; +using reverse_iterator = std::map<int, int>::reverse_iterator; +using const_reverse_iterator = std::map<int, int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<const_iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::multimap<int, int>::iterator; using const_iterator = std::multimap<int, int>::const_iterator; +using reverse_iterator = std::multimap<int, int>::reverse_iterator; +using const_reverse_iterator = std::multimap<int, int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<const_iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,22 @@ using iterator = std::multiset<int>::iterator; using const_iterator = std::multiset<int>::const_iterator; +using reverse_iterator = std::multiset<int>::reverse_iterator; +using const_reverse_iterator = std::multiset<int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::set<int>::iterator; using const_iterator = std::set<int>::const_iterator; +using reverse_iterator = std::set<int>::reverse_iterator; +using const_reverse_iterator = std::set<int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp @@ -19,11 +19,23 @@ using iterator = std::array<int, 10>::iterator; 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::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, int>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, int>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::deque<int>::iterator; using const_iterator = std::deque<int>::const_iterator; +using reverse_iterator = std::deque<int>::reverse_iterator; +using const_reverse_iterator = std::deque<int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp @@ -24,7 +24,13 @@ static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<const_iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); diff --git a/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::list<int>::iterator; using const_iterator = std::list<int>::const_iterator; +using reverse_iterator = std::list<int>::reverse_iterator; +using const_reverse_iterator = std::list<int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::vector<bool>::iterator; using const_iterator = std::vector<bool>::const_iterator; +using reverse_iterator = std::vector<bool>::reverse_iterator; +using const_reverse_iterator = std::vector<bool>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,24 @@ using iterator = std::vector<int>::iterator; using const_iterator = std::vector<int>::const_iterator; +using reverse_iterator = std::vector<int>::reverse_iterator; +using const_reverse_iterator = std::vector<int>::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp @@ -26,15 +26,32 @@ static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); 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::indirectly_readable<local_iterator>); -static_assert(!std::indirectly_writable<local_iterator, value_type>); static_assert(std::incrementable<local_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_local_iterator>); static_assert(!std::indirectly_writable<const_local_iterator, value_type>); static_assert(std::incrementable<const_local_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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>); diff --git a/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp @@ -26,15 +26,35 @@ static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, local_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_local_iterator>); static_assert(std::indirectly_readable<local_iterator>); static_assert(!std::indirectly_writable<local_iterator, value_type>); static_assert(std::incrementable<local_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_local_iterator>); static_assert(!std::indirectly_writable<const_local_iterator, value_type>); static_assert(std::incrementable<const_local_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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>); diff --git a/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp @@ -26,15 +26,35 @@ static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, local_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_local_iterator>); static_assert(std::indirectly_readable<local_iterator>); static_assert(!std::indirectly_writable<local_iterator, value_type>); static_assert(std::incrementable<local_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_local_iterator>); static_assert(!std::indirectly_writable<const_local_iterator, value_type>); static_assert(std::incrementable<const_local_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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>); diff --git a/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp @@ -26,15 +26,32 @@ static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +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::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); 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::indirectly_readable<local_iterator>); -static_assert(!std::indirectly_writable<local_iterator, value_type>); static_assert(std::incrementable<local_iterator>); +static_assert(std::input_or_output_iterator<local_iterator>); +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::indirectly_readable<const_local_iterator>); static_assert(!std::indirectly_writable<const_local_iterator, value_type>); static_assert(std::incrementable<const_local_iterator>); +static_assert(std::input_or_output_iterator<const_local_iterator>); +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>); diff --git a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp @@ -18,8 +18,12 @@ #include <iterator> using iterator = std::span<int>::iterator; +using reverse_iterator = std::span<int>::reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp @@ -21,9 +21,13 @@ static_assert(!std::indirectly_writable<fs::directory_iterator, fs::directory_iterator::value_type>); static_assert(std::weakly_incrementable<fs::directory_iterator>); 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::indirectly_readable<fs::recursive_directory_iterator>); static_assert( !std::indirectly_writable<fs::recursive_directory_iterator, fs::recursive_directory_iterator::value_type>); static_assert(std::weakly_incrementable<fs::recursive_directory_iterator>); 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>); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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 In> +// concept input_or_output_iterator; + +#include <iterator> + +#include "test_iterators.h" + +static_assert(std::input_or_output_iterator<int*>); +static_assert(std::input_or_output_iterator<int const*>); +static_assert(std::input_or_output_iterator<int volatile*>); +static_assert(std::input_or_output_iterator<int const volatile*>); + +static_assert(std::input_or_output_iterator<input_iterator<int*> >); +static_assert(std::input_or_output_iterator<input_iterator<int const*> >); +static_assert(std::input_or_output_iterator<input_iterator<int volatile*> >); +static_assert(std::input_or_output_iterator<input_iterator<int const volatile*> >); + +static_assert(std::input_or_output_iterator<forward_iterator<int*> >); +static_assert(std::input_or_output_iterator<forward_iterator<int const*> >); +static_assert(std::input_or_output_iterator<forward_iterator<int volatile*> >); +static_assert(std::input_or_output_iterator<forward_iterator<int const volatile*> >); + +static_assert(std::input_or_output_iterator<bidirectional_iterator<int*> >); +static_assert(std::input_or_output_iterator<bidirectional_iterator<int const*> >); +static_assert(std::input_or_output_iterator<bidirectional_iterator<int volatile*> >); +static_assert(std::input_or_output_iterator<bidirectional_iterator<int const volatile*> >); + +static_assert(std::input_or_output_iterator<random_access_iterator<int*> >); +static_assert(std::input_or_output_iterator<random_access_iterator<int const*> >); +static_assert(std::input_or_output_iterator<random_access_iterator<int volatile*> >); +static_assert(std::input_or_output_iterator<random_access_iterator<int const volatile*> >); + +static_assert(!std::input_or_output_iterator<void*>); +static_assert(!std::input_or_output_iterator<void const*>); +static_assert(!std::input_or_output_iterator<void volatile*>); +static_assert(!std::input_or_output_iterator<void const volatile*>); + +struct S {}; +static_assert(!std::input_or_output_iterator<S>); +static_assert(!std::input_or_output_iterator<int S::*>); +static_assert(!std::input_or_output_iterator<int (S::*)()>); +static_assert(!std::input_or_output_iterator<int (S::*)() const>); +static_assert(!std::input_or_output_iterator<int (S::*)() volatile>); + +struct missing_dereference { + using difference_type = std::ptrdiff_t; + + missing_dereference& operator++(); + missing_dereference& operator++(int); +}; +static_assert(std::weakly_incrementable<missing_dereference> && !std::input_or_output_iterator<missing_dereference>); + +struct void_dereference { + using difference_type = std::ptrdiff_t; + + void operator*(); + void_dereference& operator++(); + void_dereference& operator++(int); +}; +static_assert(std::weakly_incrementable<void_dereference> && !std::input_or_output_iterator<void_dereference>); + +struct not_weakly_incrementable { + int operator*() const; +}; +static_assert(!std::input_or_output_iterator<not_weakly_incrementable>); diff --git a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp copy from libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp copy to libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp --- a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp @@ -11,15 +11,21 @@ // UNSUPPORTED: gcc-10 // XFAIL: msvc && clang -// iterator, reverse_iterator - -#include <span> +// template<class In> +// concept input_or_output_iterator; #include <iterator> -using iterator = std::span<int>::iterator; -using value_type = iterator::value_type; +// clang-format off +template<std::weakly_incrementable> +[[nodiscard]] constexpr bool check_subsumption() { + return false; +} + +template<std::input_or_output_iterator> +[[nodiscard]] constexpr bool check_subsumption() { + return true; +} +// clang-format on -static_assert(std::indirectly_readable<iterator>); -static_assert(std::indirectly_writable<iterator, value_type>); -static_assert(std::incrementable<iterator>); +static_assert(check_subsumption<int*>()); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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 S, class I> +// concept sentinel_for; + +#include <iterator> + +static_assert(std::sentinel_for<int*, int*>); +static_assert(!std::sentinel_for<int*, long*>); +struct nth_element_sentinel { + bool operator==(int*) const; +}; +static_assert(std::sentinel_for<nth_element_sentinel, int*>); +static_assert(std::sentinel_for<nth_element_sentinel, int*>); + +struct not_semiregular { + not_semiregular() = delete; + bool operator==(int*) const; +}; +static_assert(!std::sentinel_for<not_semiregular, int*>); + +struct weakly_equality_comparable_with_int { + bool operator==(int) const; +}; +static_assert(!std::sentinel_for<weakly_equality_comparable_with_int, int>); + +struct move_only_iterator { + using value_type = int; + using difference_type = std::ptrdiff_t; + + move_only_iterator() = default; + + move_only_iterator(move_only_iterator&&) = default; + move_only_iterator& operator=(move_only_iterator&&) = default; + + move_only_iterator(move_only_iterator const&) = delete; + move_only_iterator& operator=(move_only_iterator const&) = delete; + + value_type operator*() const; + move_only_iterator& operator++(); + move_only_iterator operator++(int); + + bool operator==(move_only_iterator const&) const = default; +}; +static_assert(std::movable<move_only_iterator> && !std::copyable<move_only_iterator> && + std::input_or_output_iterator<move_only_iterator> && + !std::sentinel_for<move_only_iterator, move_only_iterator>); diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp copy from libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp copy to libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp @@ -11,13 +11,24 @@ // UNSUPPORTED: gcc-10 // XFAIL: msvc && clang -// back_insert_iterator +// template<class S, class I> +// concept sentinel_for; #include <iterator> +#include <concepts> #include <vector> -using iterator = std::back_insert_iterator<std::vector<int> >; -static_assert(!std::indirectly_readable<iterator>); -static_assert(std::indirectly_writable<iterator, int>); -static_assert(!std::weakly_incrementable<iterator>); +// clang-format off +template<std::input_or_output_iterator, std::semiregular> +[[nodiscard]] constexpr bool check_sentinel_subsumption() { + return false; +} + +template<class I, std::sentinel_for<I> > +[[nodiscard]] constexpr bool check_subsumption() { + return true; +} +// clang-format on + +static_assert(check_subsumption<std::vector<int>::iterator, std::vector<int>::iterator>()); diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp @@ -21,3 +21,5 @@ static_assert(!std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, int>); static_assert(!std::weakly_incrementable<iterator>); +static_assert(!std::input_or_output_iterator<iterator>); +static_assert(!std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp @@ -21,3 +21,5 @@ static_assert(!std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, int>); static_assert(!std::weakly_incrementable<iterator>); +static_assert(!std::input_or_output_iterator<iterator>); +static_assert(!std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp @@ -21,3 +21,5 @@ static_assert(!std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, int>); static_assert(!std::weakly_incrementable<iterator>); +static_assert(!std::input_or_output_iterator<iterator>); +static_assert(!std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp @@ -19,3 +19,5 @@ static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, int>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp @@ -16,6 +16,12 @@ #include <iterator> using iterator = std::reverse_iterator<int*>; + static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, int>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); + +using other_iterator = std::reverse_iterator<float*>; +static_assert(std::sentinel_for<iterator, other_iterator>); diff --git a/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp @@ -21,3 +21,5 @@ static_assert(std::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, int>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp @@ -23,3 +23,5 @@ static_assert(!std::indirectly_writable<iterator, char>); static_assert(std::weakly_incrementable<iterator>); static_assert(!std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp @@ -21,3 +21,5 @@ static_assert(!std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, int>); static_assert(!std::weakly_incrementable<iterator>); +static_assert(!std::input_or_output_iterator<iterator>); +static_assert(!std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp @@ -22,3 +22,5 @@ static_assert(!std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, char>); static_assert(!std::weakly_incrementable<iterator>); +static_assert(!std::input_or_output_iterator<iterator>); +static_assert(!std::sentinel_for<iterator, iterator>); diff --git a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp @@ -20,3 +20,5 @@ static_assert(std::indirectly_readable<std::cregex_iterator>); static_assert(!std::indirectly_writable<std::cregex_iterator, char>); 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>); diff --git a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp @@ -20,3 +20,5 @@ static_assert(std::indirectly_readable<std::cregex_token_iterator>); static_assert(!std::indirectly_writable<std::cregex_token_iterator, char>); 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>); diff --git a/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp @@ -19,12 +19,23 @@ using iterator = std::string::iterator; using const_iterator = std::string::const_iterator; +using reverse_iterator = std::string::reverse_iterator; +using const_reverse_iterator = std::string::const_reverse_iterator; using value_type = iterator::value_type; static_assert(std::indirectly_readable<iterator>); static_assert(std::indirectly_writable<iterator, value_type>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, value_type>); static_assert(std::incrementable<const_iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>); diff --git a/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp @@ -19,11 +19,23 @@ using iterator = std::string_view::iterator; 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::indirectly_readable<iterator>); static_assert(!std::indirectly_writable<iterator, char>); static_assert(std::incrementable<iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<iterator, iterator>); +static_assert(std::sentinel_for<iterator, const_iterator>); +static_assert(!std::sentinel_for<iterator, reverse_iterator>); +static_assert(!std::sentinel_for<iterator, const_reverse_iterator>); static_assert(std::indirectly_readable<const_iterator>); static_assert(!std::indirectly_writable<const_iterator, char>); static_assert(std::incrementable<const_iterator>); +static_assert(std::input_or_output_iterator<iterator>); +static_assert(std::sentinel_for<const_iterator, iterator>); +static_assert(std::sentinel_for<const_iterator, const_iterator>); +static_assert(!std::sentinel_for<const_iterator, reverse_iterator>); +static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);