Skip to content

Commit

Permalink
[libcxx] contiguous iterator concept: don't require pointer or comple…
Browse files Browse the repository at this point in the history
…te 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
  • Loading branch information
JoeLoser committed Sep 1, 2021
1 parent a3d357e commit 2d400db
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 37 deletions.
1 change: 0 additions & 1 deletion libcxx/include/__iterator/concepts.h
Expand Up @@ -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>>>;
};
Expand Down
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
@@ -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}}
}

0 comments on commit 2d400db

Please sign in to comment.