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

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

cpp: fixed distance, it used postincrement which resulted in end() dereference

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