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

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

cpp: finished iterators

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