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

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

cpp: fixed bugs found by deque tests

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