[libcxx][ranges] Add `contiguous_iterator`.

Differential Revision: https://reviews.llvm.org/D101396
This commit is contained in:
zoecarver 2021-04-27 08:53:17 -07:00
parent cb846654c6
commit bede7523b1
10 changed files with 300 additions and 10 deletions

View File

@ -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)

View File

@ -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>);

View File

@ -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>);

View File

@ -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>);

View File

@ -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>);

View File

@ -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>);

View File

@ -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>>);

View File

@ -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>);

View File

@ -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>);

View File

@ -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>);