source: mainline/uspace/lib/cpp/include/__bits/iterator.hpp@ e49d0ac

Last change on this file since e49d0ac was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

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