source: mainline/uspace/lib/cpp/include/impl/iterator.hpp@ 7a7ecbd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7a7ecbd was ee906a6, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added the rest of the iterator adaptors

  • Property mode set to 100644
File size: 17.8 KB
Line 
1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_ITERATOR
30#define LIBCPP_ITERATOR
31
32#include <cstdlib>
33#include <memory>
34#include <type_traits>
35
36namespace std
37{
38 /**
39 * 24.4.3, standard iterator tags:
40 */
41
42 struct input_iterator_tag
43 { /* DUMMY BODY */ };
44
45 struct output_iterator_tag
46 { /* DUMMY BODY */ };
47
48 struct forward_iterator_tag: input_iterator_tag
49 { /* DUMMY BODY */ };
50
51 struct bidirectional_iterator_tag: forward_iterator_tag
52 { /* DUMMY BODY */ };
53
54 struct random_access_iterator_tag: bidirectional_iterator_tag
55 { /* DUMMY BODY */ };
56
57 /**
58 * 24.4.1, iterator traits:
59 */
60
61 template<class Iterator>
62 struct iterator_traits
63 {
64 using difference_type = typename Iterator::difference_type;
65 using value_type = typename Iterator::value_type;
66 using iterator_category = typename Iterator::iterator_category;
67 using reference = typename Iterator::reference;
68 using pointer = typename Iterator::pointer;
69 };
70
71 template<class T>
72 struct iterator_traits<T*>
73 {
74 using difference_type = ptrdiff_t;
75 using value_type = T;
76 using iterator_category = random_access_iterator_tag;
77 using reference = T&;
78 using pointer = T*;
79 };
80
81 template<class T>
82 struct iterator_traits<const T*>
83 {
84 using difference_type = ptrdiff_t;
85 using value_type = T;
86 using iterator_category = random_access_iterator_tag;
87 using reference = const T&;
88 using pointer = const T*;
89 };
90
91 /**
92 * 24.4.2, basic iterator:
93 */
94
95 template<
96 class Category, class T, class Distance = ptrdiff_t,
97 class Pointer = T*, class Reference = T&
98 >
99 struct iterator
100 {
101 using difference_type = Distance;
102 using value_type = T;
103 using iterator_category = Category;
104 using reference = Reference;
105 using pointer = Pointer;
106 };
107
108 /**
109 * 24.5.1, reverse iterator:
110 */
111
112 template<class Iterator>
113 class reverse_iterator
114 : iterator<
115 typename iterator_traits<Iterator>::iterator_category,
116 typename iterator_traits<Iterator>::value_type,
117 typename iterator_traits<Iterator>::difference_type,
118 typename iterator_traits<Iterator>::pointer,
119 typename iterator_traits<Iterator>::reference
120 >
121 {
122 public:
123 using iterator_type = Iterator;
124 using difference_type = typename iterator_traits<Iterator>::difference_type;
125 using reference = typename iterator_traits<Iterator>::reference;
126 using pointer = typename iterator_traits<Iterator>::pointer;
127
128 reverse_iterator()
129 : current_{}
130 { /* DUMMY BODY */ }
131
132 explicit reverse_iterator(Iterator it)
133 : current_{it}
134 { /* DUMMY BODY */ }
135
136 template<class U>
137 reverse_iterator(const reverse_iterator<U>& other)
138 : current_{other.current_}
139 { /* DUMMY BODY */ }
140
141 template<class U>
142 reverse_iterator& operator=(const reverse_iterator<U>& other)
143 {
144 current_ = other.base();
145
146 return *this;
147 }
148
149 Iterator base() const
150 {
151 return current_;
152 }
153
154 reference operator*() const
155 {
156 auto tmp = current_;
157
158 return *(--tmp);
159 }
160
161 pointer operator->() const
162 {
163 // TODO: need std::addressof
164 return nullptr;
165 }
166
167 reverse_iterator& operator++()
168 {
169 --current_;
170
171 return *this;
172 }
173
174 reverse_iterator operator++(int)
175 {
176 auto tmp = *this;
177 --current_;
178
179 return tmp;
180 }
181
182 reverse_iterator& operator--()
183 {
184 ++current_;
185
186 return *this;
187 }
188
189 reverse_iterator operator--(int)
190 {
191 auto tmp = *this;
192 ++current_;
193
194 return tmp;
195 }
196
197 reverse_iterator operator+(difference_type n) const
198 {
199 return reverse_iterator{current_ - n};
200 }
201
202 reverse_iterator& operator+=(difference_type n)
203 {
204 current_ -= n;
205
206 return *this;
207 }
208
209 reverse_iterator operator-(difference_type n) const
210 {
211 return reverse_iterator{current_ + n};
212 }
213
214 reverse_iterator& operator-=(difference_type n)
215 {
216 current_ += n;
217
218 return *this;
219 }
220
221 auto operator[](difference_type n) const
222 {
223 return current_[-n - 1];
224 }
225
226 protected:
227 Iterator current_;
228 };
229
230 template<class Iterator1, class Iterator2>
231 bool operator==(const reverse_iterator<Iterator1>& lhs,
232 const reverse_iterator<Iterator2>& rhs)
233 {
234 return lhs.base() == rhs.base();
235 }
236
237 template<class Iterator1, class Iterator2>
238 bool operator<(const reverse_iterator<Iterator1>& lhs,
239 const reverse_iterator<Iterator2>& rhs)
240 {
241 // Remember: they are reversed!
242 return lhs.base() > rhs.base();
243 }
244
245 template<class Iterator1, class Iterator2>
246 bool operator!=(const reverse_iterator<Iterator1>& lhs,
247 const reverse_iterator<Iterator2>& rhs)
248 {
249 return lhs.base() != rhs.base();
250 }
251
252 template<class Iterator1, class Iterator2>
253 bool operator>(const reverse_iterator<Iterator1>& lhs,
254 const reverse_iterator<Iterator2>& rhs)
255 {
256 return lhs.base() < rhs.base();
257 }
258
259 template<class Iterator1, class Iterator2>
260 bool operator>=(const reverse_iterator<Iterator1>& lhs,
261 const reverse_iterator<Iterator2>& rhs)
262 {
263 return lhs.base() <= rhs.base();
264 }
265
266 template<class Iterator1, class Iterator2>
267 bool operator<=(const reverse_iterator<Iterator1>& lhs,
268 const reverse_iterator<Iterator2>& rhs)
269 {
270 return lhs.base() >= rhs.base();
271 }
272
273 template<class Iterator1, class Iterator2>
274 auto operator-(const reverse_iterator<Iterator1>& lhs,
275 const reverse_iterator<Iterator2>& rhs)
276 -> decltype(rhs.base() - lhs.base())
277 {
278 return rhs.base() - lhs.base();
279 }
280
281 template<class Iterator>
282 reverse_iterator<Iterator> operator+(
283 typename reverse_iterator<Iterator>::difference_type n,
284 const reverse_iterator<Iterator>& it
285 )
286 {
287 return reverse_iterator<Iterator>{it.base() - n};
288 }
289
290 template<class Iterator>
291 reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
292 {
293 return reverse_iterator<Iterator>(it);
294 }
295
296 /**
297 * 24.5.2, insert iterators:
298 */
299
300 /**
301 * 24.5.2.1, back insert iterator:
302 */
303
304 template<class Container>
305 class back_insert_iterator
306 : public iterator<output_iterator_tag, void, void, void, void>
307 {
308 public:
309 using container_type = Container;
310
311 explicit back_insert_iterator(Container& cont)
312 : container{std::addressof(cont)}
313 { /* DUMMY BODY */ }
314
315 back_insert_iterator& operator=(const typename container_type::value_type& value)
316 {
317 container->push_back(value);
318 return *this;
319 }
320
321 back_insert_iterator& operator=(typename container_type::value_type&& value)
322 {
323 container->push_back(move(value));
324 return *this;
325 }
326
327 back_insert_iterator& operator*()
328 {
329 return *this;
330 }
331
332 back_insert_iterator& operator++()
333 {
334 return *this;
335 }
336
337 back_insert_iterator operator++(int)
338 {
339 return *this;
340 }
341
342 protected:
343 Container* container;
344 };
345
346 template<class Container>
347 back_insert_iterator<Container> back_inserter(Container& cont)
348 {
349 return back_insert_iterator<Container>(cont);
350 }
351
352 /**
353 * 24.5.2.3, front insert iterator:
354 */
355
356 template<class Container>
357 class front_insert_iterator
358 : public iterator<output_iterator_tag, void, void, void, void>
359 {
360 public:
361 using container_type = Container;
362
363 explicit front_insert_iterator(Container& cont)
364 : container{std::addressof(cont)}
365 { /* DUMMY BODY */ }
366
367 front_insert_iterator& operator=(const typename container_type::value_type& value)
368 {
369 container->push_front(value);
370 return *this;
371 }
372
373 front_insert_iterator& operator=(typename container_type::value_type&& value)
374 {
375 container->push_front(move(value));
376 return *this;
377 }
378
379 front_insert_iterator& operator*()
380 {
381 return *this;
382 }
383
384 front_insert_iterator& operator++()
385 {
386 return *this;
387 }
388
389 front_insert_iterator operator++(int)
390 {
391 return *this;
392 }
393
394 protected:
395 Container* container;
396 };
397
398 template<class Container>
399 front_insert_iterator<Container> front_inserter(Container& cont)
400 {
401 return front_insert_iterator<Container>(cont);
402 }
403
404 /**
405 * 24.5.2.5, front insert iterator:
406 */
407
408 template<class Container>
409 class insert_iterator
410 : public iterator<output_iterator_tag, void, void, void, void>
411 {
412 public:
413 using container_type = Container;
414
415 explicit insert_iterator(Container& cont, typename Container::iterator i)
416 : container{std::addressof(cont)}, iter{i}
417 { /* DUMMY BODY */ }
418
419 insert_iterator& operator=(const typename container_type::value_type& value)
420 {
421 iter = container.insert(iter, value);
422 ++iter;
423
424 return *this;
425 }
426
427 insert_iterator& operator=(typename container_type::value_type&& value)
428 {
429 iter = container.insert(iter, move(value));
430 ++iter;
431
432 return *this;
433 }
434
435 insert_iterator& operator*()
436 {
437 return *this;
438 }
439
440 insert_iterator& operator++()
441 {
442 return *this;
443 }
444
445 insert_iterator operator++(int)
446 {
447 return *this;
448 }
449
450 protected:
451 Container* container;
452 typename Container::iterator iter;
453 };
454
455 template<class Container>
456 insert_iterator<Container> inserter(Container& cont, typename Container::iterator i)
457 {
458 return insert_iterator<Container>(cont, i);
459 }
460
461 /**
462 * 24.5.3.1, move iterator:
463 */
464
465 namespace aux
466 {
467 template<class Iterator, class = void>
468 struct move_it_get_reference
469 {
470 using type = typename iterator_traits<Iterator>::reference;
471 };
472
473 template<class Iterator>
474 struct move_it_get_reference<
475 Iterator, enable_if_t<
476 is_reference<typename iterator_traits<Iterator>::reference>::value,
477 void
478 >
479 >
480 {
481 using type = remove_reference_t<typename iterator_traits<Iterator>::reference>;
482 };
483 }
484
485 template<class Iterator>
486 class move_iterator
487 {
488 public:
489 using iterator_type = Iterator;
490 using pointer = iterator_type;
491 using difference_type = typename iterator_traits<iterator_type>::difference_type;
492 using value_type = typename iterator_traits<iterator_type>::value_type;
493 using iterator_category = typename iterator_traits<iterator_type>::iterator_category;
494 using reference = typename aux::move_it_get_reference<iterator_type>::type;
495
496 move_iterator()
497 : current_{}
498 { /* DUMMY BODY */ }
499
500 explicit move_iterator(iterator_type i)
501 : current_{i}
502 { /* DUMMY BODY */ }
503
504 // TODO: both require is_convertible
505 template<class U>
506 move_iterator(const move_iterator<U>& other)
507 : current_{other.current_}
508 { /* DUMMY BODY */ }
509
510 template<class U>
511 move_iterator& operator=(const move_iterator<U>& other)
512 {
513 current_ = other.current_;
514
515 return *this;
516 }
517
518 iterator_type base() const
519 {
520 return current_;
521 }
522
523 reference operator*() const
524 {
525 return static_cast<reference>(*current_);
526 }
527
528 pointer operator->() const
529 {
530 return current_;
531 }
532
533 move_iterator& operator++()
534 {
535 ++current_;
536
537 return *this;
538 }
539
540 move_iterator operator++(int)
541 {
542 auto tmp = *this;
543 ++current_;
544
545 return tmp;
546 }
547
548 move_iterator& operator--()
549 {
550 --current_;
551
552 return *this;
553 }
554
555 move_iterator operator--(int)
556 {
557 auto tmp = *this;
558 --current_;
559
560 return tmp;
561 }
562
563 move_iterator operator+(difference_type n) const
564 {
565 return move_iterator(current_ + n);
566 }
567
568 move_iterator& operator+=(difference_type n)
569 {
570 current_ += n;
571
572 return *this;
573 }
574
575 move_iterator operator-(difference_type n) const
576 {
577 return move_iterator(current_ - n);
578 }
579
580 move_iterator& operator-=(difference_type n)
581 {
582 current_ -= n;
583
584 return *this;
585 }
586
587 auto operator[](difference_type idx) const
588 {
589 return move(current_[idx]);
590 }
591
592 private:
593 iterator_type current_;
594 };
595
596 template<class Iterator1, class Iterator2>
597 bool operator==(const move_iterator<Iterator1>& lhs,
598 const move_iterator<Iterator2>& rhs)
599 {
600 return lhs.base() == rhs.base();
601 }
602
603 template<class Iterator1, class Iterator2>
604 bool operator!=(const move_iterator<Iterator1>& lhs,
605 const move_iterator<Iterator2>& rhs)
606 {
607 return lhs.base() != rhs.base();
608 }
609
610 template<class Iterator1, class Iterator2>
611 bool operator<(const move_iterator<Iterator1>& lhs,
612 const move_iterator<Iterator2>& rhs)
613 {
614 return lhs.base() < rhs.base();
615 }
616
617 template<class Iterator1, class Iterator2>
618 bool operator<=(const move_iterator<Iterator1>& lhs,
619 const move_iterator<Iterator2>& rhs)
620 {
621 return !(rhs < lhs);
622 }
623
624 template<class Iterator1, class Iterator2>
625 bool operator>(const move_iterator<Iterator1>& lhs,
626 const move_iterator<Iterator2>& rhs)
627 {
628 return rhs < lhs;
629 }
630
631 template<class Iterator1, class Iterator2>
632 bool operator>=(const move_iterator<Iterator1>& lhs,
633 const move_iterator<Iterator2>& rhs)
634 {
635 return !(lhs < rhs);
636 }
637
638 template<class Iterator1, class Iterator2>
639 auto operator-(const move_iterator<Iterator1>& lhs,
640 const move_iterator<Iterator2>& rhs)
641 -> decltype(rhs.base() - lhs.base())
642 {
643 return lhs.base() - rhs.base();
644 }
645
646 template<class Iterator>
647 move_iterator<Iterator> operator+(
648 typename move_iterator<Iterator>::difference_type n,
649 const move_iterator<Iterator>& it
650 )
651 {
652 return it + n;
653 }
654
655 template<class Iterator>
656 move_iterator<Iterator> make_move_iterator(Iterator it)
657 {
658 return move_iterator<Iterator>(it);
659 }
660}
661
662#endif
Note: See TracBrowser for help on using the repository browser.