]>
Commit | Line | Data |
---|---|---|
278d4cc4 | 1 | // -*- C++ -*- |
f92ab29f | 2 | // Iterator Wrappers for the C++ library testsuite. |
278d4cc4 | 3 | // |
7adcbafe | 4 | // Copyright (C) 2004-2022 Free Software Foundation, Inc. |
278d4cc4 CJ |
5 | // |
6 | // This file is part of the GNU ISO C++ Library. This library is free | |
7 | // software; you can redistribute it and/or modify it under the | |
8 | // terms of the GNU General Public License as published by the | |
748086b7 | 9 | // Free Software Foundation; either version 3, or (at your option) |
278d4cc4 CJ |
10 | // any later version. |
11 | // | |
12 | // This library is distributed in the hope that it will be useful, | |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | // GNU General Public License for more details. | |
16 | // | |
17 | // You should have received a copy of the GNU General Public License along | |
748086b7 JJ |
18 | // with this library; see the file COPYING3. If not see |
19 | // <http://www.gnu.org/licenses/>. | |
278d4cc4 | 20 | // |
278d4cc4 CJ |
21 | |
22 | // This file provides the following: | |
23 | // | |
24 | // input_iterator_wrapper, output_iterator_wrapper | |
25 | // forward_iterator_wrapper, bidirectional_iterator_wrapper and | |
26 | // random_access_wrapper, which attempt to exactly perform the requirements | |
27 | // of these types of iterators. These are constructed from the class | |
28 | // test_container, which is given two pointers to T and an iterator type. | |
29 | ||
30 | #include <testsuite_hooks.h> | |
acb8a4ef | 31 | #include <bits/stl_iterator_base_types.h> |
cb2168c9 | 32 | |
734f5023 | 33 | #if __cplusplus >= 201103L |
ca0f8fd1 | 34 | #include <bits/move.h> |
cb2168c9 | 35 | #endif |
278d4cc4 CJ |
36 | |
37 | #ifndef _TESTSUITE_ITERATORS | |
38 | #define _TESTSUITE_ITERATORS | |
39 | ||
40 | #ifdef DISABLE_ITERATOR_DEBUG | |
41 | #define ITERATOR_VERIFY(x) | |
42 | #else | |
43 | #define ITERATOR_VERIFY(x) VERIFY(x) | |
44 | #endif | |
45 | ||
46 | namespace __gnu_test | |
47 | { | |
48 | /** | |
49 | * @brief Simple container for holding two pointers. | |
50 | * | |
51 | * Note that input_iterator_wrapper changes first to denote | |
52 | * how the valid range of == , ++, etc. change as the iterators are used. | |
53 | */ | |
54 | template<typename T> | |
55 | struct BoundsContainer | |
56 | { | |
57 | T* first; | |
58 | T* last; | |
9921ac3d | 59 | |
65be6ddd | 60 | BoundsContainer(T* _first, T* _last) : first(_first), last(_last) |
278d4cc4 | 61 | { } |
9921ac3d JW |
62 | |
63 | std::size_t size() const { return last - first; } | |
278d4cc4 CJ |
64 | }; |
65 | ||
66 | // Simple container for holding state of a set of output iterators. | |
67 | template<typename T> | |
68 | struct OutputContainer : public BoundsContainer<T> | |
69 | { | |
70 | T* incrementedto; | |
71 | bool* writtento; | |
9921ac3d | 72 | |
278d4cc4 | 73 | OutputContainer(T* _first, T* _last) |
9921ac3d JW |
74 | : BoundsContainer<T>(_first, _last), incrementedto(_first), |
75 | writtento(new bool[this->size()]()) | |
76 | { } | |
278d4cc4 CJ |
77 | |
78 | ~OutputContainer() | |
79 | { delete[] writtento; } | |
80 | }; | |
81 | ||
82 | // Produced by output_iterator to allow limited writing to pointer | |
83 | template<class T> | |
84 | class WritableObject | |
85 | { | |
86 | T* ptr; | |
87 | ||
88 | public: | |
89 | OutputContainer<T>* SharedInfo; | |
9921ac3d JW |
90 | |
91 | WritableObject(T* ptr_in, OutputContainer<T>* SharedInfo_in): | |
278d4cc4 CJ |
92 | ptr(ptr_in), SharedInfo(SharedInfo_in) |
93 | { } | |
94 | ||
734f5023 | 95 | #if __cplusplus >= 201103L |
561e7a36 | 96 | template<class U> |
9921ac3d | 97 | typename std::enable_if<std::is_assignable<T&, U>::value>::type |
328b52d6 | 98 | operator=(U&& new_val) const |
278d4cc4 CJ |
99 | { |
100 | ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0); | |
101 | SharedInfo->writtento[ptr - SharedInfo->first] = 1; | |
01bbe151 | 102 | *ptr = std::forward<U>(new_val); |
278d4cc4 | 103 | } |
01bbe151 | 104 | #else |
3c167a8b PC |
105 | template<class U> |
106 | void | |
01bbe151 | 107 | operator=(const U& new_val) |
3c167a8b PC |
108 | { |
109 | ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0); | |
110 | SharedInfo->writtento[ptr - SharedInfo->first] = 1; | |
01bbe151 | 111 | *ptr = new_val; |
3c167a8b PC |
112 | } |
113 | #endif | |
278d4cc4 CJ |
114 | }; |
115 | ||
116 | /** | |
117 | * @brief output_iterator wrapper for pointer | |
f92ab29f | 118 | * |
278d4cc4 CJ |
119 | * This class takes a pointer and wraps it to provide exactly |
120 | * the requirements of a output_iterator. It should not be | |
f7fbb003 | 121 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
122 | */ |
123 | template<class T> | |
65be6ddd | 124 | struct output_iterator_wrapper |
0614bbbe | 125 | : public std::iterator<std::output_iterator_tag, void, std::ptrdiff_t, void, void> |
278d4cc4 | 126 | { |
4512b7d8 PP |
127 | protected: |
128 | output_iterator_wrapper() : ptr(0), SharedInfo(0) | |
129 | { } | |
130 | ||
131 | public: | |
278d4cc4 CJ |
132 | typedef OutputContainer<T> ContainerType; |
133 | T* ptr; | |
134 | ContainerType* SharedInfo; | |
135 | ||
136 | output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) | |
65be6ddd | 137 | : ptr(_ptr), SharedInfo(SharedInfo_in) |
278d4cc4 CJ |
138 | { |
139 | ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); | |
140 | } | |
f92ab29f | 141 | |
0a70fb87 | 142 | #if __cplusplus >= 201103L |
0a70fb87 JW |
143 | output_iterator_wrapper(const output_iterator_wrapper&) = default; |
144 | ||
145 | output_iterator_wrapper& | |
146 | operator=(const output_iterator_wrapper&) = default; | |
147 | #endif | |
278d4cc4 CJ |
148 | |
149 | WritableObject<T> | |
150 | operator*() const | |
151 | { | |
152 | ITERATOR_VERIFY(ptr < SharedInfo->last); | |
153 | ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false); | |
154 | return WritableObject<T>(ptr, SharedInfo); | |
155 | } | |
f92ab29f | 156 | |
278d4cc4 CJ |
157 | output_iterator_wrapper& |
158 | operator++() | |
159 | { | |
160 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
561e7a36 | 161 | ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto); |
278d4cc4 | 162 | ptr++; |
561e7a36 | 163 | SharedInfo->incrementedto=ptr; |
278d4cc4 CJ |
164 | return *this; |
165 | } | |
166 | ||
167 | output_iterator_wrapper | |
168 | operator++(int) | |
169 | { | |
170 | output_iterator_wrapper<T> tmp = *this; | |
171 | ++*this; | |
172 | return tmp; | |
173 | } | |
174 | ||
f970a17d JW |
175 | #if __cplusplus >= 201103L |
176 | template<typename U> | |
177 | void operator,(const U&) const = delete; | |
aca7a025 JW |
178 | |
179 | void operator&() const = delete; | |
f970a17d JW |
180 | #else |
181 | private: | |
182 | template<typename U> | |
183 | void operator,(const U&) const; | |
aca7a025 JW |
184 | |
185 | void operator&() const; | |
f970a17d | 186 | #endif |
278d4cc4 CJ |
187 | }; |
188 | ||
d67be443 JW |
189 | #if __cplusplus >= 201103L |
190 | template<typename T, typename U> | |
191 | void operator,(const T&, const output_iterator_wrapper<U>&) = delete; | |
192 | #endif | |
193 | ||
5211593c | 194 | #if __cplusplus >= 201103L |
9921ac3d JW |
195 | using std::remove_cv; |
196 | #else | |
e112d53a JW |
197 | template<typename T> struct remove_cv { typedef T type; }; |
198 | template<typename T> struct remove_cv<const T> { typedef T type; }; | |
199 | template<typename T> struct remove_cv<volatile T> { typedef T type; }; | |
200 | template<typename T> struct remove_cv<const volatile T> { typedef T type; }; | |
9921ac3d | 201 | #endif |
e112d53a | 202 | |
278d4cc4 CJ |
203 | /** |
204 | * @brief input_iterator wrapper for pointer | |
f92ab29f | 205 | * |
278d4cc4 CJ |
206 | * This class takes a pointer and wraps it to provide exactly |
207 | * the requirements of a input_iterator. It should not be | |
f7fbb003 | 208 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
209 | */ |
210 | template<class T> | |
65be6ddd | 211 | class input_iterator_wrapper |
e112d53a JW |
212 | : public std::iterator<std::input_iterator_tag, typename remove_cv<T>::type, |
213 | std::ptrdiff_t, T*, T&> | |
278d4cc4 | 214 | { |
118158b6 JW |
215 | struct post_inc_proxy |
216 | { | |
217 | struct deref_proxy | |
218 | { | |
219 | T* ptr; | |
220 | operator const T&() const { return *ptr; } | |
221 | } p; | |
222 | ||
223 | deref_proxy operator*() const { return p; } | |
224 | }; | |
225 | ||
278d4cc4 | 226 | protected: |
0a70fb87 | 227 | input_iterator_wrapper() : ptr(0), SharedInfo(0) |
278d4cc4 CJ |
228 | { } |
229 | ||
230 | public: | |
231 | typedef BoundsContainer<T> ContainerType; | |
232 | T* ptr; | |
233 | ContainerType* SharedInfo; | |
234 | ||
235 | input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) | |
65be6ddd | 236 | : ptr(_ptr), SharedInfo(SharedInfo_in) |
278d4cc4 | 237 | { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); } |
f92ab29f | 238 | |
0a70fb87 JW |
239 | #if __cplusplus >= 201103L |
240 | input_iterator_wrapper(const input_iterator_wrapper&) = default; | |
241 | ||
242 | input_iterator_wrapper& | |
243 | operator=(const input_iterator_wrapper&) = default; | |
244 | #endif | |
278d4cc4 CJ |
245 | |
246 | bool | |
247 | operator==(const input_iterator_wrapper& in) const | |
248 | { | |
8fc81078 | 249 | ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo); |
278d4cc4 CJ |
250 | ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first); |
251 | return ptr == in.ptr; | |
252 | } | |
253 | ||
254 | bool | |
255 | operator!=(const input_iterator_wrapper& in) const | |
256 | { | |
257 | return !(*this == in); | |
258 | } | |
259 | ||
260 | T& | |
261 | operator*() const | |
262 | { | |
263 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
264 | ITERATOR_VERIFY(ptr >= SharedInfo->first); | |
265 | return *ptr; | |
266 | } | |
267 | ||
268 | T* | |
269 | operator->() const | |
270 | { | |
271 | return &**this; | |
272 | } | |
273 | ||
278d4cc4 CJ |
274 | input_iterator_wrapper& |
275 | operator++() | |
276 | { | |
277 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
278 | ITERATOR_VERIFY(ptr>=SharedInfo->first); | |
279 | ptr++; | |
280 | SharedInfo->first=ptr; | |
281 | return *this; | |
282 | } | |
283 | ||
118158b6 | 284 | post_inc_proxy |
278d4cc4 CJ |
285 | operator++(int) |
286 | { | |
118158b6 | 287 | post_inc_proxy tmp = { { ptr } }; |
278d4cc4 | 288 | ++*this; |
118158b6 | 289 | return tmp; |
278d4cc4 | 290 | } |
f970a17d JW |
291 | |
292 | #if __cplusplus >= 201103L | |
293 | template<typename U> | |
294 | void operator,(const U&) const = delete; | |
aca7a025 JW |
295 | |
296 | void operator&() const = delete; | |
f970a17d JW |
297 | #else |
298 | private: | |
299 | template<typename U> | |
300 | void operator,(const U&) const; | |
aca7a025 JW |
301 | |
302 | void operator&() const; | |
f970a17d | 303 | #endif |
278d4cc4 CJ |
304 | }; |
305 | ||
d67be443 JW |
306 | #if __cplusplus >= 201103L |
307 | template<typename T, typename U> | |
308 | void operator,(const T&, const input_iterator_wrapper<U>&) = delete; | |
309 | #endif | |
278d4cc4 CJ |
310 | |
311 | /** | |
312 | * @brief forward_iterator wrapper for pointer | |
f92ab29f | 313 | * |
278d4cc4 CJ |
314 | * This class takes a pointer and wraps it to provide exactly |
315 | * the requirements of a forward_iterator. It should not be | |
f7fbb003 | 316 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
317 | */ |
318 | template<class T> | |
65be6ddd | 319 | struct forward_iterator_wrapper : public input_iterator_wrapper<T> |
278d4cc4 CJ |
320 | { |
321 | typedef BoundsContainer<T> ContainerType; | |
322 | typedef std::forward_iterator_tag iterator_category; | |
0a70fb87 | 323 | |
278d4cc4 | 324 | forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 325 | : input_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 | 326 | { } |
f92ab29f | 327 | |
0a70fb87 | 328 | forward_iterator_wrapper() |
278d4cc4 CJ |
329 | { } |
330 | ||
0a70fb87 JW |
331 | #if __cplusplus >= 201103L |
332 | forward_iterator_wrapper(const forward_iterator_wrapper&) = default; | |
333 | ||
334 | forward_iterator_wrapper& | |
335 | operator=(const forward_iterator_wrapper&) = default; | |
336 | #endif | |
278d4cc4 CJ |
337 | |
338 | T& | |
339 | operator*() const | |
340 | { | |
341 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
342 | return *(this->ptr); | |
343 | } | |
344 | ||
345 | T* | |
346 | operator->() const | |
347 | { return &**this; } | |
348 | ||
349 | forward_iterator_wrapper& | |
350 | operator++() | |
351 | { | |
352 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
353 | this->ptr++; | |
354 | return *this; | |
355 | } | |
356 | ||
357 | forward_iterator_wrapper | |
358 | operator++(int) | |
359 | { | |
360 | forward_iterator_wrapper<T> tmp = *this; | |
361 | ++*this; | |
362 | return tmp; | |
363 | } | |
e94f2542 JW |
364 | |
365 | #if __cplusplus >= 201402L | |
366 | bool | |
367 | operator==(const forward_iterator_wrapper& it) const noexcept | |
368 | { | |
369 | // Since C++14 value-initialized forward iterators are comparable. | |
370 | if (this->SharedInfo == nullptr || it.SharedInfo == nullptr) | |
371 | return this->SharedInfo == it.SharedInfo && this->ptr == it.ptr; | |
372 | ||
373 | const input_iterator_wrapper<T>& base_this = *this; | |
374 | const input_iterator_wrapper<T>& base_that = it; | |
375 | return base_this == base_that; | |
376 | } | |
377 | ||
378 | bool | |
379 | operator!=(const forward_iterator_wrapper& it) const noexcept | |
380 | { | |
381 | return !(*this == it); | |
382 | } | |
383 | #endif | |
f970a17d | 384 | }; |
278d4cc4 CJ |
385 | |
386 | /** | |
387 | * @brief bidirectional_iterator wrapper for pointer | |
f92ab29f | 388 | * |
278d4cc4 | 389 | * This class takes a pointer and wraps it to provide exactly |
ac2dca4d | 390 | * the requirements of a bidirectional_iterator. It should not be |
f7fbb003 | 391 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
392 | */ |
393 | template<class T> | |
65be6ddd | 394 | struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T> |
278d4cc4 CJ |
395 | { |
396 | typedef BoundsContainer<T> ContainerType; | |
397 | typedef std::bidirectional_iterator_tag iterator_category; | |
0a70fb87 | 398 | |
278d4cc4 | 399 | bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 400 | : forward_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 CJ |
401 | { } |
402 | ||
0a70fb87 JW |
403 | bidirectional_iterator_wrapper() |
404 | : forward_iterator_wrapper<T>() | |
278d4cc4 CJ |
405 | { } |
406 | ||
0a70fb87 JW |
407 | #if __cplusplus >= 201103L |
408 | bidirectional_iterator_wrapper( | |
409 | const bidirectional_iterator_wrapper&) = default; | |
278d4cc4 CJ |
410 | |
411 | bidirectional_iterator_wrapper& | |
0a70fb87 JW |
412 | operator=(const bidirectional_iterator_wrapper&) = default; |
413 | #endif | |
f92ab29f | 414 | |
278d4cc4 CJ |
415 | bidirectional_iterator_wrapper& |
416 | operator++() | |
417 | { | |
418 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
419 | this->ptr++; | |
420 | return *this; | |
421 | } | |
422 | ||
423 | bidirectional_iterator_wrapper | |
424 | operator++(int) | |
425 | { | |
426 | bidirectional_iterator_wrapper<T> tmp = *this; | |
427 | ++*this; | |
428 | return tmp; | |
429 | } | |
430 | ||
f92ab29f | 431 | bidirectional_iterator_wrapper& |
278d4cc4 CJ |
432 | operator--() |
433 | { | |
434 | ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); | |
435 | this->ptr--; | |
436 | return *this; | |
437 | } | |
438 | ||
439 | bidirectional_iterator_wrapper | |
440 | operator--(int) | |
f92ab29f | 441 | { |
278d4cc4 CJ |
442 | bidirectional_iterator_wrapper<T> tmp = *this; |
443 | --*this; | |
444 | return tmp; | |
445 | } | |
f970a17d | 446 | }; |
278d4cc4 CJ |
447 | |
448 | /** | |
449 | * @brief random_access_iterator wrapper for pointer | |
f92ab29f | 450 | * |
278d4cc4 | 451 | * This class takes a pointer and wraps it to provide exactly |
ac2dca4d | 452 | * the requirements of a random_access_iterator. It should not be |
f7fbb003 | 453 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
454 | */ |
455 | template<class T> | |
f92ab29f | 456 | struct random_access_iterator_wrapper |
65be6ddd | 457 | : public bidirectional_iterator_wrapper<T> |
278d4cc4 CJ |
458 | { |
459 | typedef BoundsContainer<T> ContainerType; | |
460 | typedef std::random_access_iterator_tag iterator_category; | |
0a70fb87 | 461 | |
278d4cc4 | 462 | random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 463 | : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 CJ |
464 | { } |
465 | ||
0a70fb87 JW |
466 | random_access_iterator_wrapper() |
467 | : bidirectional_iterator_wrapper<T>() | |
278d4cc4 CJ |
468 | { } |
469 | ||
0a70fb87 JW |
470 | #if __cplusplus >= 201103L |
471 | random_access_iterator_wrapper( | |
472 | const random_access_iterator_wrapper&) = default; | |
278d4cc4 CJ |
473 | |
474 | random_access_iterator_wrapper& | |
0a70fb87 JW |
475 | operator=(const random_access_iterator_wrapper&) = default; |
476 | #endif | |
278d4cc4 CJ |
477 | |
478 | random_access_iterator_wrapper& | |
479 | operator++() | |
480 | { | |
481 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
482 | this->ptr++; | |
483 | return *this; | |
484 | } | |
485 | ||
486 | random_access_iterator_wrapper | |
487 | operator++(int) | |
488 | { | |
489 | random_access_iterator_wrapper<T> tmp = *this; | |
490 | ++*this; | |
491 | return tmp; | |
492 | } | |
493 | ||
494 | random_access_iterator_wrapper& | |
495 | operator--() | |
496 | { | |
497 | ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); | |
498 | this->ptr--; | |
499 | return *this; | |
500 | } | |
501 | ||
502 | random_access_iterator_wrapper | |
503 | operator--(int) | |
504 | { | |
505 | random_access_iterator_wrapper<T> tmp = *this; | |
561e7a36 | 506 | --*this; |
278d4cc4 CJ |
507 | return tmp; |
508 | } | |
509 | ||
510 | random_access_iterator_wrapper& | |
445877a9 | 511 | operator+=(std::ptrdiff_t n) |
278d4cc4 CJ |
512 | { |
513 | if(n > 0) | |
514 | { | |
515 | ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr); | |
516 | this->ptr += n; | |
517 | } | |
518 | else | |
519 | { | |
e1008cd1 | 520 | ITERATOR_VERIFY(-n <= this->ptr - this->SharedInfo->first); |
278d4cc4 CJ |
521 | this->ptr += n; |
522 | } | |
523 | return *this; | |
524 | } | |
525 | ||
278d4cc4 | 526 | random_access_iterator_wrapper& |
445877a9 | 527 | operator-=(std::ptrdiff_t n) |
278d4cc4 CJ |
528 | { return *this += -n; } |
529 | ||
530 | random_access_iterator_wrapper | |
445877a9 | 531 | operator-(std::ptrdiff_t n) const |
278d4cc4 CJ |
532 | { |
533 | random_access_iterator_wrapper<T> tmp = *this; | |
534 | return tmp -= n; | |
535 | } | |
536 | ||
445877a9 | 537 | std::ptrdiff_t |
561e7a36 | 538 | operator-(const random_access_iterator_wrapper<T>& in) const |
278d4cc4 CJ |
539 | { |
540 | ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); | |
541 | return this->ptr - in.ptr; | |
542 | } | |
543 | ||
544 | T& | |
445877a9 | 545 | operator[](std::ptrdiff_t n) const |
561e7a36 | 546 | { return *(*this + n); } |
278d4cc4 CJ |
547 | |
548 | bool | |
549 | operator<(const random_access_iterator_wrapper<T>& in) const | |
550 | { | |
551 | ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); | |
552 | return this->ptr < in.ptr; | |
553 | } | |
554 | ||
555 | bool | |
556 | operator>(const random_access_iterator_wrapper<T>& in) const | |
557 | { | |
558 | return in < *this; | |
559 | } | |
560 | ||
561 | bool | |
562 | operator>=(const random_access_iterator_wrapper<T>& in) const | |
563 | { | |
564 | return !(*this < in); | |
565 | } | |
566 | ||
f92ab29f | 567 | bool |
278d4cc4 CJ |
568 | operator<=(const random_access_iterator_wrapper<T>& in) const |
569 | { | |
570 | return !(*this > in); | |
571 | } | |
f970a17d | 572 | }; |
278d4cc4 | 573 | |
561e7a36 PC |
574 | template<typename T> |
575 | random_access_iterator_wrapper<T> | |
445877a9 | 576 | operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n) |
561e7a36 PC |
577 | { return it += n; } |
578 | ||
579 | template<typename T> | |
580 | random_access_iterator_wrapper<T> | |
f92ab29f | 581 | operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it) |
561e7a36 PC |
582 | { return it += n; } |
583 | ||
278d4cc4 | 584 | |
f92ab29f | 585 | /** |
278d4cc4 CJ |
586 | * @brief A container-type class for holding iterator wrappers |
587 | * test_container takes two parameters, a class T and an iterator | |
588 | * wrapper templated by T (for example forward_iterator_wrapper<T>. | |
f92ab29f | 589 | * It takes two pointers representing a range and presents them as |
278d4cc4 CJ |
590 | * a container of iterators. |
591 | */ | |
060269c4 | 592 | template <class T, template<class TT> class ItType> |
278d4cc4 CJ |
593 | struct test_container |
594 | { | |
595 | typename ItType<T>::ContainerType bounds; | |
9921ac3d | 596 | |
4e66b02b | 597 | test_container(T* _first, T* _last) : bounds(_first, _last) |
278d4cc4 CJ |
598 | { } |
599 | ||
3ebacabd | 600 | #if __cplusplus >= 201103L |
4e66b02b JW |
601 | template<std::size_t N> |
602 | explicit | |
603 | test_container(T (&arr)[N]) : test_container(arr, arr+N) | |
604 | { } | |
3ebacabd JW |
605 | #endif |
606 | ||
278d4cc4 CJ |
607 | ItType<T> |
608 | it(int pos) | |
609 | { | |
13feb023 | 610 | ITERATOR_VERIFY(pos >= 0 && (unsigned)pos <= size()); |
278d4cc4 CJ |
611 | return ItType<T>(bounds.first + pos, &bounds); |
612 | } | |
613 | ||
614 | ItType<T> | |
615 | it(T* pos) | |
616 | { | |
617 | ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last); | |
618 | return ItType<T>(pos, &bounds); | |
619 | } | |
620 | ||
c2240038 CJ |
621 | const T& |
622 | val(int pos) | |
623 | { return (bounds.first)[pos]; } | |
624 | ||
278d4cc4 CJ |
625 | ItType<T> |
626 | begin() | |
627 | { return it(bounds.first); } | |
628 | ||
629 | ItType<T> | |
630 | end() | |
631 | { return it(bounds.last); } | |
ed920373 JW |
632 | |
633 | std::size_t | |
634 | size() const | |
9921ac3d | 635 | { return bounds.size(); } |
4e66b02b | 636 | }; |
6d0dff49 | 637 | |
e1008cd1 JW |
638 | #if __cplusplus >= 201103L |
639 | template<typename T> | |
640 | using output_container | |
641 | = test_container<T, output_iterator_wrapper>; | |
642 | ||
643 | template<typename T> | |
644 | using input_container | |
645 | = test_container<T, input_iterator_wrapper>; | |
646 | ||
647 | template<typename T> | |
648 | using forward_container | |
649 | = test_container<T, forward_iterator_wrapper>; | |
650 | ||
651 | template<typename T> | |
652 | using bidirectional_container | |
653 | = test_container<T, bidirectional_iterator_wrapper>; | |
654 | ||
655 | template<typename T> | |
656 | using random_access_container | |
657 | = test_container<T, random_access_iterator_wrapper>; | |
658 | #endif | |
659 | ||
6d0dff49 JW |
660 | #if __cplusplus > 201703L |
661 | template<typename T> | |
662 | struct contiguous_iterator_wrapper | |
663 | : random_access_iterator_wrapper<T> | |
664 | { | |
665 | using random_access_iterator_wrapper<T>::random_access_iterator_wrapper; | |
666 | ||
667 | using iterator_concept = std::contiguous_iterator_tag; | |
668 | ||
669 | contiguous_iterator_wrapper& | |
670 | operator++() | |
671 | { | |
672 | random_access_iterator_wrapper<T>::operator++(); | |
673 | return *this; | |
674 | } | |
675 | ||
676 | contiguous_iterator_wrapper& | |
677 | operator--() | |
678 | { | |
679 | random_access_iterator_wrapper<T>::operator--(); | |
680 | return *this; | |
681 | } | |
682 | ||
683 | contiguous_iterator_wrapper | |
684 | operator++(int) | |
685 | { | |
686 | auto tmp = *this; | |
687 | ++*this; | |
688 | return tmp; | |
689 | } | |
690 | ||
691 | contiguous_iterator_wrapper | |
692 | operator--(int) | |
693 | { | |
694 | auto tmp = *this; | |
695 | --*this; | |
696 | return tmp; | |
697 | } | |
698 | ||
699 | contiguous_iterator_wrapper& | |
700 | operator+=(std::ptrdiff_t n) | |
701 | { | |
702 | random_access_iterator_wrapper<T>::operator+=(n); | |
703 | return *this; | |
704 | } | |
705 | ||
706 | friend contiguous_iterator_wrapper | |
707 | operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n) | |
708 | { return iter += n; } | |
709 | ||
710 | friend contiguous_iterator_wrapper | |
711 | operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter) | |
712 | { return iter += n; } | |
713 | ||
714 | contiguous_iterator_wrapper& | |
715 | operator-=(std::ptrdiff_t n) | |
716 | { return *this += -n; } | |
717 | ||
718 | friend contiguous_iterator_wrapper | |
719 | operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n) | |
720 | { return iter -= n; } | |
721 | }; | |
722 | ||
e1008cd1 JW |
723 | template<typename T> |
724 | using contiguous_container | |
725 | = test_container<T, contiguous_iterator_wrapper>; | |
726 | ||
d6d4b339 PP |
727 | // A move-only input iterator type. |
728 | template<typename T> | |
729 | struct input_iterator_wrapper_nocopy : input_iterator_wrapper<T> | |
730 | { | |
731 | using input_iterator_wrapper<T>::input_iterator_wrapper; | |
732 | ||
733 | input_iterator_wrapper_nocopy() | |
734 | : input_iterator_wrapper<T>(nullptr, nullptr) | |
735 | { } | |
736 | ||
737 | input_iterator_wrapper_nocopy(const input_iterator_wrapper_nocopy&) = delete; | |
738 | input_iterator_wrapper_nocopy& | |
739 | operator=(const input_iterator_wrapper_nocopy&) = delete; | |
740 | ||
741 | input_iterator_wrapper_nocopy(input_iterator_wrapper_nocopy&&) = default; | |
742 | input_iterator_wrapper_nocopy& | |
743 | operator=(input_iterator_wrapper_nocopy&&) = default; | |
744 | ||
745 | using input_iterator_wrapper<T>::operator++; | |
746 | ||
747 | input_iterator_wrapper_nocopy& | |
748 | operator++() | |
749 | { | |
750 | input_iterator_wrapper<T>::operator++(); | |
751 | return *this; | |
752 | } | |
753 | }; | |
754 | ||
6d0dff49 JW |
755 | // A type meeting the minimum std::range requirements |
756 | template<typename T, template<typename> class Iter> | |
757 | class test_range | |
758 | { | |
4512b7d8 PP |
759 | // Exposes the protected default constructor of Iter<T> if needed. This |
760 | // is needed only when Iter is input_iterator_wrapper or | |
761 | // output_iterator_wrapper, because legacy forward iterators and beyond | |
762 | // are already default constructible. | |
6d0dff49 JW |
763 | struct iterator : Iter<T> |
764 | { | |
765 | using Iter<T>::Iter; | |
766 | ||
6d0dff49 JW |
767 | using Iter<T>::operator++; |
768 | ||
769 | iterator& operator++() { Iter<T>::operator++(); return *this; } | |
770 | }; | |
771 | ||
772 | template<typename I> | |
773 | struct sentinel | |
774 | { | |
775 | T* end; | |
776 | ||
5cd2e126 | 777 | friend bool operator==(const sentinel& s, const I& i) noexcept |
6d0dff49 | 778 | { return s.end == i.ptr; } |
5cd2e126 JW |
779 | |
780 | friend auto operator-(const sentinel& s, const I& i) noexcept | |
781 | requires std::random_access_iterator<I> | |
782 | { return s.end - i.ptr; } | |
783 | ||
784 | friend auto operator-(const I& i, const sentinel& s) noexcept | |
785 | requires std::random_access_iterator<I> | |
786 | { return i.ptr - s.end; } | |
6d0dff49 JW |
787 | }; |
788 | ||
26af9cd8 | 789 | protected: |
6d0dff49 JW |
790 | auto |
791 | get_iterator(T* p) | |
792 | { | |
a31517cb | 793 | if constexpr (std::default_initializable<Iter<T>>) |
6d0dff49 JW |
794 | return Iter<T>(p, &bounds); |
795 | else | |
796 | return iterator(p, &bounds); | |
797 | } | |
798 | ||
799 | public: | |
800 | test_range(T* first, T* last) : bounds(first, last) | |
801 | { } | |
802 | ||
803 | template<std::size_t N> | |
804 | explicit | |
805 | test_range(T (&arr)[N]) : test_range(arr, arr+N) | |
806 | { } | |
807 | ||
808 | auto begin() & { return get_iterator(bounds.first); } | |
809 | ||
810 | auto end() & | |
811 | { | |
812 | using I = decltype(get_iterator(bounds.last)); | |
6e5a1963 | 813 | return sentinel<I>{bounds.last}; |
6d0dff49 JW |
814 | } |
815 | ||
816 | typename Iter<T>::ContainerType bounds; | |
817 | }; | |
818 | ||
328b52d6 JW |
819 | template<typename T> |
820 | using test_contiguous_range | |
821 | = test_range<T, contiguous_iterator_wrapper>; | |
822 | template<typename T> | |
823 | using test_random_access_range | |
824 | = test_range<T, random_access_iterator_wrapper>; | |
825 | template<typename T> | |
826 | using test_bidirectional_range | |
827 | = test_range<T, bidirectional_iterator_wrapper>; | |
828 | template<typename T> | |
829 | using test_forward_range | |
830 | = test_range<T, forward_iterator_wrapper>; | |
831 | template<typename T> | |
832 | using test_input_range | |
833 | = test_range<T, input_iterator_wrapper>; | |
834 | template<typename T> | |
835 | using test_output_range | |
836 | = test_range<T, output_iterator_wrapper>; | |
837 | ||
6d0dff49 JW |
838 | // A type meeting the minimum std::sized_range requirements |
839 | template<typename T, template<typename> class Iter> | |
840 | struct test_sized_range : test_range<T, Iter> | |
841 | { | |
842 | using test_range<T, Iter>::test_range; | |
843 | ||
844 | std::size_t size() const noexcept | |
845 | { return this->bounds.size(); } | |
846 | }; | |
328b52d6 JW |
847 | |
848 | template<typename T> | |
849 | using test_contiguous_sized_range | |
850 | = test_sized_range<T, contiguous_iterator_wrapper>; | |
851 | template<typename T> | |
852 | using test_random_access_sized_range | |
853 | = test_sized_range<T, random_access_iterator_wrapper>; | |
854 | template<typename T> | |
855 | using test_bidirectional_sized_range | |
856 | = test_sized_range<T, bidirectional_iterator_wrapper>; | |
857 | template<typename T> | |
858 | using test_forward_sized_range | |
859 | = test_sized_range<T, forward_iterator_wrapper>; | |
860 | template<typename T> | |
861 | using test_input_sized_range | |
862 | = test_sized_range<T, input_iterator_wrapper>; | |
863 | template<typename T> | |
864 | using test_output_sized_range | |
865 | = test_sized_range<T, output_iterator_wrapper>; | |
b5b2e387 | 866 | |
26af9cd8 PP |
867 | // A type meeting the minimum std::sized_range requirements, and whose end() |
868 | // returns a sized sentinel. | |
869 | template<typename T, template<typename> class Iter> | |
870 | struct test_sized_range_sized_sent : test_sized_range<T, Iter> | |
871 | { | |
872 | using test_sized_range<T, Iter>::test_sized_range; | |
873 | ||
874 | template<typename I> | |
875 | struct sentinel | |
876 | { | |
877 | T* end; | |
878 | ||
879 | friend bool operator==(const sentinel& s, const I& i) noexcept | |
880 | { return s.end == i.ptr; } | |
881 | ||
882 | friend std::iter_difference_t<I> | |
883 | operator-(const sentinel& s, const I& i) noexcept | |
884 | { return s.end - i.ptr; } | |
885 | ||
886 | friend std::iter_difference_t<I> | |
887 | operator-(const I& i, const sentinel& s) noexcept | |
888 | { return i.ptr - s.end; } | |
889 | }; | |
890 | ||
891 | auto end() & | |
892 | { | |
893 | using I = decltype(this->get_iterator(this->bounds.last)); | |
894 | return sentinel<I>{this->bounds.last}; | |
895 | } | |
896 | }; | |
897 | ||
68be73fc | 898 | // test_range and test_sized_range do not own their elements, so they model |
15411a64 JW |
899 | // std::ranges::borrowed_range. This file does not define specializations of |
900 | // std::ranges::enable_borrowed_range, so that individual tests can decide | |
68be73fc JW |
901 | // whether or not to do so. |
902 | // This is also true for test_container, although only when it has forward | |
903 | // iterators (because output_iterator_wrapper and input_iterator_wrapper are | |
904 | // not default constructible so do not model std::input_or_output_iterator). | |
b9e35ee6 JW |
905 | |
906 | ||
907 | // Test for basic properties of C++20 16.3.3.6 [customization.point.object]. | |
908 | template<typename T> | |
909 | constexpr bool | |
910 | is_customization_point_object(T& obj) noexcept | |
911 | { | |
912 | // A [CPO] is a function object with a literal class type. | |
913 | static_assert( std::is_class_v<T> || std::is_union_v<T> ); | |
914 | static_assert( __is_literal_type(T) ); | |
915 | // The type of a [CPO], ignoring cv-qualifiers, shall model semiregular. | |
916 | static_assert( std::semiregular<std::remove_cv_t<T>> ); | |
917 | ||
918 | return true; | |
919 | } | |
920 | ||
6d0dff49 JW |
921 | #endif // C++20 |
922 | } // namespace __gnu_test | |
923 | #endif // _TESTSUITE_ITERATORS |