]>
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 CJ |
126 | { |
127 | typedef OutputContainer<T> ContainerType; | |
128 | T* ptr; | |
129 | ContainerType* SharedInfo; | |
130 | ||
131 | output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) | |
65be6ddd | 132 | : ptr(_ptr), SharedInfo(SharedInfo_in) |
278d4cc4 CJ |
133 | { |
134 | ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); | |
135 | } | |
f92ab29f | 136 | |
0a70fb87 JW |
137 | #if __cplusplus >= 201103L |
138 | output_iterator_wrapper() = delete; | |
139 | ||
140 | output_iterator_wrapper(const output_iterator_wrapper&) = default; | |
141 | ||
142 | output_iterator_wrapper& | |
143 | operator=(const output_iterator_wrapper&) = default; | |
144 | #endif | |
278d4cc4 CJ |
145 | |
146 | WritableObject<T> | |
147 | operator*() const | |
148 | { | |
149 | ITERATOR_VERIFY(ptr < SharedInfo->last); | |
150 | ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false); | |
151 | return WritableObject<T>(ptr, SharedInfo); | |
152 | } | |
f92ab29f | 153 | |
278d4cc4 CJ |
154 | output_iterator_wrapper& |
155 | operator++() | |
156 | { | |
157 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
561e7a36 | 158 | ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto); |
278d4cc4 | 159 | ptr++; |
561e7a36 | 160 | SharedInfo->incrementedto=ptr; |
278d4cc4 CJ |
161 | return *this; |
162 | } | |
163 | ||
164 | output_iterator_wrapper | |
165 | operator++(int) | |
166 | { | |
167 | output_iterator_wrapper<T> tmp = *this; | |
168 | ++*this; | |
169 | return tmp; | |
170 | } | |
171 | ||
f970a17d JW |
172 | #if __cplusplus >= 201103L |
173 | template<typename U> | |
174 | void operator,(const U&) const = delete; | |
175 | #else | |
176 | private: | |
177 | template<typename U> | |
178 | void operator,(const U&) const; | |
179 | #endif | |
278d4cc4 CJ |
180 | }; |
181 | ||
d67be443 JW |
182 | #if __cplusplus >= 201103L |
183 | template<typename T, typename U> | |
184 | void operator,(const T&, const output_iterator_wrapper<U>&) = delete; | |
185 | #endif | |
186 | ||
5211593c | 187 | #if __cplusplus >= 201103L |
9921ac3d JW |
188 | using std::remove_cv; |
189 | #else | |
e112d53a JW |
190 | template<typename T> struct remove_cv { typedef T type; }; |
191 | template<typename T> struct remove_cv<const T> { typedef T type; }; | |
192 | template<typename T> struct remove_cv<volatile T> { typedef T type; }; | |
193 | template<typename T> struct remove_cv<const volatile T> { typedef T type; }; | |
9921ac3d | 194 | #endif |
e112d53a | 195 | |
278d4cc4 CJ |
196 | /** |
197 | * @brief input_iterator wrapper for pointer | |
f92ab29f | 198 | * |
278d4cc4 CJ |
199 | * This class takes a pointer and wraps it to provide exactly |
200 | * the requirements of a input_iterator. It should not be | |
f7fbb003 | 201 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
202 | */ |
203 | template<class T> | |
65be6ddd | 204 | class input_iterator_wrapper |
e112d53a JW |
205 | : public std::iterator<std::input_iterator_tag, typename remove_cv<T>::type, |
206 | std::ptrdiff_t, T*, T&> | |
278d4cc4 CJ |
207 | { |
208 | protected: | |
0a70fb87 | 209 | input_iterator_wrapper() : ptr(0), SharedInfo(0) |
278d4cc4 CJ |
210 | { } |
211 | ||
212 | public: | |
213 | typedef BoundsContainer<T> ContainerType; | |
214 | T* ptr; | |
215 | ContainerType* SharedInfo; | |
216 | ||
217 | input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) | |
65be6ddd | 218 | : ptr(_ptr), SharedInfo(SharedInfo_in) |
278d4cc4 | 219 | { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); } |
f92ab29f | 220 | |
0a70fb87 JW |
221 | #if __cplusplus >= 201103L |
222 | input_iterator_wrapper(const input_iterator_wrapper&) = default; | |
223 | ||
224 | input_iterator_wrapper& | |
225 | operator=(const input_iterator_wrapper&) = default; | |
226 | #endif | |
278d4cc4 CJ |
227 | |
228 | bool | |
229 | operator==(const input_iterator_wrapper& in) const | |
230 | { | |
8fc81078 | 231 | ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo); |
278d4cc4 CJ |
232 | ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first); |
233 | return ptr == in.ptr; | |
234 | } | |
235 | ||
236 | bool | |
237 | operator!=(const input_iterator_wrapper& in) const | |
238 | { | |
239 | return !(*this == in); | |
240 | } | |
241 | ||
242 | T& | |
243 | operator*() const | |
244 | { | |
245 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
246 | ITERATOR_VERIFY(ptr >= SharedInfo->first); | |
247 | return *ptr; | |
248 | } | |
249 | ||
250 | T* | |
251 | operator->() const | |
252 | { | |
253 | return &**this; | |
254 | } | |
255 | ||
278d4cc4 CJ |
256 | input_iterator_wrapper& |
257 | operator++() | |
258 | { | |
259 | ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); | |
260 | ITERATOR_VERIFY(ptr>=SharedInfo->first); | |
261 | ptr++; | |
262 | SharedInfo->first=ptr; | |
263 | return *this; | |
264 | } | |
265 | ||
266 | void | |
267 | operator++(int) | |
268 | { | |
269 | ++*this; | |
270 | } | |
f970a17d JW |
271 | |
272 | #if __cplusplus >= 201103L | |
273 | template<typename U> | |
274 | void operator,(const U&) const = delete; | |
275 | #else | |
276 | private: | |
277 | template<typename U> | |
278 | void operator,(const U&) const; | |
279 | #endif | |
278d4cc4 CJ |
280 | }; |
281 | ||
d67be443 JW |
282 | #if __cplusplus >= 201103L |
283 | template<typename T, typename U> | |
284 | void operator,(const T&, const input_iterator_wrapper<U>&) = delete; | |
285 | #endif | |
278d4cc4 CJ |
286 | |
287 | /** | |
288 | * @brief forward_iterator wrapper for pointer | |
f92ab29f | 289 | * |
278d4cc4 CJ |
290 | * This class takes a pointer and wraps it to provide exactly |
291 | * the requirements of a forward_iterator. It should not be | |
f7fbb003 | 292 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
293 | */ |
294 | template<class T> | |
65be6ddd | 295 | struct forward_iterator_wrapper : public input_iterator_wrapper<T> |
278d4cc4 CJ |
296 | { |
297 | typedef BoundsContainer<T> ContainerType; | |
298 | typedef std::forward_iterator_tag iterator_category; | |
0a70fb87 | 299 | |
278d4cc4 | 300 | forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 301 | : input_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 | 302 | { } |
f92ab29f | 303 | |
0a70fb87 | 304 | forward_iterator_wrapper() |
278d4cc4 CJ |
305 | { } |
306 | ||
0a70fb87 JW |
307 | #if __cplusplus >= 201103L |
308 | forward_iterator_wrapper(const forward_iterator_wrapper&) = default; | |
309 | ||
310 | forward_iterator_wrapper& | |
311 | operator=(const forward_iterator_wrapper&) = default; | |
312 | #endif | |
278d4cc4 CJ |
313 | |
314 | T& | |
315 | operator*() const | |
316 | { | |
317 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
318 | return *(this->ptr); | |
319 | } | |
320 | ||
321 | T* | |
322 | operator->() const | |
323 | { return &**this; } | |
324 | ||
325 | forward_iterator_wrapper& | |
326 | operator++() | |
327 | { | |
328 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
329 | this->ptr++; | |
330 | return *this; | |
331 | } | |
332 | ||
333 | forward_iterator_wrapper | |
334 | operator++(int) | |
335 | { | |
336 | forward_iterator_wrapper<T> tmp = *this; | |
337 | ++*this; | |
338 | return tmp; | |
339 | } | |
f970a17d | 340 | }; |
278d4cc4 CJ |
341 | |
342 | /** | |
343 | * @brief bidirectional_iterator wrapper for pointer | |
f92ab29f | 344 | * |
278d4cc4 | 345 | * This class takes a pointer and wraps it to provide exactly |
ac2dca4d | 346 | * the requirements of a bidirectional_iterator. It should not be |
f7fbb003 | 347 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
348 | */ |
349 | template<class T> | |
65be6ddd | 350 | struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T> |
278d4cc4 CJ |
351 | { |
352 | typedef BoundsContainer<T> ContainerType; | |
353 | typedef std::bidirectional_iterator_tag iterator_category; | |
0a70fb87 | 354 | |
278d4cc4 | 355 | bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 356 | : forward_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 CJ |
357 | { } |
358 | ||
0a70fb87 JW |
359 | bidirectional_iterator_wrapper() |
360 | : forward_iterator_wrapper<T>() | |
278d4cc4 CJ |
361 | { } |
362 | ||
0a70fb87 JW |
363 | #if __cplusplus >= 201103L |
364 | bidirectional_iterator_wrapper( | |
365 | const bidirectional_iterator_wrapper&) = default; | |
278d4cc4 CJ |
366 | |
367 | bidirectional_iterator_wrapper& | |
0a70fb87 JW |
368 | operator=(const bidirectional_iterator_wrapper&) = default; |
369 | #endif | |
f92ab29f | 370 | |
278d4cc4 CJ |
371 | bidirectional_iterator_wrapper& |
372 | operator++() | |
373 | { | |
374 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
375 | this->ptr++; | |
376 | return *this; | |
377 | } | |
378 | ||
379 | bidirectional_iterator_wrapper | |
380 | operator++(int) | |
381 | { | |
382 | bidirectional_iterator_wrapper<T> tmp = *this; | |
383 | ++*this; | |
384 | return tmp; | |
385 | } | |
386 | ||
f92ab29f | 387 | bidirectional_iterator_wrapper& |
278d4cc4 CJ |
388 | operator--() |
389 | { | |
390 | ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); | |
391 | this->ptr--; | |
392 | return *this; | |
393 | } | |
394 | ||
395 | bidirectional_iterator_wrapper | |
396 | operator--(int) | |
f92ab29f | 397 | { |
278d4cc4 CJ |
398 | bidirectional_iterator_wrapper<T> tmp = *this; |
399 | --*this; | |
400 | return tmp; | |
401 | } | |
f970a17d | 402 | }; |
278d4cc4 CJ |
403 | |
404 | /** | |
405 | * @brief random_access_iterator wrapper for pointer | |
f92ab29f | 406 | * |
278d4cc4 | 407 | * This class takes a pointer and wraps it to provide exactly |
ac2dca4d | 408 | * the requirements of a random_access_iterator. It should not be |
f7fbb003 | 409 | * instantiated directly, but generated from a test_container |
278d4cc4 CJ |
410 | */ |
411 | template<class T> | |
f92ab29f | 412 | struct random_access_iterator_wrapper |
65be6ddd | 413 | : public bidirectional_iterator_wrapper<T> |
278d4cc4 CJ |
414 | { |
415 | typedef BoundsContainer<T> ContainerType; | |
416 | typedef std::random_access_iterator_tag iterator_category; | |
0a70fb87 | 417 | |
278d4cc4 | 418 | random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
65be6ddd | 419 | : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in) |
278d4cc4 CJ |
420 | { } |
421 | ||
0a70fb87 JW |
422 | random_access_iterator_wrapper() |
423 | : bidirectional_iterator_wrapper<T>() | |
278d4cc4 CJ |
424 | { } |
425 | ||
0a70fb87 JW |
426 | #if __cplusplus >= 201103L |
427 | random_access_iterator_wrapper( | |
428 | const random_access_iterator_wrapper&) = default; | |
278d4cc4 CJ |
429 | |
430 | random_access_iterator_wrapper& | |
0a70fb87 JW |
431 | operator=(const random_access_iterator_wrapper&) = default; |
432 | #endif | |
278d4cc4 CJ |
433 | |
434 | random_access_iterator_wrapper& | |
435 | operator++() | |
436 | { | |
437 | ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); | |
438 | this->ptr++; | |
439 | return *this; | |
440 | } | |
441 | ||
442 | random_access_iterator_wrapper | |
443 | operator++(int) | |
444 | { | |
445 | random_access_iterator_wrapper<T> tmp = *this; | |
446 | ++*this; | |
447 | return tmp; | |
448 | } | |
449 | ||
450 | random_access_iterator_wrapper& | |
451 | operator--() | |
452 | { | |
453 | ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); | |
454 | this->ptr--; | |
455 | return *this; | |
456 | } | |
457 | ||
458 | random_access_iterator_wrapper | |
459 | operator--(int) | |
460 | { | |
461 | random_access_iterator_wrapper<T> tmp = *this; | |
561e7a36 | 462 | --*this; |
278d4cc4 CJ |
463 | return tmp; |
464 | } | |
465 | ||
466 | random_access_iterator_wrapper& | |
445877a9 | 467 | operator+=(std::ptrdiff_t n) |
278d4cc4 CJ |
468 | { |
469 | if(n > 0) | |
470 | { | |
471 | ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr); | |
472 | this->ptr += n; | |
473 | } | |
474 | else | |
475 | { | |
476 | ITERATOR_VERIFY(n <= this->ptr - this->SharedInfo->first); | |
477 | this->ptr += n; | |
478 | } | |
479 | return *this; | |
480 | } | |
481 | ||
278d4cc4 | 482 | random_access_iterator_wrapper& |
445877a9 | 483 | operator-=(std::ptrdiff_t n) |
278d4cc4 CJ |
484 | { return *this += -n; } |
485 | ||
486 | random_access_iterator_wrapper | |
445877a9 | 487 | operator-(std::ptrdiff_t n) const |
278d4cc4 CJ |
488 | { |
489 | random_access_iterator_wrapper<T> tmp = *this; | |
490 | return tmp -= n; | |
491 | } | |
492 | ||
445877a9 | 493 | std::ptrdiff_t |
561e7a36 | 494 | operator-(const random_access_iterator_wrapper<T>& in) const |
278d4cc4 CJ |
495 | { |
496 | ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); | |
497 | return this->ptr - in.ptr; | |
498 | } | |
499 | ||
500 | T& | |
445877a9 | 501 | operator[](std::ptrdiff_t n) const |
561e7a36 | 502 | { return *(*this + n); } |
278d4cc4 CJ |
503 | |
504 | bool | |
505 | operator<(const random_access_iterator_wrapper<T>& in) const | |
506 | { | |
507 | ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); | |
508 | return this->ptr < in.ptr; | |
509 | } | |
510 | ||
511 | bool | |
512 | operator>(const random_access_iterator_wrapper<T>& in) const | |
513 | { | |
514 | return in < *this; | |
515 | } | |
516 | ||
517 | bool | |
518 | operator>=(const random_access_iterator_wrapper<T>& in) const | |
519 | { | |
520 | return !(*this < in); | |
521 | } | |
522 | ||
f92ab29f | 523 | bool |
278d4cc4 CJ |
524 | operator<=(const random_access_iterator_wrapper<T>& in) const |
525 | { | |
526 | return !(*this > in); | |
527 | } | |
f970a17d | 528 | }; |
278d4cc4 | 529 | |
561e7a36 PC |
530 | template<typename T> |
531 | random_access_iterator_wrapper<T> | |
445877a9 | 532 | operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n) |
561e7a36 PC |
533 | { return it += n; } |
534 | ||
535 | template<typename T> | |
536 | random_access_iterator_wrapper<T> | |
f92ab29f | 537 | operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it) |
561e7a36 PC |
538 | { return it += n; } |
539 | ||
278d4cc4 | 540 | |
f92ab29f | 541 | /** |
278d4cc4 CJ |
542 | * @brief A container-type class for holding iterator wrappers |
543 | * test_container takes two parameters, a class T and an iterator | |
544 | * wrapper templated by T (for example forward_iterator_wrapper<T>. | |
f92ab29f | 545 | * It takes two pointers representing a range and presents them as |
278d4cc4 CJ |
546 | * a container of iterators. |
547 | */ | |
060269c4 | 548 | template <class T, template<class TT> class ItType> |
278d4cc4 CJ |
549 | struct test_container |
550 | { | |
551 | typename ItType<T>::ContainerType bounds; | |
9921ac3d | 552 | |
4e66b02b | 553 | test_container(T* _first, T* _last) : bounds(_first, _last) |
278d4cc4 CJ |
554 | { } |
555 | ||
3ebacabd | 556 | #if __cplusplus >= 201103L |
4e66b02b JW |
557 | template<std::size_t N> |
558 | explicit | |
559 | test_container(T (&arr)[N]) : test_container(arr, arr+N) | |
560 | { } | |
3ebacabd JW |
561 | #endif |
562 | ||
278d4cc4 CJ |
563 | ItType<T> |
564 | it(int pos) | |
565 | { | |
9921ac3d | 566 | ITERATOR_VERIFY(pos >= 0 && pos <= size()); |
278d4cc4 CJ |
567 | return ItType<T>(bounds.first + pos, &bounds); |
568 | } | |
569 | ||
570 | ItType<T> | |
571 | it(T* pos) | |
572 | { | |
573 | ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last); | |
574 | return ItType<T>(pos, &bounds); | |
575 | } | |
576 | ||
c2240038 CJ |
577 | const T& |
578 | val(int pos) | |
579 | { return (bounds.first)[pos]; } | |
580 | ||
278d4cc4 CJ |
581 | ItType<T> |
582 | begin() | |
583 | { return it(bounds.first); } | |
584 | ||
585 | ItType<T> | |
586 | end() | |
587 | { return it(bounds.last); } | |
ed920373 JW |
588 | |
589 | std::size_t | |
590 | size() const | |
9921ac3d | 591 | { return bounds.size(); } |
4e66b02b | 592 | }; |
6d0dff49 JW |
593 | |
594 | #if __cplusplus > 201703L | |
595 | template<typename T> | |
596 | struct contiguous_iterator_wrapper | |
597 | : random_access_iterator_wrapper<T> | |
598 | { | |
599 | using random_access_iterator_wrapper<T>::random_access_iterator_wrapper; | |
600 | ||
601 | using iterator_concept = std::contiguous_iterator_tag; | |
602 | ||
603 | contiguous_iterator_wrapper& | |
604 | operator++() | |
605 | { | |
606 | random_access_iterator_wrapper<T>::operator++(); | |
607 | return *this; | |
608 | } | |
609 | ||
610 | contiguous_iterator_wrapper& | |
611 | operator--() | |
612 | { | |
613 | random_access_iterator_wrapper<T>::operator--(); | |
614 | return *this; | |
615 | } | |
616 | ||
617 | contiguous_iterator_wrapper | |
618 | operator++(int) | |
619 | { | |
620 | auto tmp = *this; | |
621 | ++*this; | |
622 | return tmp; | |
623 | } | |
624 | ||
625 | contiguous_iterator_wrapper | |
626 | operator--(int) | |
627 | { | |
628 | auto tmp = *this; | |
629 | --*this; | |
630 | return tmp; | |
631 | } | |
632 | ||
633 | contiguous_iterator_wrapper& | |
634 | operator+=(std::ptrdiff_t n) | |
635 | { | |
636 | random_access_iterator_wrapper<T>::operator+=(n); | |
637 | return *this; | |
638 | } | |
639 | ||
640 | friend contiguous_iterator_wrapper | |
641 | operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n) | |
642 | { return iter += n; } | |
643 | ||
644 | friend contiguous_iterator_wrapper | |
645 | operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter) | |
646 | { return iter += n; } | |
647 | ||
648 | contiguous_iterator_wrapper& | |
649 | operator-=(std::ptrdiff_t n) | |
650 | { return *this += -n; } | |
651 | ||
652 | friend contiguous_iterator_wrapper | |
653 | operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n) | |
654 | { return iter -= n; } | |
655 | }; | |
656 | ||
657 | // A type meeting the minimum std::range requirements | |
658 | template<typename T, template<typename> class Iter> | |
659 | class test_range | |
660 | { | |
661 | // Adds default constructor to Iter<T> if needed | |
662 | struct iterator : Iter<T> | |
663 | { | |
664 | using Iter<T>::Iter; | |
665 | ||
666 | iterator() : Iter<T>(nullptr, nullptr) { } | |
667 | ||
668 | using Iter<T>::operator++; | |
669 | ||
670 | iterator& operator++() { Iter<T>::operator++(); return *this; } | |
671 | }; | |
672 | ||
673 | template<typename I> | |
674 | struct sentinel | |
675 | { | |
676 | T* end; | |
677 | ||
678 | friend bool operator==(const sentinel& s, const I& i) | |
679 | { return s.end == i.ptr; } | |
6d0dff49 JW |
680 | }; |
681 | ||
682 | auto | |
683 | get_iterator(T* p) | |
684 | { | |
a31517cb | 685 | if constexpr (std::default_initializable<Iter<T>>) |
6d0dff49 JW |
686 | return Iter<T>(p, &bounds); |
687 | else | |
688 | return iterator(p, &bounds); | |
689 | } | |
690 | ||
691 | public: | |
692 | test_range(T* first, T* last) : bounds(first, last) | |
693 | { } | |
694 | ||
695 | template<std::size_t N> | |
696 | explicit | |
697 | test_range(T (&arr)[N]) : test_range(arr, arr+N) | |
698 | { } | |
699 | ||
700 | auto begin() & { return get_iterator(bounds.first); } | |
701 | ||
702 | auto end() & | |
703 | { | |
704 | using I = decltype(get_iterator(bounds.last)); | |
705 | if constexpr (std::sentinel_for<I, I>) | |
706 | return get_iterator(bounds.last); | |
707 | else | |
708 | return sentinel<I>{bounds.last}; | |
709 | } | |
710 | ||
711 | typename Iter<T>::ContainerType bounds; | |
712 | }; | |
713 | ||
328b52d6 JW |
714 | template<typename T> |
715 | using test_contiguous_range | |
716 | = test_range<T, contiguous_iterator_wrapper>; | |
717 | template<typename T> | |
718 | using test_random_access_range | |
719 | = test_range<T, random_access_iterator_wrapper>; | |
720 | template<typename T> | |
721 | using test_bidirectional_range | |
722 | = test_range<T, bidirectional_iterator_wrapper>; | |
723 | template<typename T> | |
724 | using test_forward_range | |
725 | = test_range<T, forward_iterator_wrapper>; | |
726 | template<typename T> | |
727 | using test_input_range | |
728 | = test_range<T, input_iterator_wrapper>; | |
729 | template<typename T> | |
730 | using test_output_range | |
731 | = test_range<T, output_iterator_wrapper>; | |
732 | ||
6d0dff49 JW |
733 | // A type meeting the minimum std::sized_range requirements |
734 | template<typename T, template<typename> class Iter> | |
735 | struct test_sized_range : test_range<T, Iter> | |
736 | { | |
737 | using test_range<T, Iter>::test_range; | |
738 | ||
739 | std::size_t size() const noexcept | |
740 | { return this->bounds.size(); } | |
741 | }; | |
328b52d6 JW |
742 | |
743 | template<typename T> | |
744 | using test_contiguous_sized_range | |
745 | = test_sized_range<T, contiguous_iterator_wrapper>; | |
746 | template<typename T> | |
747 | using test_random_access_sized_range | |
748 | = test_sized_range<T, random_access_iterator_wrapper>; | |
749 | template<typename T> | |
750 | using test_bidirectional_sized_range | |
751 | = test_sized_range<T, bidirectional_iterator_wrapper>; | |
752 | template<typename T> | |
753 | using test_forward_sized_range | |
754 | = test_sized_range<T, forward_iterator_wrapper>; | |
755 | template<typename T> | |
756 | using test_input_sized_range | |
757 | = test_sized_range<T, input_iterator_wrapper>; | |
758 | template<typename T> | |
759 | using test_output_sized_range | |
760 | = test_sized_range<T, output_iterator_wrapper>; | |
b5b2e387 | 761 | |
68be73fc JW |
762 | // test_range and test_sized_range do not own their elements, so they model |
763 | // std::ranges::safe_range. This file does not define specializations of | |
764 | // std::ranges::enable_safe_range, so that individual tests can decide | |
765 | // whether or not to do so. | |
766 | // This is also true for test_container, although only when it has forward | |
767 | // iterators (because output_iterator_wrapper and input_iterator_wrapper are | |
768 | // not default constructible so do not model std::input_or_output_iterator). | |
6d0dff49 JW |
769 | #endif // C++20 |
770 | } // namespace __gnu_test | |
771 | #endif // _TESTSUITE_ITERATORS |