forked from OSchip/llvm-project
[libcxx][ranges] Add `contiguous_iterator`.
Differential Revision: https://reviews.llvm.org/D101396
This commit is contained in:
parent
cb846654c6
commit
bede7523b1
|
@ -12,10 +12,11 @@
|
|||
|
||||
#include <__config>
|
||||
#include <concepts>
|
||||
#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<iter_reference_t<_Ip>>;
|
||||
};
|
||||
|
||||
template<class _Ip>
|
||||
concept contiguous_iterator =
|
||||
random_access_iterator<_Ip> &&
|
||||
derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> &&
|
||||
is_lvalue_reference_v<iter_reference_t<_Ip>> &&
|
||||
same_as<iter_value_t<_Ip>, remove_cvref_t<iter_reference_t<_Ip>>> &&
|
||||
(is_pointer_v<_Ip> || requires { sizeof(__pointer_traits_element_type<_Ip>); }) &&
|
||||
requires(const _Ip& __i) {
|
||||
{ _VSTD::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>;
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
|
|
@ -21,7 +21,7 @@ using const_iterator = std::array<int, 10>::const_iterator;
|
|||
using reverse_iterator = std::array<int, 10>::reverse_iterator;
|
||||
using const_reverse_iterator = std::array<int, 10>::const_reverse_iterator;
|
||||
|
||||
static_assert(std::random_access_iterator<iterator>);
|
||||
static_assert(std::contiguous_iterator<iterator>);
|
||||
static_assert(std::indirectly_writable<iterator, int>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(std::sentinel_for<iterator, const_iterator>);
|
||||
|
@ -32,7 +32,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
|
|||
static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
|
||||
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
|
||||
|
||||
static_assert(std::random_access_iterator<const_iterator>);
|
||||
static_assert(std::contiguous_iterator<const_iterator>);
|
||||
static_assert(!std::indirectly_writable<const_iterator, int>);
|
||||
static_assert(std::sentinel_for<const_iterator, iterator>);
|
||||
static_assert(std::sentinel_for<const_iterator, const_iterator>);
|
||||
|
|
|
@ -23,6 +23,7 @@ using const_reverse_iterator = std::deque<int>::const_reverse_iterator;
|
|||
using value_type = int;
|
||||
|
||||
static_assert(std::random_access_iterator<iterator>);
|
||||
static_assert(!std::contiguous_iterator<iterator>);
|
||||
static_assert(std::indirectly_writable<iterator, value_type>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(std::sentinel_for<iterator, const_iterator>);
|
||||
|
@ -34,6 +35,7 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
|
|||
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
|
||||
|
||||
static_assert(std::random_access_iterator<const_iterator>);
|
||||
static_assert(!std::contiguous_iterator<const_iterator>);
|
||||
static_assert(!std::indirectly_writable<const_iterator, value_type>);
|
||||
static_assert(std::sentinel_for<const_iterator, iterator>);
|
||||
static_assert(std::sentinel_for<const_iterator, const_iterator>);
|
||||
|
|
|
@ -24,6 +24,8 @@ using value_type = bool;
|
|||
|
||||
static_assert(std::random_access_iterator<iterator>);
|
||||
static_assert(std::random_access_iterator<reverse_iterator>);
|
||||
static_assert(!std::contiguous_iterator<iterator>);
|
||||
static_assert(!std::contiguous_iterator<reverse_iterator>);
|
||||
static_assert(!std::indirectly_writable<iterator, value_type>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(std::sentinel_for<iterator, const_iterator>);
|
||||
|
@ -36,6 +38,8 @@ static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
|
|||
|
||||
static_assert(std::random_access_iterator<const_iterator>);
|
||||
static_assert(std::random_access_iterator<const_reverse_iterator>);
|
||||
static_assert(!std::contiguous_iterator<const_iterator>);
|
||||
static_assert(!std::contiguous_iterator<const_reverse_iterator>);
|
||||
static_assert(!std::indirectly_writable<const_iterator, value_type>);
|
||||
static_assert(std::sentinel_for<const_iterator, iterator>);
|
||||
static_assert(std::sentinel_for<const_iterator, const_iterator>);
|
||||
|
|
|
@ -22,8 +22,9 @@ using reverse_iterator = std::vector<int>::reverse_iterator;
|
|||
using const_reverse_iterator = std::vector<int>::const_reverse_iterator;
|
||||
using value_type = int;
|
||||
|
||||
static_assert(std::random_access_iterator<iterator>);
|
||||
static_assert(std::contiguous_iterator<iterator>);
|
||||
static_assert(std::random_access_iterator<reverse_iterator>);
|
||||
static_assert(!std::contiguous_iterator<reverse_iterator>);
|
||||
static_assert(std::indirectly_writable<iterator, value_type>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(std::sentinel_for<iterator, const_iterator>);
|
||||
|
@ -34,8 +35,9 @@ 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::random_access_iterator<const_iterator>);
|
||||
static_assert(std::contiguous_iterator<const_iterator>);
|
||||
static_assert(std::random_access_iterator<const_reverse_iterator>);
|
||||
static_assert(!std::contiguous_iterator<const_reverse_iterator>);
|
||||
static_assert(!std::indirectly_writable<const_iterator, value_type>);
|
||||
static_assert(std::sentinel_for<const_iterator, iterator>);
|
||||
static_assert(std::sentinel_for<const_iterator, const_iterator>);
|
||||
|
|
|
@ -20,7 +20,7 @@ using iterator = std::span<int>::iterator;
|
|||
using reverse_iterator = std::span<int>::reverse_iterator;
|
||||
using value_type = int;
|
||||
|
||||
static_assert(std::random_access_iterator<iterator>);
|
||||
static_assert(std::contiguous_iterator<iterator>);
|
||||
static_assert(std::indirectly_writable<iterator, value_type>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(!std::sentinel_for<iterator, reverse_iterator>);
|
||||
|
|
|
@ -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<class T>
|
||||
// concept contiguous_iterator;
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
static_assert(!std::contiguous_iterator<cpp17_input_iterator<int*> >);
|
||||
static_assert(!std::contiguous_iterator<cpp20_input_iterator<int*> >);
|
||||
static_assert(!std::contiguous_iterator<forward_iterator<int*> >);
|
||||
static_assert(!std::contiguous_iterator<bidirectional_iterator<int*> >);
|
||||
static_assert(!std::contiguous_iterator<random_access_iterator<int*> >);
|
||||
static_assert(std::contiguous_iterator<contiguous_iterator<int*> >);
|
||||
|
||||
static_assert(std::contiguous_iterator<int*>);
|
||||
static_assert(std::contiguous_iterator<int const*>);
|
||||
static_assert(std::contiguous_iterator<int volatile*>);
|
||||
static_assert(std::contiguous_iterator<int const volatile*>);
|
||||
|
||||
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<simple_contiguous_iterator>);
|
||||
static_assert(std::contiguous_iterator<simple_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<missmatch_value_iter_ref_t>);
|
||||
static_assert(!std::contiguous_iterator<missmatch_value_iter_ref_t>);
|
||||
|
||||
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<wrong_iter_reference_t>);
|
||||
static_assert(!std::contiguous_iterator<wrong_iter_reference_t>);
|
||||
|
||||
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<no_element_type>);
|
||||
static_assert(!std::contiguous_iterator<no_element_type>);
|
||||
|
||||
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<to_address_wrong_return_type> {
|
||||
typedef void element_type;
|
||||
static void *to_address(to_address_wrong_return_type const&);
|
||||
};
|
||||
|
||||
static_assert(std::random_access_iterator<to_address_wrong_return_type>);
|
||||
static_assert(!std::contiguous_iterator<to_address_wrong_return_type>);
|
||||
|
||||
template<class>
|
||||
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<template_and_no_element_type<int>>);
|
||||
static_assert(std::contiguous_iterator<template_and_no_element_type<int>>);
|
|
@ -34,9 +34,11 @@ static_assert(!std::sized_sentinel_for<reverse_bidirectional_iterator, reverse_b
|
|||
using reverse_random_access_iterator = std::reverse_iterator<random_access_iterator<int*>>;
|
||||
static_assert(common_reverse_iterator_checks<reverse_random_access_iterator>());
|
||||
static_assert(std::random_access_iterator<reverse_random_access_iterator>);
|
||||
static_assert(!std::contiguous_iterator<reverse_random_access_iterator>);
|
||||
static_assert(std::sized_sentinel_for<reverse_random_access_iterator, reverse_random_access_iterator>);
|
||||
|
||||
using reverse_contiguous_iterator = std::reverse_iterator<contiguous_iterator<int*>>;
|
||||
static_assert(common_reverse_iterator_checks<reverse_contiguous_iterator>());
|
||||
static_assert(std::random_access_iterator<reverse_contiguous_iterator>);
|
||||
static_assert(!std::contiguous_iterator<reverse_contiguous_iterator>);
|
||||
static_assert(std::sized_sentinel_for<reverse_contiguous_iterator, reverse_contiguous_iterator>);
|
||||
|
|
|
@ -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<iterator>);
|
||||
static_assert(std::contiguous_iterator<iterator>);
|
||||
static_assert(std::indirectly_writable<iterator, value_type>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(std::sentinel_for<iterator, const_iterator>);
|
||||
|
@ -33,7 +33,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
|
|||
static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
|
||||
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
|
||||
|
||||
static_assert(std::random_access_iterator<const_iterator>);
|
||||
static_assert(std::contiguous_iterator<const_iterator>);
|
||||
static_assert(!std::indirectly_writable<const_iterator, value_type>);
|
||||
static_assert(std::sentinel_for<const_iterator, iterator>);
|
||||
static_assert(std::sentinel_for<const_iterator, const_iterator>);
|
||||
|
|
|
@ -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<iterator>);
|
||||
static_assert(std::contiguous_iterator<iterator>);
|
||||
static_assert(!std::indirectly_writable<iterator, char>);
|
||||
static_assert(std::sentinel_for<iterator, iterator>);
|
||||
static_assert(std::sentinel_for<iterator, const_iterator>);
|
||||
|
@ -32,7 +32,7 @@ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
|
|||
static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
|
||||
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
|
||||
|
||||
static_assert(std::random_access_iterator<const_iterator>);
|
||||
static_assert(std::contiguous_iterator<const_iterator>);
|
||||
static_assert(!std::indirectly_writable<const_iterator, char>);
|
||||
static_assert(std::sentinel_for<const_iterator, iterator>);
|
||||
static_assert(std::sentinel_for<const_iterator, const_iterator>);
|
||||
|
|
Loading…
Reference in New Issue