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

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

cpp: added missing iterator operations

  • Property mode set to 100644
File size: 30.9 KB
RevLine 
[aab972f]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
[f041811]32#include <cstdlib>
[9317f45]33#include <initializer_list>
34#include <iosfwd>
[ee906a6]35#include <memory>
36#include <type_traits>
[2215fd0]37#include <utility>
[f041811]38
[aab972f]39namespace std
40{
41 /**
42 * 24.4.3, standard iterator tags:
43 */
44
45 struct input_iterator_tag
46 { /* DUMMY BODY */ };
47
48 struct output_iterator_tag
49 { /* DUMMY BODY */ };
50
51 struct forward_iterator_tag: input_iterator_tag
52 { /* DUMMY BODY */ };
53
54 struct bidirectional_iterator_tag: forward_iterator_tag
55 { /* DUMMY BODY */ };
56
57 struct random_access_iterator_tag: bidirectional_iterator_tag
58 { /* DUMMY BODY */ };
59
60 /**
61 * 24.4.1, iterator traits:
62 */
63
64 template<class Iterator>
65 struct iterator_traits
66 {
67 using difference_type = typename Iterator::difference_type;
68 using value_type = typename Iterator::value_type;
69 using iterator_category = typename Iterator::iterator_category;
70 using reference = typename Iterator::reference;
71 using pointer = typename Iterator::pointer;
72 };
73
74 template<class T>
75 struct iterator_traits<T*>
76 {
77 using difference_type = ptrdiff_t;
78 using value_type = T;
79 using iterator_category = random_access_iterator_tag;
80 using reference = T&;
81 using pointer = T*;
82 };
83
84 template<class T>
85 struct iterator_traits<const T*>
86 {
87 using difference_type = ptrdiff_t;
88 using value_type = T;
89 using iterator_category = random_access_iterator_tag;
90 using reference = const T&;
91 using pointer = const T*;
92 };
93
94 /**
95 * 24.4.2, basic iterator:
96 */
97
98 template<
99 class Category, class T, class Distance = ptrdiff_t,
100 class Pointer = T*, class Reference = T&
101 >
102 struct iterator
103 {
104 using difference_type = Distance;
105 using value_type = T;
106 using iterator_category = Category;
107 using reference = Reference;
108 using pointer = Pointer;
109 };
110
[a44c35d]111 /**
112 * 24.4.4, iterator operations
113 */
114
115 template<class InputIterator, class Distance>
116 void advance(InputIterator& it, Distance n)
117 {
118 for (Distance i = Distance{}; i < n; ++i)
119 ++it;
120 }
121
122 template<class InputIterator>
123 typename iterator_traits<InputIterator>::difference_type
124 distance(InputIterator first, InputIterator last)
125 {
126 using cat_t = typename iterator_traits<InputIterator>::iterator_category;
127
128 if constexpr (is_same_v<cat_t, random_access_iterator_tag>)
129 return last - first;
130 else
131 {
132 cat_t diff{};
133 while (++first != last)
134 ++diff;
135 }
136 }
137
138 template<class ForwardIterator>
139 ForwardIterator
140 next(ForwardIterator it, typename iterator_traits<ForwardIterator>::difference_type n = 1)
141 {
142 advance(it, n);
143
144 return it;
145 }
146
147 template<class BidirectionalIterator>
148 BidirectionalIterator
149 prev(BidirectionalIterator it,
150 typename iterator_traits<BidirectionalIterator>::difference_type n = 1)
151 {
152 advance(it, -n);
153
154 return it;
155 }
156
[aab972f]157 /**
[ee906a6]158 * 24.5.1, reverse iterator:
[aab972f]159 */
160
161 template<class Iterator>
162 class reverse_iterator
163 : iterator<
164 typename iterator_traits<Iterator>::iterator_category,
165 typename iterator_traits<Iterator>::value_type,
166 typename iterator_traits<Iterator>::difference_type,
167 typename iterator_traits<Iterator>::pointer,
168 typename iterator_traits<Iterator>::reference
169 >
170 {
171 public:
172 using iterator_type = Iterator;
[f041811]173 using difference_type = typename iterator_traits<Iterator>::difference_type;
174 using reference = typename iterator_traits<Iterator>::reference;
175 using pointer = typename iterator_traits<Iterator>::pointer;
[aab972f]176
177 reverse_iterator()
178 : current_{}
179 { /* DUMMY BODY */ }
180
181 explicit reverse_iterator(Iterator it)
182 : current_{it}
183 { /* DUMMY BODY */ }
184
185 template<class U>
186 reverse_iterator(const reverse_iterator<U>& other)
187 : current_{other.current_}
188 { /* DUMMY BODY */ }
189
190 template<class U>
191 reverse_iterator& operator=(const reverse_iterator<U>& other)
192 {
193 current_ = other.base();
194
195 return *this;
196 }
197
198 Iterator base() const
199 {
200 return current_;
201 }
202
203 reference operator*() const
204 {
205 auto tmp = current_;
206
207 return *(--tmp);
208 }
209
210 pointer operator->() const
211 {
[2215fd0]212 return addressof(operator*());
[aab972f]213 }
214
215 reverse_iterator& operator++()
216 {
217 --current_;
218
219 return *this;
220 }
221
222 reverse_iterator operator++(int)
223 {
224 auto tmp = *this;
225 --current_;
226
227 return tmp;
228 }
229
230 reverse_iterator& operator--()
231 {
232 ++current_;
233
234 return *this;
235 }
236
237 reverse_iterator operator--(int)
238 {
239 auto tmp = *this;
240 ++current_;
241
242 return tmp;
243 }
244
245 reverse_iterator operator+(difference_type n) const
246 {
247 return reverse_iterator{current_ - n};
248 }
249
250 reverse_iterator& operator+=(difference_type n)
251 {
252 current_ -= n;
253
254 return *this;
255 }
256
257 reverse_iterator operator-(difference_type n) const
258 {
259 return reverse_iterator{current_ + n};
260 }
261
262 reverse_iterator& operator-=(difference_type n)
263 {
264 current_ += n;
265
266 return *this;
267 }
268
269 auto operator[](difference_type n) const
270 {
271 return current_[-n - 1];
272 }
273
274 protected:
275 Iterator current_;
276 };
277
278 template<class Iterator1, class Iterator2>
279 bool operator==(const reverse_iterator<Iterator1>& lhs,
280 const reverse_iterator<Iterator2>& rhs)
281 {
[f041811]282 return lhs.base() == rhs.base();
[aab972f]283 }
284
285 template<class Iterator1, class Iterator2>
286 bool operator<(const reverse_iterator<Iterator1>& lhs,
[f041811]287 const reverse_iterator<Iterator2>& rhs)
[aab972f]288 {
289 // Remember: they are reversed!
[f041811]290 return lhs.base() > rhs.base();
[aab972f]291 }
292
293 template<class Iterator1, class Iterator2>
294 bool operator!=(const reverse_iterator<Iterator1>& lhs,
295 const reverse_iterator<Iterator2>& rhs)
296 {
[f041811]297 return lhs.base() != rhs.base();
[aab972f]298 }
299
300 template<class Iterator1, class Iterator2>
301 bool operator>(const reverse_iterator<Iterator1>& lhs,
[ee906a6]302 const reverse_iterator<Iterator2>& rhs)
[aab972f]303 {
[f041811]304 return lhs.base() < rhs.base();
[aab972f]305 }
306
307 template<class Iterator1, class Iterator2>
308 bool operator>=(const reverse_iterator<Iterator1>& lhs,
309 const reverse_iterator<Iterator2>& rhs)
310 {
[f041811]311 return lhs.base() <= rhs.base();
[aab972f]312 }
313
314 template<class Iterator1, class Iterator2>
315 bool operator<=(const reverse_iterator<Iterator1>& lhs,
316 const reverse_iterator<Iterator2>& rhs)
317 {
[f041811]318 return lhs.base() >= rhs.base();
[aab972f]319 }
320
321 template<class Iterator1, class Iterator2>
322 auto operator-(const reverse_iterator<Iterator1>& lhs,
[ee906a6]323 const reverse_iterator<Iterator2>& rhs)
[aab972f]324 -> decltype(rhs.base() - lhs.base())
325 {
[f041811]326 return rhs.base() - lhs.base();
[aab972f]327 }
328
329 template<class Iterator>
330 reverse_iterator<Iterator> operator+(
331 typename reverse_iterator<Iterator>::difference_type n,
332 const reverse_iterator<Iterator>& it
333 )
334 {
[f041811]335 return reverse_iterator<Iterator>{it.base() - n};
[aab972f]336 }
337
338 template<class Iterator>
339 reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
340 {
341 return reverse_iterator<Iterator>(it);
342 }
343
[ee906a6]344 /**
345 * 24.5.2, insert iterators:
346 */
347
348 /**
349 * 24.5.2.1, back insert iterator:
350 */
351
352 template<class Container>
353 class back_insert_iterator
354 : public iterator<output_iterator_tag, void, void, void, void>
355 {
356 public:
357 using container_type = Container;
358
359 explicit back_insert_iterator(Container& cont)
360 : container{std::addressof(cont)}
361 { /* DUMMY BODY */ }
362
363 back_insert_iterator& operator=(const typename container_type::value_type& value)
364 {
365 container->push_back(value);
366 return *this;
367 }
368
369 back_insert_iterator& operator=(typename container_type::value_type&& value)
370 {
371 container->push_back(move(value));
372 return *this;
373 }
374
375 back_insert_iterator& operator*()
376 {
377 return *this;
378 }
379
380 back_insert_iterator& operator++()
381 {
382 return *this;
383 }
384
385 back_insert_iterator operator++(int)
386 {
387 return *this;
388 }
389
390 protected:
391 Container* container;
392 };
393
394 template<class Container>
395 back_insert_iterator<Container> back_inserter(Container& cont)
396 {
397 return back_insert_iterator<Container>(cont);
398 }
399
400 /**
401 * 24.5.2.3, front insert iterator:
402 */
403
404 template<class Container>
405 class front_insert_iterator
406 : public iterator<output_iterator_tag, void, void, void, void>
407 {
408 public:
409 using container_type = Container;
410
411 explicit front_insert_iterator(Container& cont)
412 : container{std::addressof(cont)}
413 { /* DUMMY BODY */ }
414
415 front_insert_iterator& operator=(const typename container_type::value_type& value)
416 {
417 container->push_front(value);
418 return *this;
419 }
420
421 front_insert_iterator& operator=(typename container_type::value_type&& value)
422 {
423 container->push_front(move(value));
424 return *this;
425 }
426
427 front_insert_iterator& operator*()
428 {
429 return *this;
430 }
431
432 front_insert_iterator& operator++()
433 {
434 return *this;
435 }
436
437 front_insert_iterator operator++(int)
438 {
439 return *this;
440 }
441
442 protected:
443 Container* container;
444 };
445
446 template<class Container>
447 front_insert_iterator<Container> front_inserter(Container& cont)
448 {
449 return front_insert_iterator<Container>(cont);
450 }
451
452 /**
453 * 24.5.2.5, front insert iterator:
454 */
455
456 template<class Container>
457 class insert_iterator
458 : public iterator<output_iterator_tag, void, void, void, void>
459 {
460 public:
461 using container_type = Container;
462
463 explicit insert_iterator(Container& cont, typename Container::iterator i)
464 : container{std::addressof(cont)}, iter{i}
465 { /* DUMMY BODY */ }
466
467 insert_iterator& operator=(const typename container_type::value_type& value)
468 {
469 iter = container.insert(iter, value);
470 ++iter;
471
472 return *this;
473 }
474
475 insert_iterator& operator=(typename container_type::value_type&& value)
476 {
477 iter = container.insert(iter, move(value));
478 ++iter;
479
480 return *this;
481 }
482
483 insert_iterator& operator*()
484 {
485 return *this;
486 }
487
488 insert_iterator& operator++()
489 {
490 return *this;
491 }
492
493 insert_iterator operator++(int)
494 {
495 return *this;
496 }
497
498 protected:
499 Container* container;
500 typename Container::iterator iter;
501 };
502
503 template<class Container>
504 insert_iterator<Container> inserter(Container& cont, typename Container::iterator i)
505 {
506 return insert_iterator<Container>(cont, i);
507 }
508
509 /**
510 * 24.5.3.1, move iterator:
511 */
512
513 namespace aux
514 {
515 template<class Iterator, class = void>
516 struct move_it_get_reference
517 {
518 using type = typename iterator_traits<Iterator>::reference;
519 };
520
521 template<class Iterator>
522 struct move_it_get_reference<
523 Iterator, enable_if_t<
524 is_reference<typename iterator_traits<Iterator>::reference>::value,
525 void
526 >
527 >
528 {
529 using type = remove_reference_t<typename iterator_traits<Iterator>::reference>;
530 };
531 }
532
533 template<class Iterator>
534 class move_iterator
535 {
536 public:
537 using iterator_type = Iterator;
538 using pointer = iterator_type;
539 using difference_type = typename iterator_traits<iterator_type>::difference_type;
540 using value_type = typename iterator_traits<iterator_type>::value_type;
541 using iterator_category = typename iterator_traits<iterator_type>::iterator_category;
542 using reference = typename aux::move_it_get_reference<iterator_type>::type;
543
544 move_iterator()
545 : current_{}
546 { /* DUMMY BODY */ }
547
548 explicit move_iterator(iterator_type i)
549 : current_{i}
550 { /* DUMMY BODY */ }
551
552 // TODO: both require is_convertible
553 template<class U>
554 move_iterator(const move_iterator<U>& other)
555 : current_{other.current_}
556 { /* DUMMY BODY */ }
557
558 template<class U>
559 move_iterator& operator=(const move_iterator<U>& other)
560 {
561 current_ = other.current_;
562
563 return *this;
564 }
565
566 iterator_type base() const
567 {
568 return current_;
569 }
570
571 reference operator*() const
572 {
573 return static_cast<reference>(*current_);
574 }
575
576 pointer operator->() const
577 {
578 return current_;
579 }
580
581 move_iterator& operator++()
582 {
583 ++current_;
584
585 return *this;
586 }
587
588 move_iterator operator++(int)
589 {
590 auto tmp = *this;
591 ++current_;
592
593 return tmp;
594 }
595
596 move_iterator& operator--()
597 {
598 --current_;
599
600 return *this;
601 }
602
603 move_iterator operator--(int)
604 {
605 auto tmp = *this;
606 --current_;
607
608 return tmp;
609 }
610
611 move_iterator operator+(difference_type n) const
612 {
613 return move_iterator(current_ + n);
614 }
615
616 move_iterator& operator+=(difference_type n)
617 {
618 current_ += n;
619
620 return *this;
621 }
622
623 move_iterator operator-(difference_type n) const
624 {
625 return move_iterator(current_ - n);
626 }
627
628 move_iterator& operator-=(difference_type n)
629 {
630 current_ -= n;
631
632 return *this;
633 }
634
635 auto operator[](difference_type idx) const
636 {
637 return move(current_[idx]);
638 }
639
640 private:
641 iterator_type current_;
642 };
643
644 template<class Iterator1, class Iterator2>
645 bool operator==(const move_iterator<Iterator1>& lhs,
646 const move_iterator<Iterator2>& rhs)
647 {
648 return lhs.base() == rhs.base();
649 }
650
651 template<class Iterator1, class Iterator2>
652 bool operator!=(const move_iterator<Iterator1>& lhs,
653 const move_iterator<Iterator2>& rhs)
654 {
655 return lhs.base() != rhs.base();
656 }
657
658 template<class Iterator1, class Iterator2>
659 bool operator<(const move_iterator<Iterator1>& lhs,
660 const move_iterator<Iterator2>& rhs)
661 {
662 return lhs.base() < rhs.base();
663 }
664
665 template<class Iterator1, class Iterator2>
666 bool operator<=(const move_iterator<Iterator1>& lhs,
667 const move_iterator<Iterator2>& rhs)
668 {
669 return !(rhs < lhs);
670 }
671
672 template<class Iterator1, class Iterator2>
673 bool operator>(const move_iterator<Iterator1>& lhs,
674 const move_iterator<Iterator2>& rhs)
675 {
676 return rhs < lhs;
677 }
678
679 template<class Iterator1, class Iterator2>
680 bool operator>=(const move_iterator<Iterator1>& lhs,
681 const move_iterator<Iterator2>& rhs)
682 {
683 return !(lhs < rhs);
684 }
685
686 template<class Iterator1, class Iterator2>
687 auto operator-(const move_iterator<Iterator1>& lhs,
688 const move_iterator<Iterator2>& rhs)
689 -> decltype(rhs.base() - lhs.base())
690 {
691 return lhs.base() - rhs.base();
692 }
693
694 template<class Iterator>
695 move_iterator<Iterator> operator+(
696 typename move_iterator<Iterator>::difference_type n,
697 const move_iterator<Iterator>& it
698 )
699 {
700 return it + n;
701 }
702
703 template<class Iterator>
704 move_iterator<Iterator> make_move_iterator(Iterator it)
705 {
706 return move_iterator<Iterator>(it);
707 }
[9317f45]708
709 /**
710 * 24.6, stream iterators:
711 */
712
713 /**
714 * 24.6.1, class template istream_iterator:
715 */
716
717 template<class T, class Char = char, class Traits = char_traits<Char>,
718 class Distance = ptrdiff_t>
719 class istream_iterator
720 : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
721 {
722 public:
723 using char_type = Char;
724 using traits_type = Traits;
725 using istream_type = basic_istream<char_type, traits_type>;
726
727 // TODO: if T is literal, this should be constexpr
728 istream_iterator()
729 : is_{nullptr}, value_{}
730 { /* DUMMY BODY */ }
731
732 istream_iterator(istream_type& is)
733 : is_{&is}, value_{}
734 { /* DUMMY BODY */ }
735
736 istream_iterator(const istream_iterator&) = default;
737
738 ~istream_iterator() = default;
739
740 const T& operator*() const
741 {
742 return value_;
743 }
744
745 const T* operator->() const
746 {
747 return &(operator*());
748 }
749
750 istream_iterator& operator++()
751 {
752 if (is_)
753 (*is_) >> value_;
754
755 return *this;
756 }
757
758 istream_iterator operator++(int)
759 {
760 auto tmp{*this};
761
762 if (is_)
763 (*is_) >> value_;
764
765 return tmp;
766 }
767
768 private:
769 basic_istream<char_type, traits_type>* is_;
770
771 T value_;
772
773 friend bool operator==<>(const istream_iterator&,
774 const istream_iterator&);
775
776 friend bool operator!=<>(const istream_iterator&,
777 const istream_iterator&);
778 };
779
780 template<class T, class Char, class Traits, class Distance>
781 bool operator==(const istream_iterator<T, Char, Traits, Distance>& lhs,
782 const istream_iterator<T, Char, Traits, Distance>& rhs)
783 {
784 return lhs.is_ == rhs.is_;
785 }
786
787 template<class T, class Char, class Traits, class Distance>
788 bool operator!=(const istream_iterator<T, Char, Traits, Distance>& lhs,
789 const istream_iterator<T, Char, Traits, Distance>& rhs)
790 {
791 return !(lhs == rhs);
792 }
793
794 /**
795 * 24.6.2, class template ostream_iterator:
796 */
797
798 template<class T, class Char = char, class Traits = char_traits<Char>>
799 class ostream_iterator
800 : public iterator<output_iterator_tag, void, void, void, void>
801 {
802 public:
803 using char_type = Char;
804 using traits_type = Traits;
805 using ostream_type = basic_ostream<char_type, traits_type>;
806
807 ostream_iterator(ostream_type& os)
808 : os_{&os}, delim_{nullptr}
809 { /* DUMMY BODY */ }
810
811 ostream_iterator(ostream_type& os, const char_type* delim)
812 : os_{&os}, delim_{delim}
813 { /* DUMMY BODY */ }
814
815 ostream_iterator(const ostream_iterator&) = default;
816
817 ~ostream_iterator() = default;
818
819 ostream_iterator& operator=(const T& value)
820 {
821 os_ << value;
822 if (delim_)
823 os_ << delim_;
824
825 return *this;
826 }
827
828 ostream_iterator& operator*() const
829 {
830 return *this;
831 }
832
833 ostream_iterator& operator++()
834 {
835 return *this;
836 }
837
838 ostream_iterator& operator++(int)
839 {
840 return *this;
841 }
842
843 private:
844 basic_ostream<char_type, traits_type>* os_;
845
846 const char_type* delim_;
847 };
848
849 /**
850 * 24.6.3, class template istreambuf_iterator:
851 */
852
853 template<class Char, class Traits>
854 class istreambuf_iterator
855 : public iterator<input_iterator_tag, Char, typename Traits::off_type, Char*, Char>
856 {
857 public:
858 using char_type = Char;
859 using traits_type = Traits;
860 using int_type = typename traits_type::int_type;
861 using streambuf_type = basic_streambuf<char_type, traits_type>;
862 using istream_type = basic_istream<char_type, traits_type>;
863
864 class proxy_type
865 {
866 public:
[fe39530]867 proxy_type(int_type c, streambuf_type* sbuf)
868 : char_{c}, sbuf_{sbuf}
869 { /* DUMMY BODY */ }
870
[9317f45]871 char_type operator*()
872 {
[fe39530]873 return traits_type::to_char_type(char_);
[9317f45]874 }
875
876 private:
[fe39530]877 int_type char_;
[9317f45]878
879 streambuf_type* sbuf_;
880 };
881
882 constexpr istreambuf_iterator() noexcept
883 : sbuf_{nullptr}
884 { /* DUMMY BODY */ }
885
886 istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
887
888 ~istreambuf_iterator() = default;
889
890 istreambuf_iterator(istream_type& is) noexcept
891 : sbuf_{is.rdbuf()}
892 { /* DUMMY BODY */ }
893
894 istreambuf_iterator(streambuf_type* sbuf) noexcept
895 : sbuf_{sbuf}
896 { /* DUMMY BODY */ }
897
898 istreambuf_iterator(const proxy_type& proxy) noexcept
899 : sbuf_{proxy.sbuf_}
900 { /* DUMMY BODY */ }
901
[fe39530]902 char_type operator*() /* const */ // TODO: Should be const :/
[9317f45]903 {
904 if (sbuf_)
905 {
906 auto res = sbuf_->sgetc();
907 if (res == traits_type::eof())
908 sbuf_ = nullptr;
909
910 return res;
911 }
912 else
913 return traits_type::eof();
914 }
915
916 istreambuf_iterator& operator++()
917 {
918 if (sbuf_)
919 sbuf_->sbumpc();
920
921 return *this;
922 }
923
924 proxy_type operator++(int)
925 {
926 if (sbuf_)
927 return proxy_type{sbuf_->sbumpc(), sbuf_};
928 else
929 return proxy_type{traits_type::eof(), nullptr};
930 }
931
932 bool equal(const istreambuf_iterator& rhs) const
933 {
934 if ((sbuf_ == nullptr && rhs.sbuf_ == nullptr) ||
935 (sbuf_ != nullptr && rhs.sbuf_ != nullptr))
936 return true;
937 else
938 return false;
939 }
940
941 private:
942 streambuf_type* sbuf_;
943 };
944
945 template<class Char, class Traits>
946 bool operator==(const istreambuf_iterator<Char, Traits>& lhs,
947 const istreambuf_iterator<Char, Traits>& rhs)
948 {
949 return lhs.equal(rhs);
950 }
951
952 template<class Char, class Traits>
953 bool operator!=(const istreambuf_iterator<Char, Traits>& lhs,
954 const istreambuf_iterator<Char, Traits>& rhs)
955 {
956 return !lhs.equal(rhs);
957 }
958
959 /**
960 * 24.6.4, class template ostreambuf_iterator:
961 */
962
963 template<class Char, class Traits>
964 class ostreambuf_iterator
965 : public iterator<output_iterator_tag, void, void, void, void>
966 {
967 public:
968 using char_type = Char;
969 using traits_type = Traits;
970 using streambuf_type = basic_streambuf<char_type, traits_type>;
971 using ostream_type = basic_ostream<char_type, traits_type>;
972
973 ostreambuf_iterator(ostream_type& os) noexcept
974 : sbuf_{os.rdbuf()}
975 { /* DUMMY BODY */ }
976
977 ostreambuf_iterator(streambuf_type* sbuf) noexcept
978 : sbuf_{sbuf}
979 { /* DUMMY BODY */ }
980
981 ostreambuf_iterator& operator=(char_type c)
982 {
983 if (!failed() && sbuf_->sputc(c) == traits_type::eof())
984 failed_ = true;
985
986 return *this;
987 }
988
989 ostreambuf_iterator& operator*()
990 {
991 return *this;
992 }
993
994 ostreambuf_iterator& operator++()
995 {
996 return *this;
997 }
998
999 ostreambuf_iterator& operator++(int)
1000 {
1001 return *this;
1002 }
1003
1004 bool failed() const noexcept
1005 {
1006 return failed_;
1007 }
1008
1009 private:
1010 streambuf_type* sbuf_;
1011
1012 bool failed_{false};
1013 };
1014
1015 /**
1016 * 24.7, range access:
1017 */
1018
1019 template<class Container>
1020 auto begin(Container& c) -> decltype(c.begin())
1021 {
1022 return c.begin();
1023 }
1024
1025 template<class Container>
1026 auto begin(const Container& c) -> decltype(c.begin())
1027 {
1028 return c.begin();
1029 }
1030
1031 template<class Container>
1032 auto end(Container& c) -> decltype(c.end())
1033 {
1034 return c.end();
1035 }
1036
1037 template<class Container>
1038 auto end(const Container& c) -> decltype(c.end())
1039 {
1040 return c.end();
1041 }
1042
1043 template<class T, size_t N>
1044 constexpr T* begin(T (&array)[N]) noexcept
1045 {
1046 return array;
1047 }
1048
1049 template<class T, size_t N>
1050 constexpr T* end(T (&array)[N]) noexcept
1051 {
1052 return array + N;
1053 }
1054
1055 template<class Container>
1056 constexpr auto cbegin(const Container& c) noexcept(noexcept(std::begin(c)))
1057 -> decltype(std::begin(c))
1058 {
1059 return std::begin(c);
1060 }
1061
1062 template<class Container>
1063 constexpr auto cend(const Container& c) noexcept(noexcept(std::end(c)))
1064 -> decltype(std::end(c))
1065 {
1066 return std::end(c);
1067 }
1068
1069 template<class Container>
1070 auto rbegin(Container& c) -> decltype(c.rbegin())
1071 {
1072 return c.rbegin();
1073 }
1074
1075 template<class Container>
1076 auto rbegin(const Container& c) -> decltype(c.rbegin())
1077 {
1078 return c.rbegin();
1079 }
1080
1081 template<class Container>
1082 auto rend(Container& c) -> decltype(c.rend())
1083 {
1084 return c.rend();
1085 }
1086
1087 template<class Container>
1088 auto rend(const Container& c) -> decltype(c.rend())
1089 {
1090 return c.rend();
1091 }
1092
1093 template<class T, size_t N>
1094 reverse_iterator<T*> rbegin(T (&array)[N])
1095 {
1096 return reverse_iterator<T*>{array + N};
1097 }
1098
1099 template<class T, size_t N>
1100 reverse_iterator<T*> rend(T (&array)[N])
1101 {
1102 return reverse_iterator<T*>{array};
1103 }
1104
1105 template<class T>
1106 reverse_iterator<const T*> rbegin(initializer_list<T> init)
1107 {
1108 return reverse_iterator<const T*>{init.end()};
1109 }
1110
1111 template<class T>
1112 reverse_iterator<const T*> rend(initializer_list<T> init)
1113 {
1114 return reverse_iterator<const T*>{init.begin()};
1115 }
1116
1117 template<class Container>
1118 auto crbegin(const Container& c) -> decltype(std::rbegin(c))
1119 {
1120 return std::rbegin(c);
1121 }
1122
1123 template<class Container>
1124 auto crend(const Container& c) -> decltype(std::rend(c))
1125 {
1126 return std::rend(c);
1127 }
1128
1129 /**
1130 * 24.8, container access:
1131 */
1132
1133 template<class Container>
1134 constexpr auto size(const Container& c) -> decltype(c.size())
1135 {
1136 return c.size();
1137 }
1138
1139 template<class T, size_t N>
1140 constexpr size_t size(T (&array)[N]) noexcept
1141 {
1142 return N;
1143 }
1144
1145 template<class Container>
1146 constexpr auto empty(const Container& c) -> decltype(c.empty())
1147 {
1148 return c.empty();
1149 }
1150
1151 template<class T, size_t N>
1152 constexpr bool empty(T (&array)[N]) noexcept
1153 {
1154 return false;
1155 }
1156
1157 template<class T>
1158 constexpr bool empty(initializer_list<T> init) noexcept
1159 {
1160 return init.size() == 0;
1161 }
1162
1163 template<class Container>
1164 constexpr auto data(Container& c) -> decltype(c.data())
1165 {
1166 return c.data();
1167 }
1168
1169 template<class Container>
1170 constexpr auto data(const Container& c) -> decltype(c.data())
1171 {
1172 return c.data();
1173 }
1174
1175 template<class T, size_t N>
1176 constexpr T* data(T (&array)[N]) noexcept
1177 {
1178 return array;
1179 }
1180
1181 template<class T>
1182 constexpr const T* data(initializer_list<T> init) noexcept
1183 {
1184 return init.begin();
1185 }
[aab972f]1186}
1187
1188#endif
Note: See TracBrowser for help on using the repository browser.