Skip to content

Commit 2d400db

Browse files
committed
[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
1 parent a3d357e commit 2d400db

File tree

3 files changed

+59
-37
lines changed

3 files changed

+59
-37
lines changed

libcxx/include/__iterator/concepts.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ concept contiguous_iterator =
171171
derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> &&
172172
is_lvalue_reference_v<iter_reference_t<_Ip>> &&
173173
same_as<iter_value_t<_Ip>, remove_cvref_t<iter_reference_t<_Ip>>> &&
174-
(is_pointer_v<_Ip> || requires { sizeof(__pointer_traits_element_type<_Ip>); }) &&
175174
requires(const _Ip& __i) {
176175
{ _VSTD::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>;
177176
};

libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,10 @@ static_assert(!std::contiguous_iterator<mismatch_value_iter_ref_t>);
101101
struct wrong_iter_reference_t {
102102
typedef std::contiguous_iterator_tag iterator_category;
103103
typedef short value_type;
104+
typedef short element_type;
104105
typedef std::ptrdiff_t difference_type;
105-
typedef int* pointer;
106-
typedef short& reference;
106+
typedef short* pointer;
107+
typedef int& reference;
107108
typedef wrong_iter_reference_t self;
108109

109110
wrong_iter_reference_t();
@@ -132,40 +133,6 @@ struct wrong_iter_reference_t {
132133
static_assert(std::random_access_iterator<wrong_iter_reference_t>);
133134
static_assert(!std::contiguous_iterator<wrong_iter_reference_t>);
134135

135-
struct no_element_type {
136-
typedef std::contiguous_iterator_tag iterator_category;
137-
typedef int value_type;
138-
typedef std::ptrdiff_t difference_type;
139-
typedef int* pointer;
140-
typedef int& reference;
141-
typedef no_element_type self;
142-
143-
no_element_type();
144-
145-
reference operator*() const;
146-
pointer operator->() const;
147-
auto operator<=>(const self&) const = default;
148-
149-
self& operator++();
150-
self operator++(int);
151-
152-
self& operator--();
153-
self operator--(int);
154-
155-
self& operator+=(difference_type n);
156-
self operator+(difference_type n) const;
157-
friend self operator+(difference_type n, self x);
158-
159-
self& operator-=(difference_type n);
160-
self operator-(difference_type n) const;
161-
difference_type operator-(const self& n) const;
162-
163-
reference operator[](difference_type n) const;
164-
};
165-
166-
static_assert(std::random_access_iterator<no_element_type>);
167-
static_assert(!std::contiguous_iterator<no_element_type>);
168-
169136
struct to_address_wrong_return_type {
170137
typedef std::contiguous_iterator_tag iterator_category;
171138
typedef int value_type;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: libcpp-no-concepts
11+
// REQUIRES: libc++
12+
13+
// This test checks that std::contiguous_iterator uses std::to_address, which is not SFINAE-friendly
14+
// when the type is missing the `T::element_type` typedef.
15+
16+
#include <iterator>
17+
18+
#include <compare>
19+
#include <cstddef>
20+
21+
struct no_element_type {
22+
typedef std::contiguous_iterator_tag iterator_category;
23+
typedef int value_type;
24+
typedef std::ptrdiff_t difference_type;
25+
typedef int* pointer;
26+
typedef int& reference;
27+
typedef no_element_type self;
28+
29+
no_element_type();
30+
31+
reference operator*() const;
32+
pointer operator->() const;
33+
auto operator<=>(const self&) const = default;
34+
35+
self& operator++();
36+
self operator++(int);
37+
38+
self& operator--();
39+
self operator--(int);
40+
41+
self& operator+=(difference_type n);
42+
self operator+(difference_type n) const;
43+
friend self operator+(difference_type n, self x);
44+
45+
self& operator-=(difference_type n);
46+
self operator-(difference_type n) const;
47+
difference_type operator-(const self& n) const;
48+
49+
reference operator[](difference_type n) const;
50+
};
51+
52+
void test() {
53+
(void) std::contiguous_iterator<no_element_type>;
54+
// expected-error@*:* {{implicit instantiation of undefined template}}
55+
// expected-note@*:* {{to_address}}
56+
}

0 commit comments

Comments
 (0)