diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h index 0dd8a72210ee..985928119668 100644 --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -12,10 +12,11 @@ #include <__config> #include -#include <__iterator/iter_move.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> +#include <__iterator/iter_move.h> #include <__iterator/readable_traits.h> +#include <__memory/pointer_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -152,6 +153,17 @@ concept random_access_iterator = { __j[__n] } -> same_as>; }; +template +concept contiguous_iterator = + random_access_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && + is_lvalue_reference_v> && + same_as, remove_cvref_t>> && + (is_pointer_v<_Ip> || requires { sizeof(__pointer_traits_element_type<_Ip>); }) && + requires(const _Ip& __i) { + { _VSTD::to_address(__i) } -> same_as>>; + }; + // clang-format on #endif // !defined(_LIBCPP_HAS_NO_RANGES) 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 index 3010bd367804..0987835fcda0 100644 --- 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 @@ -21,7 +21,7 @@ using const_iterator = std::array::const_iterator; using reverse_iterator = std::array::reverse_iterator; using const_reverse_iterator = std::array::const_reverse_iterator; -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); @@ -32,7 +32,7 @@ static_assert(std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); 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 index 79543203f1aa..248e34b51572 100644 --- 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 @@ -23,6 +23,7 @@ using const_reverse_iterator = std::deque::const_reverse_iterator; using value_type = int; static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); static_assert(std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); @@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); 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 index 06770fc7cedb..7f5f87b2f818 100644 --- 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 @@ -24,6 +24,8 @@ using value_type = bool; static_assert(std::random_access_iterator); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); +static_assert(!std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); @@ -36,6 +38,8 @@ static_assert(!std::sized_sentinel_for); static_assert(std::random_access_iterator); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); +static_assert(!std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); 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 index 148d68633819..e1160dc5f7df 100644 --- 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 @@ -22,8 +22,9 @@ using reverse_iterator = std::vector::reverse_iterator; using const_reverse_iterator = std::vector::const_reverse_iterator; using value_type = int; -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); static_assert(std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); @@ -34,8 +35,9 @@ static_assert(std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); 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 index 0e147c753340..80022c298796 100644 --- 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 @@ -20,7 +20,7 @@ using iterator = std::span::iterator; using reverse_iterator = std::span::reverse_iterator; using value_type = int; -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(std::indirectly_writable); static_assert(std::sentinel_for); static_assert(!std::sentinel_for); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp new file mode 100644 index 000000000000..8a771e18935d --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// concept contiguous_iterator; + +#include + +#include "test_iterators.h" + +static_assert(!std::contiguous_iterator >); +static_assert(!std::contiguous_iterator >); +static_assert(!std::contiguous_iterator >); +static_assert(!std::contiguous_iterator >); +static_assert(!std::contiguous_iterator >); +static_assert(std::contiguous_iterator >); + +static_assert(std::contiguous_iterator); +static_assert(std::contiguous_iterator); +static_assert(std::contiguous_iterator); +static_assert(std::contiguous_iterator); + +struct simple_contiguous_iterator { + typedef std::contiguous_iterator_tag iterator_category; + typedef int value_type; + typedef int element_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef simple_contiguous_iterator self; + + simple_contiguous_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::random_access_iterator); +static_assert(std::contiguous_iterator); + +struct missmatch_value_iter_ref_t { + typedef std::contiguous_iterator_tag iterator_category; + typedef short value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef missmatch_value_iter_ref_t self; + + missmatch_value_iter_ref_t(); + + 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::random_access_iterator); +static_assert(!std::contiguous_iterator); + +struct wrong_iter_reference_t { + typedef std::contiguous_iterator_tag iterator_category; + typedef short value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef short& reference; + typedef wrong_iter_reference_t self; + + wrong_iter_reference_t(); + + 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::random_access_iterator); +static_assert(!std::contiguous_iterator); + +struct no_element_type { + typedef std::contiguous_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_element_type self; + + no_element_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); + 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::random_access_iterator); +static_assert(!std::contiguous_iterator); + +struct to_address_wrong_return_type { + typedef std::contiguous_iterator_tag iterator_category; + typedef int value_type; + typedef int element_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef to_address_wrong_return_type self; + + to_address_wrong_return_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); + 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; +}; + +template<> +struct std::pointer_traits { + typedef void element_type; + static void *to_address(to_address_wrong_return_type const&); +}; + +static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); + +template +struct template_and_no_element_type { + typedef std::contiguous_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef template_and_no_element_type self; + + template_and_no_element_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); + 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; +}; + +// Template param is used instead of element_type. +static_assert(std::random_access_iterator>); +static_assert(std::contiguous_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 index 3165caf234c7..10231b4080e5 100644 --- 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 @@ -34,9 +34,11 @@ static_assert(!std::sized_sentinel_for>; static_assert(common_reverse_iterator_checks()); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); static_assert(std::sized_sentinel_for); using reverse_contiguous_iterator = std::reverse_iterator>; static_assert(common_reverse_iterator_checks()); static_assert(std::random_access_iterator); +static_assert(!std::contiguous_iterator); static_assert(std::sized_sentinel_for); 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 index 7cf60157e180..f147efac7495 100644 --- 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 @@ -22,7 +22,7 @@ using reverse_iterator = std::string::reverse_iterator; using const_reverse_iterator = std::string::const_reverse_iterator; using value_type = char; -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); @@ -33,7 +33,7 @@ static_assert(std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); 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 index cd6b3790782a..53eee4ef80b3 100644 --- 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 @@ -21,7 +21,7 @@ using const_iterator = std::string_view::const_iterator; using reverse_iterator = std::string_view::reverse_iterator; using const_reverse_iterator = std::string_view::const_reverse_iterator; -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for); @@ -32,7 +32,7 @@ static_assert(std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::sized_sentinel_for); -static_assert(std::random_access_iterator); +static_assert(std::contiguous_iterator); static_assert(!std::indirectly_writable); static_assert(std::sentinel_for); static_assert(std::sentinel_for);