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 @@ -125,7 +125,34 @@ { __i-- } -> same_as<_Ip>; }; - // clang-format on +template +inline constexpr bool disable_sized_sentinel_for = false; + +template +concept sized_sentinel_for = + sentinel_for<_Sp, _Ip> && + !disable_sized_sentinel_for, remove_cv_t<_Ip> > && + requires(const _Ip& __i, const _Sp& __s) { + { __s - __i } -> same_as >; + { __i - __s } -> same_as >; + }; + +template +concept random_access_iterator = + bidirectional_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> && + totally_ordered<_Ip> && + sized_sentinel_for<_Ip, _Ip> && + requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) { + { __i += __n } -> same_as<_Ip&>; + { __j + __n } -> same_as<_Ip>; + { __n + __j } -> same_as<_Ip>; + { __i -= __n } -> same_as<_Ip&>; + { __j - __n } -> same_as<_Ip>; + { __j[__n] } -> same_as>; + }; + +// clang-format on #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -65,6 +65,10 @@ template concept common_range = range<_Tp> && same_as, sentinel_t<_Tp> >; + + template + concept random_access_range = + bidirectional_range<_Tp> && random_access_iterator >; } // namespace ranges #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp @@ -24,7 +24,9 @@ static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp @@ -24,7 +24,9 @@ static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp @@ -25,8 +25,10 @@ static_assert(stdr::common_range); static_assert(stdr::forward_range); static_assert(!stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); static_assert(stdr::forward_range); static_assert(!stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp @@ -24,7 +24,9 @@ static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp @@ -24,7 +24,9 @@ static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp @@ -24,7 +24,9 @@ static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp @@ -24,7 +24,9 @@ static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); static_assert(stdr::bidirectional_range); +static_assert(stdr::random_access_range); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/random_access_iterator.compile.pass.cpp @@ -0,0 +1,287 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// concept random_access_iterator; + +#include + +#include "test_iterators.h" + +static_assert(!std::random_access_iterator >); +static_assert(!std::random_access_iterator >); +static_assert(!std::random_access_iterator >); +static_assert(std::random_access_iterator >); +static_assert(std::random_access_iterator >); + +static_assert(!std::random_access_iterator >); +static_assert(!std::random_access_iterator >); +static_assert(!std::random_access_iterator >); +// TODO: are we adding cxx20_iterators? +// static_assert( std::random_access_iterator >); + +static_assert(std::random_access_iterator); +static_assert(std::random_access_iterator); +static_assert(std::random_access_iterator); +static_assert(std::random_access_iterator); + +struct simple_random_access_iterator { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef simple_random_access_iterator self; + + simple_random_access_iterator(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + self operator+(difference_type n) const; + friend self operator+(difference_type n, self x); + + self& operator-=(difference_type n); + self operator-(difference_type n) const; + difference_type operator-(const self n) const; + + reference operator[](difference_type n) const; +}; +static_assert(std::forward_iterator); +static_assert(std::random_access_iterator); + +struct no_plus_equals { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_plus_equals self; + + no_plus_equals(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self operator+(difference_type n) const; + friend self operator+(difference_type n, self x); + + self& operator-=(difference_type n); + self operator-(difference_type n) const; + difference_type operator-(const self n) const; + + reference operator[](difference_type n) const; +}; +static_assert(std::forward_iterator); +static_assert(!std::random_access_iterator); + +struct no_plus_difference_type { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_plus_difference_type self; + + no_plus_difference_type(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + friend self operator+(difference_type n, self x); + + self& operator-=(difference_type n); + self operator-(difference_type n) const; + difference_type operator-(const self n) const; + + reference operator[](difference_type n) const; +}; +static_assert(std::forward_iterator); +static_assert(!std::random_access_iterator); + +struct difference_type_no_plus { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef difference_type_no_plus self; + + difference_type_no_plus(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + self operator+(difference_type n) const; + + self& operator-=(difference_type n); + self operator-(difference_type n) const; + difference_type operator-(const self n) const; + + reference operator[](difference_type n) const; +}; +static_assert(std::forward_iterator); +static_assert(!std::random_access_iterator); + +struct no_minus_equals { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_minus_equals self; + + no_minus_equals(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + self operator+(difference_type n) const; + friend self operator+(difference_type n, self x); + + self operator-(difference_type n) const; + difference_type operator-(const self n) const; + + reference operator[](difference_type n) const; +}; +static_assert(std::forward_iterator); +static_assert(!std::random_access_iterator); + +struct no_minus { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_minus self; + + no_minus(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + self operator+(difference_type n) const; + friend self operator+(difference_type n, self x); + + self& operator-=(difference_type n); + + reference operator[](difference_type n) const; +}; +static_assert(std::forward_iterator); +static_assert(!std::random_access_iterator); + +struct no_subscript { + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_subscript self; + + no_subscript(); + + reference operator*() const; + pointer operator->() const; + friend bool operator==(const self, const self y); + friend bool operator< (const self, const self y); + friend bool operator<=(const self, const self y); + friend bool operator> (const self, const self y); + friend bool operator>=(const self, const self y); + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + self operator+(difference_type n) const; + friend self operator+(difference_type n, self x); + + self& operator-=(difference_type n); + self operator-(difference_type n) const; + difference_type operator-(const self n) const; +}; +static_assert(std::forward_iterator); +static_assert(!std::random_access_iterator); diff --git a/libcxx/test/std/ranges/range.refinements/random_access_range.compile.pass.cpp b/libcxx/test/std/ranges/range.refinements/random_access_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.refinements/random_access_range.compile.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// template +// concept random_access_range; + +#include + +#include "test_range.h" +#include "test_iterators.h" + +namespace ranges = std::ranges; + +template