[libcxx] contiguous iterator concept: don't require pointer or complete element types

`contiguous_iterator` requires the iterator type passed is either a
pointer type or that the element type of the iterator is a complete
object type. These constraints are not part of the current wording in
defining the `contiguous_iterator` concept - adjust the concept to
reflect this.

Inspired from discussion at https://reviews.llvm.org/D108645.

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D108855
This commit is contained in:
Joe Loser 2021-09-01 08:32:34 -04:00
parent a3d357e504
commit 2d400db63c
No known key found for this signature in database
GPG Key ID: 1CDBEBC050EA230D
3 changed files with 59 additions and 37 deletions

View File

@ -171,7 +171,6 @@ concept contiguous_iterator =
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>>>;
};

View File

@ -101,9 +101,10 @@ static_assert(!std::contiguous_iterator<mismatch_value_iter_ref_t>);
struct wrong_iter_reference_t {
typedef std::contiguous_iterator_tag iterator_category;
typedef short value_type;
typedef short element_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef short& reference;
typedef short* pointer;
typedef int& reference;
typedef wrong_iter_reference_t self;
wrong_iter_reference_t();
@ -132,40 +133,6 @@ struct wrong_iter_reference_t {
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;
auto operator<=>(const self&) const = default;
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;

View File

@ -0,0 +1,56 @@
//===----------------------------------------------------------------------===//
//
// 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
// REQUIRES: libc++
// This test checks that std::contiguous_iterator uses std::to_address, which is not SFINAE-friendly
// when the type is missing the `T::element_type` typedef.
#include <iterator>
#include <compare>
#include <cstddef>
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;
auto operator<=>(const self&) const = default;
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;
};
void test() {
(void) std::contiguous_iterator<no_element_type>;
// expected-error@*:* {{implicit instantiation of undefined template}}
// expected-note@*:* {{to_address}}
}