source: mainline/uspace/lib/cpp/include/__bits/io/istream.hpp@ 7dcce0a

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

cpp: abort and report when an unimplemented function is called

  • Property mode set to 100644
File size: 29.3 KB
Line 
1/*
2 * Copyright (c) 2019 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_BITS_IO_ISTREAM
30#define LIBCPP_BITS_IO_ISTREAM
31
32#include <cassert>
33#include <ios>
34#include <iosfwd>
35#include <limits>
36#include <locale>
37#include <ostream>
38#include <utility>
39
40namespace std
41{
42
43 /**
44 * 27.7.2.1, class template basic_stream:
45 */
46
47 template<class Char, class Traits>
48 class basic_istream: virtual public basic_ios<Char, Traits>
49 {
50 public:
51 using traits_type = Traits;
52 using char_type = Char;
53 using int_type = typename traits_type::int_type;
54 using pos_type = typename traits_type::pos_type;
55 using off_type = typename traits_type::off_type;
56
57 /**
58 * 27.7.2.1.1, constructor/destructor:
59 */
60
61 explicit basic_istream(basic_streambuf<Char, Traits>* sb)
62 : gcount_{0}
63 {
64 basic_ios<Char, Traits>::init(sb);
65 }
66
67 virtual ~basic_istream()
68 { /* DUMMY BODY */ }
69
70 /**
71 * 27.7.2.1.3, prefix/suffix:
72 */
73
74 class sentry
75 {
76 public:
77 explicit sentry(basic_istream<Char, Traits>& is, bool noskipws = false)
78 : ok_{false}
79 {
80 if (!is.good())
81 is.setstate(ios_base::failbit);
82 else
83 {
84 if (is.tie())
85 is.tie()->flush();
86
87 if (!noskipws && ((is.flags() & ios_base::skipws) != 0))
88 {
89 const auto& ct = use_facet<ctype<Char>>(is.getloc());
90 while (true)
91 {
92 auto i = is.rdbuf()->sgetc();
93 if (Traits::eq_int_type(i, Traits::eof()))
94 {
95 is.setstate(ios_base::failbit | ios_base::eofbit);
96 break;
97 }
98
99 auto c = Traits::to_char_type(i);
100 if (!ct.is(ctype_base::space, c))
101 break;
102 else
103 is.rdbuf()->sbumpc();
104 }
105 }
106 }
107
108 if (is.good())
109 ok_ = true;
110 }
111
112 ~sentry() = default;
113
114 explicit operator bool() const
115 {
116 return ok_;
117 }
118
119 sentry(const sentry&) = delete;
120 sentry& operator=(const sentry&) = delete;
121
122 private:
123 using traits_type = Traits;
124 bool ok_;
125 };
126
127 /**
128 * 27.7.2.2, formatted input:
129 */
130
131 basic_istream<Char, Traits>& operator>>(
132 basic_istream<Char, Traits>& (*pf)(basic_istream<Char, Traits>&)
133 )
134 {
135 return pf(*this);
136 }
137
138 basic_istream<Char, Traits>& operator>>(
139 basic_ios<Char, Traits>& (*pf)(basic_ios<Char, Traits>&)
140 )
141 {
142 pf(*this);
143
144 return *this;
145 }
146
147 basic_istream<Char, Traits>& operator>>(
148 ios_base& (*pf)(ios_base&)
149 )
150 {
151 pf(*this);
152
153 return *this;
154 }
155
156 basic_istream<Char, Traits>& operator>>(bool& x)
157 {
158 sentry sen{*this, false};
159
160 if (sen)
161 {
162 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
163 auto err = ios_base::goodbit;
164
165 auto loc = this->getloc();
166 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
167 this->setstate(err);
168 }
169
170 return *this;
171 }
172
173 basic_istream<Char, Traits>& operator>>(short& x)
174 {
175 sentry sen{*this, false};
176
177 if (sen)
178 {
179 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
180 auto err = ios_base::goodbit;
181
182 long tmp{};
183 auto loc = this->getloc();
184 use_facet<num_get>(loc).get(*this, 0, *this, err, tmp);
185
186 if (tmp < numeric_limits<short>::min())
187 {
188 err |= ios_base::failbit;
189 x = numeric_limits<short>::min();
190 }
191 else if (numeric_limits<short>::max() < tmp)
192 {
193 err |= ios_base::failbit;
194 x = numeric_limits<short>::max();
195 }
196 else
197 x = static_cast<short>(tmp);
198
199 this->setstate(err);
200 }
201
202 return *this;
203 }
204
205 basic_istream<Char, Traits>& operator>>(unsigned short& x)
206 {
207 sentry sen{*this, false};
208
209 if (sen)
210 {
211 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
212 auto err = ios_base::goodbit;
213
214 auto loc = this->getloc();
215 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
216 this->setstate(err);
217 }
218
219 return *this;
220 }
221
222 basic_istream<Char, Traits>& operator>>(int& x)
223 {
224 sentry sen{*this, false};
225
226 if (sen)
227 {
228 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
229 auto err = ios_base::goodbit;
230
231 long tmp{};
232 auto loc = this->getloc();
233 use_facet<num_get>(loc).get(*this, 0, *this, err, tmp);
234
235 if (tmp < numeric_limits<int>::min())
236 {
237 err |= ios_base::failbit;
238 x = numeric_limits<int>::min();
239 }
240 else if (numeric_limits<int>::max() < tmp)
241 {
242 err |= ios_base::failbit;
243 x = numeric_limits<int>::max();
244 }
245 else
246 x = static_cast<int>(tmp);
247
248 this->setstate(err);
249 }
250
251 return *this;
252 }
253
254 basic_istream<Char, Traits>& operator>>(unsigned int& x)
255 {
256 sentry sen{*this, false};
257
258 if (sen)
259 {
260 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
261 auto err = ios_base::goodbit;
262
263 auto loc = this->getloc();
264 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
265 this->setstate(err);
266 }
267
268 return *this;
269 }
270
271 basic_istream<Char, Traits>& operator>>(long& x)
272 {
273 sentry sen{*this, false};
274
275 if (sen)
276 {
277 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
278 auto err = ios_base::goodbit;
279
280 auto loc = this->getloc();
281 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
282 this->setstate(err);
283 }
284
285 return *this;
286 }
287
288 basic_istream<Char, Traits>& operator>>(unsigned long& x)
289 {
290 sentry sen{*this, false};
291
292 if (sen)
293 {
294 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
295 auto err = ios_base::goodbit;
296
297 auto loc = this->getloc();
298 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
299 this->setstate(err);
300 }
301
302 return *this;
303 }
304
305 basic_istream<Char, Traits>& operator>>(long long& x)
306 {
307 sentry sen{*this, false};
308
309 if (sen)
310 {
311 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
312 auto err = ios_base::goodbit;
313
314 auto loc = this->getloc();
315 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
316 this->setstate(err);
317 }
318
319 return *this;
320 }
321
322 basic_istream<Char, Traits>& operator>>(unsigned long long& x)
323 {
324 sentry sen{*this, false};
325
326 if (sen)
327 {
328 using num_get = num_get<Char, istreambuf_iterator<Char, Traits>>;
329 auto err = ios_base::goodbit;
330
331 auto loc = this->getloc();
332 use_facet<num_get>(loc).get(*this, 0, *this, err, x);
333 this->setstate(err);
334 }
335
336 return *this;
337 }
338
339 basic_istream<Char, Traits>& operator>>(float& x)
340 {
341 // TODO: implement
342 __unimplemented();
343 return *this;
344 }
345
346 basic_istream<Char, Traits>& operator>>(double& x)
347 {
348 // TODO: implement
349 __unimplemented();
350 return *this;
351 }
352
353 basic_istream<Char, Traits>& operator>>(long double& x)
354 {
355 // TODO: implement
356 __unimplemented();
357 return *this;
358 }
359
360 basic_istream<Char, Traits>& operator>>(void*& p)
361 {
362 // TODO: implement
363 __unimplemented();
364 return *this;
365 }
366
367 basic_istream<Char, Traits>& operator>>(basic_streambuf<Char, Traits>* sb)
368 {
369 if (!sb)
370 {
371 this->setstate(ios_base::failbit);
372 return *this;
373 }
374
375 gcount_ = 0;
376 sentry sen{*this, false};
377
378 if (sen)
379 {
380 while (true)
381 {
382 auto ic = this->rdbuf()->sgetc();
383 if (traits_type::eq_int_type(ic, traits_type::eof()))
384 {
385 this->setstate(ios_base::eofbit);
386 break;
387 }
388
389 auto res = sb->sputc(traits_type::to_char_type(ic));
390 if (traits_type::eq_int_type(res, traits_type::eof()))
391 break;
392
393 ++gcount_;
394 this->rdbuf()->sbumpc();
395 }
396 }
397
398 return *this;
399 }
400
401 /**
402 * 27.7.2.3, unformatted input:
403 * TODO: Once we have exceptions, implement
404 * 27.7.2.3 paragraph 1.
405 */
406
407 streamsize gcount() const
408 {
409 return gcount_;
410 }
411
412 int_type get()
413 {
414 gcount_ = 0;
415 sentry sen{*this, true};
416
417 if (sen)
418 {
419 auto res = this->rdbuf()->sbumpc();
420 if (!traits_type::eq_int_type(res, traits_type::eof()))
421 {
422 gcount_ = 1;
423 return res;
424 }
425
426 this->setstate(ios_base::failbit | ios_base::eofbit);
427 }
428
429 return traits_type::eof();
430 }
431
432 basic_istream<Char, Traits>& get(char_type& c)
433 {
434 auto res = get();
435 if (res != traits_type::eof())
436 c = traits_type::to_char_type(res);
437
438 return *this;
439 }
440
441 basic_istream<Char, Traits>& get(char_type* s, streamsize n, char_type delim)
442 {
443 gcount_ = 0;
444 sentry sen{*this, true};
445
446 if (sen && n > 0)
447 {
448 while(gcount_ < n - 1)
449 {
450 auto c = this->rdbuf()->sbumpc();
451
452 if (traits_type::eq_int_type(c, traits_type::eof()))
453 {
454 this->setstate(ios_base::eofbit);
455 break;
456 }
457
458 s[gcount_++] = traits_type::to_char_type(c);
459
460 auto peek = traits_type::to_char_type(this->rdbuf()->sgetc());
461 if (traits_type::eq(peek, delim))
462 break;
463 }
464
465 if (gcount_ == 0)
466 this->setstate(ios_base::failbit);
467 s[n] = char_type{};
468 }
469
470 return *this;
471 }
472
473 basic_istream<Char, Traits>& get(char_type* s, streamsize n)
474 {
475 return get(s, n, this->widen('\n'));
476 }
477
478 basic_istream<Char, Traits>& get(basic_streambuf<Char, Traits>& sb)
479 {
480 get(sb, this->widen('\n'));
481 }
482
483 basic_istream<Char, Traits>& get(basic_streambuf<Char, Traits>& sb, char_type delim)
484 {
485 gcount_ = 0;
486 sentry sen{*this, true};
487
488 if (sen)
489 {
490 while (true)
491 {
492 auto i = this->rdbuf()->sgetc();
493 if (traits_type::eq_int_type(i, traits_type::eof()))
494 {
495 this->setstate(ios_base::eofbit);
496 break;
497 }
498
499 auto c = traits_type::to_char_type(i);
500 if (traits_type::eq(c, delim))
501 break;
502
503 auto insert_ret = sb.sputc(c);
504 if (traits_type::eq_int_type(insert_ret, traits_type::eof()))
505 break;
506
507 this->rdbuf()->sbumpc();
508 ++gcount_;
509 }
510
511 if (gcount_ == 0)
512 this->setstate(ios_base::failbit);
513 }
514
515 return *this;
516 }
517
518 basic_istream<Char, Traits>& getline(char_type* s, streamsize n)
519 {
520 return getline(s, n, this->widen('\n'));
521 }
522
523 basic_istream<Char, Traits>& getline(char_type* s, streamsize n, char_type delim)
524 {
525 gcount_ = 0;
526 sentry sen{*this, true};
527
528 if (sen)
529 {
530 while (true)
531 { // We have exactly specified order of checks, easier to do them in the body.
532 auto c = this->rdbuf()->sbumpc();
533
534 if (traits_type::eq_int_type(c, traits_type::eof()))
535 {
536 this->setstate(ios_base::eofbit);
537 break;
538 }
539
540 if (traits_type::eq_int_type(c, traits_type::to_int_type(delim)))
541 break;
542
543 if (n < 1 || gcount_ >= n - 1)
544 {
545 this->setstate(ios_base::failbit);
546 break;
547 }
548
549 s[gcount_++] = traits_type::to_char_type(c);
550 }
551
552 if (gcount_ == 0)
553 this->setstate(ios_base::failbit);
554 if (n > 0)
555 s[gcount_] = char_type{};
556 }
557
558 return *this;
559 }
560
561 basic_istream<Char, Traits>& ignore(streamsize n = 1, int_type delim = traits_type::eof())
562 {
563 sentry sen{*this, true};
564
565 if (sen)
566 {
567 streamsize i{};
568 while (n == numeric_limits<streamsize>::max() || i < n)
569 {
570 auto c = this->rdbuf()->sbumpc();
571
572 if (traits_type::eq_int_type(c, traits_type::eof()))
573 {
574 this->setstate(ios_base::eofbit);
575 break;
576 }
577
578 if (traits_type::eq_int_type(c, delim))
579 break;
580 }
581 }
582
583 return *this;
584 }
585
586 int_type peek()
587 {
588 sentry sen{*this, true};
589
590 if (!this->good())
591 return traits_type::eof();
592 else
593 return this->rdbuf()->sgetc();
594 }
595
596 basic_istream<Char, Traits>& read(char_type* s, streamsize n)
597 {
598 gcount_ = 0;
599 sentry sen{*this, true};
600
601 if (!this->good())
602 {
603 this->setstate(ios_base::failbit);
604 return *this;
605 }
606
607 while (gcount_ < n)
608 {
609 auto c = this->rdbuf()->sbumpc();
610 if (traits_type::eq_int_type(c, traits_type::eof()))
611 {
612 this->setstate(ios_base::failbit | ios_base::eofbit);
613 break;
614 }
615
616 s[gcount_++] = traits_type::to_char_type(c);
617 }
618
619 return *this;
620 }
621
622 streamsize readsome(char_type* s, streamsize n)
623 {
624 gcount_ = 0;
625 sentry sen{*this, true};
626
627 if (!this->good())
628 {
629 this->setstate(ios_base::failbit);
630 return streamsize{};
631 }
632
633 auto avail = this->rdbuf()->in_avail();
634 if (avail == -1)
635 {
636 this->setstate(ios_base::eofbit);
637 return streamsize{};
638 } else if (avail > 0)
639 {
640 auto count = (avail < n ? avail : n);
641 while (gcount_ < count)
642 s[gcount_++] = traits_type::to_char_type(this->rdbuf()->sbumpc());
643 }
644
645 return gcount_;
646 }
647
648 basic_istream<Char, Traits>& putback(char_type c)
649 {
650 this->clear(this->rdstate() & (~ios_base::eofbit));
651
652 gcount_ = 0;
653 sentry sen{*this, true};
654
655 if (!this->good())
656 {
657 this->setstate(ios_base::failbit);
658 return *this;
659 }
660
661 if (this->rdbuf())
662 {
663 auto ret = this->rdbuf()->sputbackc(c);
664 if (traits_type::eq_int_type(ret, traits_type::eof()))
665 this->setstate(ios_base::badbit);
666 }
667 else
668 this->setstate(ios_base::badbit);
669
670 return *this;
671 }
672
673 basic_istream<Char, Traits>& unget()
674 {
675 this->clear(this->rdstate() & (~ios_base::eofbit));
676
677 gcount_ = 0;
678 sentry sen{*this, true};
679
680 if (!this->good())
681 {
682 this->setstate(ios_base::failbit);
683 return *this;
684 }
685
686 if (this->rdbuf())
687 {
688 auto ret = this->rdbuf()->sungetc();
689 if (traits_type::eq_int_type(ret, traits_type::eof()))
690 this->setstate(ios_base::badbit);
691 }
692 else
693 this->setstate(ios_base::badbit);
694
695 return *this;
696 }
697
698 int sync()
699 {
700 sentry s{*this, true};
701
702 if (this->rdbuf())
703 {
704 auto ret = this->rdbuf()->pubsync();
705 if (ret == -1)
706 {
707 this->setstate(ios_base::badbit);
708 return -1;
709 }
710 else
711 return 0;
712 }
713 else
714 return -1;
715 }
716
717 pos_type tellg()
718 {
719 sentry s{*this, true};
720
721 if (this->fail())
722 return pos_type(-1);
723 else
724 return this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in);
725 }
726
727 basic_istream<Char, Traits>& seekg(pos_type pos)
728 {
729 this->clear(this->rdstate() & (~ios_base::eofbit));
730
731 sentry sen{*this, true};
732
733 if (!this->fail())
734 this->rdbuf()->pubseekoff(pos, ios_base::in);
735 else
736 this->setstate(ios_base::failbit);
737
738 return *this;
739 }
740
741 basic_istream<Char, Traits>& seekg(off_type off, ios_base::seekdir dir)
742 {
743 sentry sen{*this, true};
744
745 if (!this->fail())
746 this->rdbuf()->pubseekoff(off, dir, ios_base::in);
747 else
748 this->setstate(ios_base::failbit);
749
750 return *this;
751 }
752
753 protected:
754 streamsize gcount_;
755
756 basic_istream(const basic_istream&) = delete;
757
758 basic_istream(basic_istream&& rhs)
759 {
760 gcount_ = rhs.gcout_;
761
762 basic_ios<Char, Traits>::move(rhs);
763
764 rhs.gcount_ = 0;
765 }
766
767 /**
768 * 27.7.2.1.2, assign/swap:
769 */
770
771 basic_istream& operator=(const basic_istream& rhs) = delete;
772
773 basic_istream& operator=(basic_istream&& rhs)
774 {
775 swap(rhs);
776
777 return *this;
778 }
779
780 void swap(basic_istream& rhs)
781 {
782 basic_ios<Char, Traits>::swap(rhs);
783 swap(gcount_, rhs.gcount_);
784 }
785 };
786
787 /**
788 * 27.7.2.2.3, character extraction templates:
789 */
790
791 template<class Char, class Traits>
792 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
793 Char& c)
794 {
795 typename basic_istream<Char, Traits>::sentry sen{is, false};
796
797 if (sen)
798 {
799 auto ic = is.rdbuf()->sgetc();
800 if (Traits::eq_int_type(ic, Traits::eof()))
801 {
802 is.setstate(ios_base::failbit | ios_base::eofbit);
803 return is;
804 }
805
806 c = Traits::to_char_type(is.rdbuf()->sbumpc());
807 }
808
809 return is;
810 }
811
812 template<class Char, class Traits>
813 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
814 unsigned char& c)
815 {
816 return is >> reinterpret_cast<char&>(c);
817 }
818
819 template<class Char, class Traits>
820 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
821 signed char& c)
822 {
823 return is >> reinterpret_cast<char&>(c);
824 }
825
826 template<class Char, class Traits>
827 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
828 Char* str)
829 {
830 typename basic_istream<Char, Traits>::sentry sen{is, false};
831
832 if (sen)
833 {
834 const auto& ct = use_facet<ctype<Char>>(is.getloc());
835
836 size_t n{};
837 if (is.width() > 0)
838 n = static_cast<size_t>(is.width());
839 else
840 n = (numeric_limits<size_t>::max() / sizeof(Char)) - sizeof(Char);
841
842 size_t i{};
843 for (; i < n - 1; ++i)
844 {
845 auto ic = is.rdbuf()->sgetc();
846 if (Traits::eq_int_type(ic, Traits::eof()))
847 break;
848
849 auto c = Traits::to_char_type(ic);
850 if (ct.is(ctype_base::space, c))
851 break;
852
853 str[i] = c;
854 is.rdbuf()->sbumpc();
855 }
856
857 str[i] = Char{};
858 if (i == 0)
859 is.setstate(ios_base::failbit);
860 }
861
862 return is;
863 }
864
865 template<class Char, class Traits>
866 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
867 unsigned char* str)
868 {
869 return is >> reinterpret_cast<char*>(str);
870 }
871
872 template<class Char, class Traits>
873 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
874 signed char* str)
875 {
876 return is >> reinterpret_cast<char*>(str);
877 }
878
879 /**
880 * 27.7.2.4, standard basic_istream manipulators:
881 */
882
883 template<class Char, class Traits = char_traits<Char>>
884 basic_istream<Char, Traits>& ws(basic_istream<Char, Traits>& is)
885 {
886 using sentry = typename basic_istream<Char, Traits>::sentry;
887 sentry sen{is, true};
888
889 if (sen)
890 {
891 const auto& ct = use_facet<ctype<Char>>(is.getloc());
892 while (true)
893 {
894 auto i = is.rdbuf()->sgetc();
895 if (Traits::eq_int_type(i, Traits::eof()))
896 {
897 is.setstate(ios_base::eofbit);
898 break;
899 }
900
901 auto c = Traits::to_char_type(i);
902 if (!ct.is(c, ct.space))
903 break;
904 else
905 is.rdbuf()->sbumpc();
906 }
907 }
908
909 return is;
910 }
911
912 using istream = basic_istream<char>;
913 using wistream = basic_istream<wchar_t>;
914
915 /**
916 * 27.7.2.5, class template basic_iostream:
917 */
918
919 template<class Char, class Traits>
920 class basic_iostream
921 : public basic_istream<Char, Traits>,
922 public basic_ostream<Char, Traits>
923 {
924 public:
925 using char_type = Char;
926 using traits_type = Traits;
927 using int_type = typename traits_type::int_type;
928 using pos_type = typename traits_type::pos_type;
929 using off_type = typename traits_type::off_type;
930
931 explicit basic_iostream(basic_streambuf<char_type, traits_type>* sb)
932 : basic_istream<char_type, traits_type>(sb),
933 basic_ostream<char_type, traits_type>(sb)
934 { /* DUMMY BODY */ }
935
936 virtual ~basic_iostream()
937 { /* DUMMY BODY */ }
938
939 protected:
940 basic_iostream(const basic_iostream&) = delete;
941 basic_iostream& operator=(const basic_iostream&) = delete;
942
943 basic_iostream(basic_iostream&& other)
944 : basic_istream<char_type, traits_type>(move(other))
945 { /* DUMMY BODY */ }
946
947 basic_iostream& operator=(basic_iostream&& other)
948 {
949 swap(other);
950 }
951
952 void swap(basic_iostream& other)
953 {
954 basic_istream<char_type, traits_type>::swap(other);
955 }
956 };
957
958 using iostream = basic_iostream<char>;
959 using wiostream = basic_iostream<wchar_t>;
960
961 /**
962 * 27.7.2.6, rvalue stream extraction:
963 */
964
965 template<class Char, class Traits, class T>
966 basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>&& is, T& x)
967 {
968 is >> x;
969
970 return is;
971 }
972}
973
974#endif
Note: See TracBrowser for help on using the repository browser.