]>
Commit | Line | Data |
---|---|---|
278d4cc4 | 1 | // -*- C++ -*- |
f92ab29f | 2 | // Iterator Wrappers for the C++ library testsuite. |
278d4cc4 | 3 | // |
8d9254fc | 4 | // Copyright (C) 2004-2020 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 |
445877a9 | 125 | : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&> |
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; | |
178 | #else | |
179 | private: | |
180 | template<typename U> | |
181 | void operator,(const U&) const; | |
182 | #endif | |
278d4cc4 CJ |
183 | }; |
184 | ||
d67be443 JW |
185 | #if __cplusplus >= 201103L |
186 | template<typename T, typename U> | |
187 | void operator,(const T&, const output_iterator_wrapper<U>&) = delete; | |
188 | #endif | |
189 | ||
5211593c | 190 | #if __cplusplus >= 201103L |
9921ac3d JW |
191 | using std::remove_cv; |
192 | #else | |
e112d53a JW |
193 | template<typename T> struct remove_cv { typedef T type; }; |
194 | template<typename T> struct remove_cv<const T> { typedef T type; }; | |
195 | template<typename T> struct remove_cv<volatile T> { typedef T type; }; | |
196 | template<typename T> struct remove_cv<const volatile T> { typedef T type; }; | |
9921ac3d | 197 | #endif |
e112d53a | 198 | |
278d4cc4 CJ |
199 | /** |
200 | * @brief input_iterator wrapper for pointer | |
f92ab29f | 201 | * |
278d4cc4 CJ |
202 | * This class takes a pointer and wraps it to provide exactly |
203 | * the requirements of a input_iterator. It should not be | |
f7fbb003 | 204 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
205 | */ |
206 | template<class T> | |
65be6ddd | 207 | class input_iterator_wrapper |
e112d53a JW |
208 | : public std::iterator<std::input_iterator_tag, typename remove_cv<T>::type, |
209 | std::ptrdiff_t, T*, T&> | |
278d4cc4 | 210 | { |
118158b6 JW |
211 | struct post_inc_proxy |
212 | { | |
213 | struct deref_proxy | |
214 | { | |
215 | T* ptr; | |
216 | operator const T&() const { return *ptr; } | |
217 | } p; | |
218 | ||
219 | deref_proxy operator*() const { return p; } | |
220 | }; | |
221 | ||
278d4cc4 | 222 | protected: |
0a70fb87 | 223 | input_iterator_wrapper() : ptr(0), SharedInfo(0) |
278d4cc4 CJ |
224 | { } |
225 | ||
226 | public: | |
227 | typedef BoundsContainer<T> ContainerType; | |
228 | T* ptr; | |
229 | ContainerType* SharedInfo; | |
230 | ||
231 | input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) | |
65be6ddd | 232 | : ptr(_ptr), SharedInfo(SharedInfo_in) |
278d4cc4 | 233 | { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); } |
f92ab29f | 234 | |
0a70fb87 JW |
235 | #if __cplusplus >= 201103L |
236 | input_iterator_wrapper(const input_iterator_wrapper&) = default; | |
237 | ||
238 | input_iterator_wrapper& | |
239 | operator=(const input_iterator_wrapper&) = default; | |
240 | #endif | |
278d4cc4 CJ |
241 | |
242 | bool | |
243 | operator==(const input_iterator_wrapper& in) const | |
244 | { | |
8fc81078 | 245 | ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo); |
278d4cc4 CJ |
246 | ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first); |
247 | return ptr == in.ptr; | |
248 | } | |
249 | ||
250 | bool | |
251 | operator!=(const input_iterator_wrapper& in) const | |
252 | { | |
253 | return !(*this == in); | |
254 | } | |
255 | ||
256 | T& | |
257 | operator*() const | |
258 | { | |
259 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
260 | ITERATOR_VERIFY(ptr >= SharedInfo->first); | |
261 | return *ptr; | |
262 | } | |
263 | ||
264 | T* | |
265 | operator->() const | |
266 | { | |
267 | return &**this; | |
268 | } | |
269 | ||
278d4cc4 CJ |
270 | input_iterator_wrapper& |
271 | operator++() | |
272 | { | |
273 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
274 | ITERATOR_VERIFY(ptr>=SharedInfo->first); | |
275 | ptr++; | |
276 | SharedInfo->first=ptr; | |
277 | return *this; | |
278 | } | |
279 | ||
118158b6 | 280 | post_inc_proxy |
278d4cc4 CJ |
281 | operator++(int) |
282 | { | |
118158b6 | 283 | post_inc_proxy tmp = { { ptr } }; |
278d4cc4 | 284 | ++*this; |
118158b6 | 285 | return tmp; |
278d4cc4 | 286 | } |
f970a17d JW |
287 | |
288 | #if __cplusplus >= 201103L | |
289 | template<typename U> | |
290 | void operator,(const U&) const = delete; | |
291 | #else | |
292 | private: | |
293 | template<typename U> | |
294 | void operator,(const U&) const; | |
295 | #endif | |
278d4cc4 CJ |
296 | }; |
297 | ||
d67be443 JW |
298 | #if __cplusplus >= 201103L |
299 | template<typename T, typename U> | |
300 | void operator,(const T&, const input_iterator_wrapper<U>&) = delete; | |
301 | #endif | |
278d4cc4 CJ |
302 | |
303 | /** | |
304 | * @brief forward_iterator wrapper for pointer | |
f92ab29f | 305 | * |
278d4cc4 CJ |
306 | * This class takes a pointer and wraps it to provide exactly |
307 | * the requirements of a forward_iterator. It should not be | |
f7fbb003 | 308 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
309 | */ |
310 | template<class T> | |
65be6ddd | 311 | struct forward_iterator_wrapper : public input_iterator_wrapper<T> |
278d4cc4 CJ |
312 | { |
313 | typedef BoundsContainer<T> ContainerType; | |
314 | typedef std::forward_iterator_tag iterator_category; | |
0a70fb87 | 315 | |
278d4cc4 | 316 | forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 317 | : input_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 | 318 | { } |
f92ab29f | 319 | |
0a70fb87 | 320 | forward_iterator_wrapper() |
278d4cc4 CJ |
321 | { } |
322 | ||
0a70fb87 JW |
323 | #if __cplusplus >= 201103L |
324 | forward_iterator_wrapper(const forward_iterator_wrapper&) = default; | |
325 | ||
326 | forward_iterator_wrapper& | |
327 | operator=(const forward_iterator_wrapper&) = default; | |
328 | #endif | |
278d4cc4 CJ |
329 | |
330 | T& | |
331 | operator*() const | |
332 | { | |
333 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
334 | return *(this->ptr); | |
335 | } | |
336 | ||
337 | T* | |
338 | operator->() const | |
339 | { return &**this; } | |
340 | ||
341 | forward_iterator_wrapper& | |
342 | operator++() | |
343 | { | |
344 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
345 | this->ptr++; | |
346 | return *this; | |
347 | } | |
348 | ||
349 | forward_iterator_wrapper | |
350 | operator++(int) | |
351 | { | |
352 | forward_iterator_wrapper<T> tmp = *this; | |
353 | ++*this; | |
354 | return tmp; | |
355 | } | |
e94f2542 JW |
356 | |
357 | #if __cplusplus >= 201402L | |
358 | bool | |
359 | operator==(const forward_iterator_wrapper& it) const noexcept | |
360 | { | |
361 | // Since C++14 value-initialized forward iterators are comparable. | |
362 | if (this->SharedInfo == nullptr || it.SharedInfo == nullptr) | |
363 | return this->SharedInfo == it.SharedInfo && this->ptr == it.ptr; | |
364 | ||
365 | const input_iterator_wrapper<T>& base_this = *this; | |
366 | const input_iterator_wrapper<T>& base_that = it; | |
367 | return base_this == base_that; | |
368 | } | |
369 | ||
370 | bool | |
371 | operator!=(const forward_iterator_wrapper& it) const noexcept | |
372 | { | |
373 | return !(*this == it); | |
374 | } | |
375 | #endif | |
f970a17d | 376 | }; |
278d4cc4 CJ |
377 | |
378 | /** | |
379 | * @brief bidirectional_iterator wrapper for pointer | |
f92ab29f | 380 | * |
278d4cc4 | 381 | * This class takes a pointer and wraps it to provide exactly |
ac2dca4d | 382 | * the requirements of a bidirectional_iterator. It should not be |
f7fbb003 | 383 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
384 | */ |
385 | template<class T> | |
65be6ddd | 386 | struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T> |
278d4cc4 CJ |
387 | { |
388 | typedef BoundsContainer<T> ContainerType; | |
389 | typedef std::bidirectional_iterator_tag iterator_category; | |
0a70fb87 | 390 | |
278d4cc4 | 391 | bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 392 | : forward_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 CJ |
393 | { } |
394 | ||
0a70fb87 JW |
395 | bidirectional_iterator_wrapper() |
396 | : forward_iterator_wrapper<T>() | |
278d4cc4 CJ |
397 | { } |
398 | ||
0a70fb87 JW |
399 | #if __cplusplus >= 201103L |
400 | bidirectional_iterator_wrapper( | |
401 | const bidirectional_iterator_wrapper&) = default; | |
278d4cc4 CJ |
402 | |
403 | bidirectional_iterator_wrapper& | |
0a70fb87 JW |
404 | operator=(const bidirectional_iterator_wrapper&) = default; |
405 | #endif | |
f92ab29f | 406 | |
278d4cc4 CJ |
407 | bidirectional_iterator_wrapper& |
408 | operator++() | |
409 | { | |
410 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
411 | this->ptr++; | |
412 | return *this; | |
413 | } | |
414 | ||
415 | bidirectional_iterator_wrapper | |
416 | operator++(int) | |
417 | { | |
418 | bidirectional_iterator_wrapper<T> tmp = *this; | |
419 | ++*this; | |
420 | return tmp; | |
421 | } | |
422 | ||
f92ab29f | 423 | bidirectional_iterator_wrapper& |
278d4cc4 CJ |
424 | operator--() |
425 | { | |
426 | ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); | |
427 | this->ptr--; | |
428 | return *this; | |
429 | } | |
430 | ||
431 | bidirectional_iterator_wrapper | |
432 | operator--(int) | |
f92ab29f | 433 | { |
278d4cc4 CJ |
434 | bidirectional_iterator_wrapper<T> tmp = *this; |
435 | --*this; | |
436 | return tmp; | |
437 | } | |
f970a17d | 438 | }; |
278d4cc4 CJ |
439 | |
440 | /** | |
441 | * @brief random_access_iterator wrapper for pointer | |
f92ab29f | 442 | * |
278d4cc4 | 443 | * This class takes a pointer and wraps it to provide exactly |
ac2dca4d | 444 | * the requirements of a random_access_iterator. It should not be |
f7fbb003 | 445 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
446 | */ |
447 | template<class T> | |
f92ab29f | 448 | struct random_access_iterator_wrapper |
65be6ddd | 449 | : public bidirectional_iterator_wrapper<T> |
278d4cc4 CJ |
450 | { |
451 | typedef BoundsContainer<T> ContainerType; | |
452 | typedef std::random_access_iterator_tag iterator_category; | |
0a70fb87 | 453 | |
278d4cc4 | 454 | random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 455 | : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 CJ |
456 | { } |
457 | ||
0a70fb87 JW |
458 | random_access_iterator_wrapper() |
459 | : bidirectional_iterator_wrapper<T>() | |
278d4cc4 CJ |
460 | { } |
461 | ||
0a70fb87 JW |
462 | #if __cplusplus >= 201103L |
463 | random_access_iterator_wrapper( | |
464 | const random_access_iterator_wrapper&) = default; | |
278d4cc4 CJ |
465 | |
466 | random_access_iterator_wrapper& | |
0a70fb87 JW |
467 | operator=(const random_access_iterator_wrapper&) = default; |
468 | #endif | |
278d4cc4 CJ |
469 | |
470 | random_access_iterator_wrapper& | |
471 | operator++() | |
472 | { | |
473 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
474 | this->ptr++; | |
475 | return *this; | |
476 | } | |
477 | ||
478 | random_access_iterator_wrapper | |
479 | operator++(int) | |
480 | { | |
481 | random_access_iterator_wrapper<T> tmp = *this; | |
482 | ++*this; | |
483 | return tmp; | |
484 | } | |
485 | ||
486 | random_access_iterator_wrapper& | |
487 | operator--() | |
488 | { | |
489 | ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); | |
490 | this->ptr--; | |
491 | return *this; | |
492 | } | |
493 | ||
494 | random_access_iterator_wrapper | |
495 | operator--(int) | |
496 | { | |
497 | random_access_iterator_wrapper<T> tmp = *this; | |
561e7a36 | 498 | --*this; |
278d4cc4 CJ |
499 | return tmp; |
500 | } | |
501 | ||
502 | random_access_iterator_wrapper& | |
445877a9 | 503 | operator+=(std::ptrdiff_t n) |
278d4cc4 CJ |
504 | { |
505 | if(n > 0) | |
506 | { | |
507 | ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr); | |
508 | this->ptr += n; | |
509 | } | |
510 | else | |
511 | { | |
e1008cd1 | 512 | ITERATOR_VERIFY(-n <= this->ptr - this->SharedInfo->first); |
278d4cc4 CJ |
513 | this->ptr += n; |
514 | } | |
515 | return *this; | |
516 | } | |
517 | ||
278d4cc4 | 518 | random_access_iterator_wrapper& |
445877a9 | 519 | operator-=(std::ptrdiff_t n) |
278d4cc4 CJ |
520 | { return *this += -n; } |
521 | ||
522 | random_access_iterator_wrapper | |
445877a9 | 523 | operator-(std::ptrdiff_t n) const |
278d4cc4 CJ |
524 | { |
525 | random_access_iterator_wrapper<T> tmp = *this; | |
526 | return tmp -= n; | |
527 | } | |
528 | ||
445877a9 | 529 | std::ptrdiff_t |
561e7a36 | 530 | operator-(const random_access_iterator_wrapper<T>& in) const |
278d4cc4 CJ |
531 | { |
532 | ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); | |
533 | return this->ptr - in.ptr; | |
534 | } | |
535 | ||
536 | T& | |
445877a9 | 537 | operator[](std::ptrdiff_t n) const |
561e7a36 | 538 | { return *(*this + n); } |
278d4cc4 CJ |
539 | |
540 | bool | |
541 | operator<(const random_access_iterator_wrapper<T>& in) const | |
542 | { | |
543 | ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); | |
544 | return this->ptr < in.ptr; | |
545 | } | |
546 | ||
547 | bool | |
548 | operator>(const random_access_iterator_wrapper<T>& in) const | |
549 | { | |
550 | return in < *this; | |
551 | } | |
552 | ||
553 | bool | |
554 | operator>=(const random_access_iterator_wrapper<T>& in) const | |
555 | { | |
556 | return !(*this < in); | |
557 | } | |
558 | ||
f92ab29f | 559 | bool |
278d4cc4 CJ |
560 | operator<=(const random_access_iterator_wrapper<T>& in) const |
561 | { | |
562 | return !(*this > in); | |
563 | } | |
f970a17d | 564 | }; |
278d4cc4 | 565 | |
561e7a36 PC |
566 | template<typename T> |
567 | random_access_iterator_wrapper<T> | |
445877a9 | 568 | operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n) |
561e7a36 PC |
569 | { return it += n; } |
570 | ||
571 | template<typename T> | |
572 | random_access_iterator_wrapper<T> | |
f92ab29f | 573 | operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it) |
561e7a36 PC |
574 | { return it += n; } |
575 | ||
278d4cc4 | 576 | |
f92ab29f | 577 | /** |
278d4cc4 CJ |
578 | * @brief A container-type class for holding iterator wrappers |
579 | * test_container takes two parameters, a class T and an iterator | |
580 | * wrapper templated by T (for example forward_iterator_wrapper<T>. | |
f92ab29f | 581 | * It takes two pointers representing a range and presents them as |
278d4cc4 CJ |
582 | * a container of iterators. |
583 | */ | |
060269c4 | 584 | template <class T, template<class TT> class ItType> |
278d4cc4 CJ |
585 | struct test_container |
586 | { | |
587 | typename ItType<T>::ContainerType bounds; | |
9921ac3d | 588 | |
4e66b02b | 589 | test_container(T* _first, T* _last) : bounds(_first, _last) |
278d4cc4 CJ |
590 | { } |
591 | ||
3ebacabd | 592 | #if __cplusplus >= 201103L |
4e66b02b JW |
593 | template<std::size_t N> |
594 | explicit | |
595 | test_container(T (&arr)[N]) : test_container(arr, arr+N) | |
596 | { } | |
3ebacabd JW |
597 | #endif |
598 | ||
278d4cc4 CJ |
599 | ItType<T> |
600 | it(int pos) | |
601 | { | |
13feb023 | 602 | ITERATOR_VERIFY(pos >= 0 && (unsigned)pos <= size()); |
278d4cc4 CJ |
603 | return ItType<T>(bounds.first + pos, &bounds); |
604 | } | |
605 | ||
606 | ItType<T> | |
607 | it(T* pos) | |
608 | { | |
609 | ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last); | |
610 | return ItType<T>(pos, &bounds); | |
611 | } | |
612 | ||
c2240038 CJ |
613 | const T& |
614 | val(int pos) | |
615 | { return (bounds.first)[pos]; } | |
616 | ||
278d4cc4 CJ |
617 | ItType<T> |
618 | begin() | |
619 | { return it(bounds.first); } | |
620 | ||
621 | ItType<T> | |
622 | end() | |
623 | { return it(bounds.last); } | |
ed920373 JW |
624 | |
625 | std::size_t | |
626 | size() const | |
9921ac3d | 627 | { return bounds.size(); } |
4e66b02b | 628 | }; |
6d0dff49 | 629 | |
e1008cd1 JW |
630 | #if __cplusplus >= 201103L |
631 | template<typename T> | |
632 | using output_container | |
633 | = test_container<T, output_iterator_wrapper>; | |
634 | ||
635 | template<typename T> | |
636 | using input_container | |
637 | = test_container<T, input_iterator_wrapper>; | |
638 | ||
639 | template<typename T> | |
640 | using forward_container | |
641 | = test_container<T, forward_iterator_wrapper>; | |
642 | ||
643 | template<typename T> | |
644 | using bidirectional_container | |
645 | = test_container<T, bidirectional_iterator_wrapper>; | |
646 | ||
647 | template<typename T> | |
648 | using random_access_container | |
649 | = test_container<T, random_access_iterator_wrapper>; | |
650 | #endif | |
651 | ||
6d0dff49 JW |
652 | #if __cplusplus > 201703L |
653 | template<typename T> | |
654 | struct contiguous_iterator_wrapper | |
655 | : random_access_iterator_wrapper<T> | |
656 | { | |
657 | using random_access_iterator_wrapper<T>::random_access_iterator_wrapper; | |
658 | ||
659 | using iterator_concept = std::contiguous_iterator_tag; | |
660 | ||
661 | contiguous_iterator_wrapper& | |
662 | operator++() | |
663 | { | |
664 | random_access_iterator_wrapper<T>::operator++(); | |
665 | return *this; | |
666 | } | |
667 | ||
668 | contiguous_iterator_wrapper& | |
669 | operator--() | |
670 | { | |
671 | random_access_iterator_wrapper<T>::operator--(); | |
672 | return *this; | |
673 | } | |
674 | ||
675 | contiguous_iterator_wrapper | |
676 | operator++(int) | |
677 | { | |
678 | auto tmp = *this; | |
679 | ++*this; | |
680 | return tmp; | |
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+=(std::ptrdiff_t n) | |
693 | { | |
694 | random_access_iterator_wrapper<T>::operator+=(n); | |
695 | return *this; | |
696 | } | |
697 | ||
698 | friend contiguous_iterator_wrapper | |
699 | operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n) | |
700 | { return iter += n; } | |
701 | ||
702 | friend contiguous_iterator_wrapper | |
703 | operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter) | |
704 | { return iter += n; } | |
705 | ||
706 | contiguous_iterator_wrapper& | |
707 | operator-=(std::ptrdiff_t n) | |
708 | { return *this += -n; } | |
709 | ||
710 | friend contiguous_iterator_wrapper | |
711 | operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n) | |
712 | { return iter -= n; } | |
713 | }; | |
714 | ||
e1008cd1 JW |
715 | template<typename T> |
716 | using contiguous_container | |
717 | = test_container<T, contiguous_iterator_wrapper>; | |
718 | ||
d6d4b339 PP |
719 | // A move-only input iterator type. |
720 | template<typename T> | |
721 | struct input_iterator_wrapper_nocopy : input_iterator_wrapper<T> | |
722 | { | |
723 | using input_iterator_wrapper<T>::input_iterator_wrapper; | |
724 | ||
725 | input_iterator_wrapper_nocopy() | |
726 | : input_iterator_wrapper<T>(nullptr, nullptr) | |
727 | { } | |
728 | ||
729 | input_iterator_wrapper_nocopy(const input_iterator_wrapper_nocopy&) = delete; | |
730 | input_iterator_wrapper_nocopy& | |
731 | operator=(const input_iterator_wrapper_nocopy&) = delete; | |
732 | ||
733 | input_iterator_wrapper_nocopy(input_iterator_wrapper_nocopy&&) = default; | |
734 | input_iterator_wrapper_nocopy& | |
735 | operator=(input_iterator_wrapper_nocopy&&) = default; | |
736 | ||
737 | using input_iterator_wrapper<T>::operator++; | |
738 | ||
739 | input_iterator_wrapper_nocopy& | |
740 | operator++() | |
741 | { | |
742 | input_iterator_wrapper<T>::operator++(); | |
743 | return *this; | |
744 | } | |
745 | }; | |
746 | ||
6d0dff49 JW |
747 | // A type meeting the minimum std::range requirements |
748 | template<typename T, template<typename> class Iter> | |
749 | class test_range | |
750 | { | |
4512b7d8 PP |
751 | // Exposes the protected default constructor of Iter<T> if needed. This |
752 | // is needed only when Iter is input_iterator_wrapper or | |
753 | // output_iterator_wrapper, because legacy forward iterators and beyond | |
754 | // are already default constructible. | |
6d0dff49 JW |
755 | struct iterator : Iter<T> |
756 | { | |
757 | using Iter<T>::Iter; | |
758 | ||
6d0dff49 JW |
759 | using Iter<T>::operator++; |
760 | ||
761 | iterator& operator++() { Iter<T>::operator++(); return *this; } | |
762 | }; | |
763 | ||
764 | template<typename I> | |
765 | struct sentinel | |
766 | { | |
767 | T* end; | |
768 | ||
5cd2e126 | 769 | friend bool operator==(const sentinel& s, const I& i) noexcept |
6d0dff49 | 770 | { return s.end == i.ptr; } |
5cd2e126 JW |
771 | |
772 | friend auto operator-(const sentinel& s, const I& i) noexcept | |
773 | requires std::random_access_iterator<I> | |
774 | { return s.end - i.ptr; } | |
775 | ||
776 | friend auto operator-(const I& i, const sentinel& s) noexcept | |
777 | requires std::random_access_iterator<I> | |
778 | { return i.ptr - s.end; } | |
6d0dff49 JW |
779 | }; |
780 | ||
26af9cd8 | 781 | protected: |
6d0dff49 JW |
782 | auto |
783 | get_iterator(T* p) | |
784 | { | |
a31517cb | 785 | if constexpr (std::default_initializable<Iter<T>>) |
6d0dff49 JW |
786 | return Iter<T>(p, &bounds); |
787 | else | |
788 | return iterator(p, &bounds); | |
789 | } | |
790 | ||
791 | public: | |
792 | test_range(T* first, T* last) : bounds(first, last) | |
793 | { } | |
794 | ||
795 | template<std::size_t N> | |
796 | explicit | |
797 | test_range(T (&arr)[N]) : test_range(arr, arr+N) | |
798 | { } | |
799 | ||
800 | auto begin() & { return get_iterator(bounds.first); } | |
801 | ||
802 | auto end() & | |
803 | { | |
804 | using I = decltype(get_iterator(bounds.last)); | |
6e5a1963 | 805 | return sentinel<I>{bounds.last}; |
6d0dff49 JW |
806 | } |
807 | ||
808 | typename Iter<T>::ContainerType bounds; | |
809 | }; | |
810 | ||
328b52d6 JW |
811 | template<typename T> |
812 | using test_contiguous_range | |
813 | = test_range<T, contiguous_iterator_wrapper>; | |
814 | template<typename T> | |
815 | using test_random_access_range | |
816 | = test_range<T, random_access_iterator_wrapper>; | |
817 | template<typename T> | |
818 | using test_bidirectional_range | |
819 | = test_range<T, bidirectional_iterator_wrapper>; | |
820 | template<typename T> | |
821 | using test_forward_range | |
822 | = test_range<T, forward_iterator_wrapper>; | |
823 | template<typename T> | |
824 | using test_input_range | |
825 | = test_range<T, input_iterator_wrapper>; | |
826 | template<typename T> | |
827 | using test_output_range | |
828 | = test_range<T, output_iterator_wrapper>; | |
829 | ||
6d0dff49 JW |
830 | // A type meeting the minimum std::sized_range requirements |
831 | template<typename T, template<typename> class Iter> | |
832 | struct test_sized_range : test_range<T, Iter> | |
833 | { | |
834 | using test_range<T, Iter>::test_range; | |
835 | ||
836 | std::size_t size() const noexcept | |
837 | { return this->bounds.size(); } | |
838 | }; | |
328b52d6 JW |
839 | |
840 | template<typename T> | |
841 | using test_contiguous_sized_range | |
842 | = test_sized_range<T, contiguous_iterator_wrapper>; | |
843 | template<typename T> | |
844 | using test_random_access_sized_range | |
845 | = test_sized_range<T, random_access_iterator_wrapper>; | |
846 | template<typename T> | |
847 | using test_bidirectional_sized_range | |
848 | = test_sized_range<T, bidirectional_iterator_wrapper>; | |
849 | template<typename T> | |
850 | using test_forward_sized_range | |
851 | = test_sized_range<T, forward_iterator_wrapper>; | |
852 | template<typename T> | |
853 | using test_input_sized_range | |
854 | = test_sized_range<T, input_iterator_wrapper>; | |
855 | template<typename T> | |
856 | using test_output_sized_range | |
857 | = test_sized_range<T, output_iterator_wrapper>; | |
b5b2e387 | 858 | |
26af9cd8 PP |
859 | // A type meeting the minimum std::sized_range requirements, and whose end() |
860 | // returns a sized sentinel. | |
861 | template<typename T, template<typename> class Iter> | |
862 | struct test_sized_range_sized_sent : test_sized_range<T, Iter> | |
863 | { | |
864 | using test_sized_range<T, Iter>::test_sized_range; | |
865 | ||
866 | template<typename I> | |
867 | struct sentinel | |
868 | { | |
869 | T* end; | |
870 | ||
871 | friend bool operator==(const sentinel& s, const I& i) noexcept | |
872 | { return s.end == i.ptr; } | |
873 | ||
874 | friend std::iter_difference_t<I> | |
875 | operator-(const sentinel& s, const I& i) noexcept | |
876 | { return s.end - i.ptr; } | |
877 | ||
878 | friend std::iter_difference_t<I> | |
879 | operator-(const I& i, const sentinel& s) noexcept | |
880 | { return i.ptr - s.end; } | |
881 | }; | |
882 | ||
883 | auto end() & | |
884 | { | |
885 | using I = decltype(this->get_iterator(this->bounds.last)); | |
886 | return sentinel<I>{this->bounds.last}; | |
887 | } | |
888 | }; | |
889 | ||
68be73fc | 890 | // test_range and test_sized_range do not own their elements, so they model |
15411a64 JW |
891 | // std::ranges::borrowed_range. This file does not define specializations of |
892 | // std::ranges::enable_borrowed_range, so that individual tests can decide | |
68be73fc JW |
893 | // whether or not to do so. |
894 | // This is also true for test_container, although only when it has forward | |
895 | // iterators (because output_iterator_wrapper and input_iterator_wrapper are | |
896 | // not default constructible so do not model std::input_or_output_iterator). | |
6d0dff49 JW |
897 | #endif // C++20 |
898 | } // namespace __gnu_test | |
899 | #endif // _TESTSUITE_ITERATORS |