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
11// std::ranges::data
12
13#include <ranges>
14
15#include <cassert>
16#include <type_traits>
17#include "test_macros.h"
18#include "test_iterators.h"
19
20using RangeDataT = decltype(std::ranges::data);
21using RangeCDataT = decltype(std::ranges::cdata);
22
23static int globalBuff[2];
24
25struct Incomplete;
26
27static_assert(!std::is_invocable_v<RangeDataT, Incomplete[]>);
28static_assert(!std::is_invocable_v<RangeDataT, Incomplete(&&)[2]>);
29static_assert(!std::is_invocable_v<RangeDataT, Incomplete(&&)[2][2]>);
30static_assert(!std::is_invocable_v<RangeDataT, int [1]>);
31static_assert(!std::is_invocable_v<RangeDataT, int (&&)[1]>);
32static_assert( std::is_invocable_v<RangeDataT, int (&)[1]>);
33
34static_assert(!std::is_invocable_v<RangeCDataT, Incomplete[]>);
35static_assert(!std::is_invocable_v<RangeCDataT, Incomplete(&&)[2]>);
36static_assert(!std::is_invocable_v<RangeCDataT, Incomplete(&&)[2][2]>);
37static_assert(!std::is_invocable_v<RangeCDataT, int [1]>);
38static_assert(!std::is_invocable_v<RangeCDataT, int (&&)[1]>);
39static_assert( std::is_invocable_v<RangeCDataT, int (&)[1]>);
40
41struct DataMember {
42 int x;
43 constexpr const int *data() const { return &x; }
44};
45static_assert( std::is_invocable_v<RangeDataT, DataMember &>);
46static_assert(!std::is_invocable_v<RangeDataT, DataMember &&>);
47static_assert( std::is_invocable_v<RangeDataT, DataMember const&>);
48static_assert(!std::is_invocable_v<RangeDataT, DataMember const&&>);
49static_assert( std::is_invocable_v<RangeCDataT, DataMember &>);
50static_assert(!std::is_invocable_v<RangeCDataT, DataMember &&>);
51static_assert( std::is_invocable_v<RangeCDataT, DataMember const&>);
52static_assert(!std::is_invocable_v<RangeCDataT, DataMember const&&>);
53
54constexpr bool testReturnTypes() {
55 {
56 int *x[2];
57 ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int**);
58 ASSERT_SAME_TYPE(decltype(std::ranges::cdata(x)), int* const*);
59 }
60 {
61 int x[2][2];
62 ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int(*)[2]);
63 ASSERT_SAME_TYPE(decltype(std::ranges::cdata(x)), const int(*)[2]);
64 }
65 {
66 struct D {
67 char*& data();
68 short*& data() const;
69 };
70 ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<D&>())), char*);
71 static_assert(!std::is_invocable_v<RangeDataT, D&&>);
72 ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const D&>())), short*);
73 static_assert(!std::is_invocable_v<RangeDataT, const D&&>);
74 ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<D&>())), short*);
75 static_assert(!std::is_invocable_v<RangeCDataT, D&&>);
76 ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<const D&>())), short*);
77 static_assert(!std::is_invocable_v<RangeCDataT, const D&&>);
78 }
79 {
80 struct NC {
81 char *begin() const;
82 char *end() const;
83 int *data();
84 };
85 static_assert(!std::ranges::contiguous_range<NC>);
86 static_assert( std::ranges::contiguous_range<const NC>);
87 ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<NC&>())), int*);
88 static_assert(!std::is_invocable_v<RangeDataT, NC&&>);
89 ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const NC&>())), char*);
90 static_assert(!std::is_invocable_v<RangeDataT, const NC&&>);
91 ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<NC&>())), char*);
92 static_assert(!std::is_invocable_v<RangeCDataT, NC&&>);
93 ASSERT_SAME_TYPE(decltype(std::ranges::cdata(std::declval<const NC&>())), char*);
94 static_assert(!std::is_invocable_v<RangeCDataT, const NC&&>);
95 }
96 return true;
97}
98
99struct VoidDataMember {
100 void *data() const;
101};
102static_assert(!std::is_invocable_v<RangeDataT, VoidDataMember const&>);
103static_assert(!std::is_invocable_v<RangeCDataT, VoidDataMember const&>);
104
105struct Empty { };
106struct EmptyDataMember {
107 Empty data() const;
108};
109static_assert(!std::is_invocable_v<RangeDataT, EmptyDataMember const&>);
110static_assert(!std::is_invocable_v<RangeCDataT, EmptyDataMember const&>);
111
112struct PtrConvertibleDataMember {
113 struct Ptr {
114 operator int*() const;
115 };
116 Ptr data() const;
117};
118static_assert(!std::is_invocable_v<RangeDataT, PtrConvertibleDataMember const&>);
119static_assert(!std::is_invocable_v<RangeCDataT, PtrConvertibleDataMember const&>);
120
121struct NonConstDataMember {
122 int x;
123 constexpr int *data() { return &x; }
124};
125
126struct EnabledBorrowingDataMember {
127 constexpr int *data() { return &globalBuff[0]; }
128};
129template<>
130inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingDataMember> = true;
131
132struct DataMemberAndBegin {
133 int x;
134 constexpr const int *data() const { return &x; }
135 const int *begin() const;
136};
137
138constexpr bool testDataMember() {
139 DataMember a;
140 assert(std::ranges::data(a) == &a.x);
141 assert(std::ranges::cdata(a) == &a.x);
142
143 NonConstDataMember b;
144 assert(std::ranges::data(b) == &b.x);
145 static_assert(!std::is_invocable_v<RangeCDataT, decltype((b))>);
146
147 EnabledBorrowingDataMember c;
148 assert(std::ranges::data(std::move(c)) == &globalBuff[0]);
149 static_assert(!std::is_invocable_v<RangeCDataT, decltype(std::move(c))>);
150
151 DataMemberAndBegin d;
152 assert(std::ranges::data(d) == &d.x);
153 assert(std::ranges::cdata(d) == &d.x);
154
155 return true;
156}
157
158using ContiguousIter = contiguous_iterator<const int*>;
159
160struct BeginMemberContiguousIterator {
161 int buff[8];
162
163 constexpr ContiguousIter begin() const { return ContiguousIter(buff); }
164};
165static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &>);
166static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &&>);
167static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&>);
168static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&&>);
169static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &>);
170static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &&>);
171static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&>);
172static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&&>);
173
174struct BeginMemberRandomAccess {
175 int buff[8];
176
177 random_access_iterator<const int*> begin() const;
178};
179static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess&>);
180static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRandomAccess&&>);
181static_assert(!std::is_invocable_v<RangeDataT, const BeginMemberRandomAccess&>);
182static_assert(!std::is_invocable_v<RangeDataT, const BeginMemberRandomAccess&&>);
183static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRandomAccess&>);
184static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRandomAccess&&>);
185static_assert(!std::is_invocable_v<RangeCDataT, const BeginMemberRandomAccess&>);
186static_assert(!std::is_invocable_v<RangeCDataT, const BeginMemberRandomAccess&&>);
187
188struct BeginFriendContiguousIterator {
189 int buff[8];
190
191 friend constexpr ContiguousIter begin(const BeginFriendContiguousIterator &iter) {
192 return ContiguousIter(iter.buff);
193 }
194};
195static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &>);
196static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator &&>);
197static_assert( std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&>);
198static_assert(!std::is_invocable_v<RangeDataT, BeginMemberContiguousIterator const&&>);
199static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &>);
200static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator &&>);
201static_assert( std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&>);
202static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberContiguousIterator const&&>);
203
204struct BeginFriendRandomAccess {
205 friend random_access_iterator<const int*> begin(const BeginFriendRandomAccess iter);
206};
207static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess&>);
208static_assert(!std::is_invocable_v<RangeDataT, BeginFriendRandomAccess&&>);
209static_assert(!std::is_invocable_v<RangeDataT, const BeginFriendRandomAccess&>);
210static_assert(!std::is_invocable_v<RangeDataT, const BeginFriendRandomAccess&&>);
211static_assert(!std::is_invocable_v<RangeCDataT, BeginFriendRandomAccess&>);
212static_assert(!std::is_invocable_v<RangeCDataT, BeginFriendRandomAccess&&>);
213static_assert(!std::is_invocable_v<RangeCDataT, const BeginFriendRandomAccess&>);
214static_assert(!std::is_invocable_v<RangeCDataT, const BeginFriendRandomAccess&&>);
215
216struct BeginMemberRvalue {
217 int buff[8];
218
219 ContiguousIter begin() &&;
220};
221static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&>);
222static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&&>);
223static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&>);
224static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&&>);
225static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue&>);
226static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue&&>);
227static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue const&>);
228static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberRvalue const&&>);
229
230struct BeginMemberBorrowingEnabled {
231 constexpr contiguous_iterator<int*> begin() { return contiguous_iterator<int*>{&globalBuff[1]}; }
232};
233template<>
234inline constexpr bool std::ranges::enable_borrowed_range<BeginMemberBorrowingEnabled> = true;
235static_assert( std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled &>);
236static_assert( std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled &&>);
237static_assert(!std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled const&>);
238static_assert(!std::is_invocable_v<RangeDataT, BeginMemberBorrowingEnabled const&&>);
239static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled &>);
240static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled &&>);
241static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled const&>);
242static_assert(!std::is_invocable_v<RangeCDataT, BeginMemberBorrowingEnabled const&&>);
243
244constexpr bool testViaRangesBegin() {
245 int arr[2];
246 assert(std::ranges::data(arr) == arr + 0);
247 assert(std::ranges::cdata(arr) == arr + 0);
248
249 BeginMemberContiguousIterator a;
250 assert(std::ranges::data(a) == a.buff);
251 assert(std::ranges::cdata(a) == a.buff);
252
253 const BeginFriendContiguousIterator b {};
254 assert(std::ranges::data(b) == b.buff);
255 assert(std::ranges::cdata(b) == b.buff);
256
257 BeginMemberBorrowingEnabled c;
258 assert(std::ranges::data(std::move(c)) == &globalBuff[1]);
259 static_assert(!std::is_invocable_v<RangeCDataT, decltype(std::move(c))>);
260
261 return true;
262}
263
264// Test ADL-proofing.
265struct Incomplete;
266template<class T> struct Holder { T t; };
267static_assert(!std::is_invocable_v<RangeDataT, Holder<Incomplete>*>);
268static_assert(!std::is_invocable_v<RangeDataT, Holder<Incomplete>*&>);
269static_assert(!std::is_invocable_v<RangeCDataT, Holder<Incomplete>*>);
270static_assert(!std::is_invocable_v<RangeCDataT, Holder<Incomplete>*&>);
271
272struct RandomButNotContiguous {
273 random_access_iterator<int*> begin() const;
274 random_access_iterator<int*> end() const;
275};
276static_assert(!std::is_invocable_v<RangeDataT, RandomButNotContiguous>);
277static_assert(!std::is_invocable_v<RangeDataT, RandomButNotContiguous&>);
278static_assert(!std::is_invocable_v<RangeCDataT, RandomButNotContiguous>);
279static_assert(!std::is_invocable_v<RangeCDataT, RandomButNotContiguous&>);
280
281int main(int, char**) {
282 static_assert(testReturnTypes());
283
284 testDataMember();
285 static_assert(testDataMember());
286
287 testViaRangesBegin();
288 static_assert(testViaRangesBegin());
289
290 return 0;
291}
292

source code of libcxx/test/std/ranges/range.access/data.pass.cpp