1 // String based streams -*- C++ -*-
3 // Copyright (C) 1997-2020 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/sstream
26 * This is a Standard C++ Library header.
30 // ISO C++ 14882: 27.7 String-based streams
33 #ifndef _GLIBCXX_SSTREAM
34 #define _GLIBCXX_SSTREAM 1
36 #pragma GCC system_header
41 namespace std _GLIBCXX_VISIBILITY(default)
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 _GLIBCXX_BEGIN_NAMESPACE_CXX11
46 // [27.7.1] template class basic_stringbuf
48 * @brief The actual work of input and output (for std::string).
51 * @tparam _CharT Type of character stream.
52 * @tparam _Traits Traits for character type, defaults to
53 * char_traits<_CharT>.
54 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
56 * This class associates either or both of its input and output sequences
57 * with a sequence of characters, which can be initialized from, or made
58 * available as, a @c std::basic_string. (Paraphrased from [27.7.1]/1.)
60 * For this class, open modes (of type @c ios_base::openmode) have
61 * @c in set if the input sequence can be read, and @c out set if the
62 * output sequence can be written.
64 template<typename _CharT, typename _Traits, typename _Alloc>
65 class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
67 struct __xfer_bufptrs;
70 typedef _CharT char_type;
71 typedef _Traits traits_type;
72 // _GLIBCXX_RESOLVE_LIB_DEFECTS
73 // 251. basic_stringbuf missing allocator_type
74 typedef _Alloc allocator_type;
75 typedef typename traits_type::int_type int_type;
76 typedef typename traits_type::pos_type pos_type;
77 typedef typename traits_type::off_type off_type;
79 typedef basic_streambuf<char_type, traits_type> __streambuf_type;
80 typedef basic_string<char_type, _Traits, _Alloc> __string_type;
81 typedef typename __string_type::size_type __size_type;
84 /// Place to stash in || out || in | out settings for current stringbuf.
85 ios_base::openmode _M_mode;
88 __string_type _M_string;
94 * @brief Starts with an empty string buffer.
96 * The default constructor initializes the parent class using its
100 : __streambuf_type(), _M_mode(ios_base::in | ios_base::out), _M_string()
104 * @brief Starts with an empty string buffer.
105 * @param __mode Whether the buffer can read, or write, or both.
107 * The default constructor initializes the parent class using its
111 basic_stringbuf(ios_base::openmode __mode)
112 : __streambuf_type(), _M_mode(__mode), _M_string()
116 * @brief Starts with an existing string buffer.
117 * @param __str A string to copy as a starting buffer.
118 * @param __mode Whether the buffer can read, or write, or both.
120 * This constructor initializes the parent class using its
124 basic_stringbuf(const __string_type& __str,
125 ios_base::openmode __mode = ios_base::in | ios_base::out)
126 : __streambuf_type(), _M_mode(),
127 _M_string(__str.data(), __str.size(), __str.get_allocator())
128 { _M_stringbuf_init(__mode); }
130 #if __cplusplus >= 201103L
131 basic_stringbuf(const basic_stringbuf&) = delete;
133 basic_stringbuf(basic_stringbuf&& __rhs)
134 : basic_stringbuf(std::move(__rhs), __xfer_bufptrs(__rhs, this))
135 { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); }
137 // 27.8.2.2 Assign and swap:
140 operator=(const basic_stringbuf&) = delete;
143 operator=(basic_stringbuf&& __rhs)
145 __xfer_bufptrs __st{__rhs, this};
146 const __streambuf_type& __base = __rhs;
147 __streambuf_type::operator=(__base);
148 this->pubimbue(__rhs.getloc());
149 _M_mode = __rhs._M_mode;
150 _M_string = std::move(__rhs._M_string);
151 __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0);
156 swap(basic_stringbuf& __rhs)
158 __xfer_bufptrs __l_st{*this, std::__addressof(__rhs)};
159 __xfer_bufptrs __r_st{__rhs, this};
160 __streambuf_type& __base = __rhs;
161 __streambuf_type::swap(__base);
162 __rhs.pubimbue(this->pubimbue(__rhs.getloc()));
163 std::swap(_M_mode, __rhs._M_mode);
164 std::swap(_M_string, __rhs._M_string);
170 * @brief Copying out the string buffer.
171 * @return A copy of one of the underlying sequences.
173 * <em>If the buffer is only created in input mode, the underlying
174 * character sequence is equal to the input sequence; otherwise, it
175 * is equal to the output sequence.</em> [27.7.1.2]/1
180 __string_type __ret(_M_string.get_allocator());
183 // The current egptr() may not be the actual string end.
184 if (this->pptr() > this->egptr())
185 __ret.assign(this->pbase(), this->pptr());
187 __ret.assign(this->pbase(), this->egptr());
195 * @brief Setting a new buffer.
196 * @param __s The string to use as a new sequence.
198 * Deallocates any previous stored sequence, then copies @a s to
202 str(const __string_type& __s)
204 // Cannot use _M_string = __s, since v3 strings are COW
205 // (not always true now but assign() always works).
206 _M_string.assign(__s.data(), __s.size());
207 _M_stringbuf_init(_M_mode);
211 // Common initialization code goes here.
213 _M_stringbuf_init(ios_base::openmode __mode)
216 __size_type __len = 0;
217 if (_M_mode & (ios_base::ate | ios_base::app))
218 __len = _M_string.size();
219 _M_sync(const_cast<char_type*>(_M_string.data()), 0, __len);
225 streamsize __ret = -1;
226 if (_M_mode & ios_base::in)
229 __ret = this->egptr() - this->gptr();
238 pbackfail(int_type __c = traits_type::eof());
241 overflow(int_type __c = traits_type::eof());
244 * @brief Manipulates the buffer.
245 * @param __s Pointer to a buffer area.
246 * @param __n Size of @a __s.
249 * If no buffer has already been created, and both @a __s and @a __n are
250 * non-zero, then @c __s is used as a buffer; see
251 * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering
254 virtual __streambuf_type*
255 setbuf(char_type* __s, streamsize __n)
259 // This is implementation-defined behavior, and assumes
260 // that an external char_type array of length __n exists
261 // and has been pre-allocated. If this is not the case,
262 // things will quickly blow up.
264 // Step 1: Destroy the current internal array.
267 // Step 2: Use the external array.
268 _M_sync(__s, __n, 0);
274 seekoff(off_type __off, ios_base::seekdir __way,
275 ios_base::openmode __mode = ios_base::in | ios_base::out);
278 seekpos(pos_type __sp,
279 ios_base::openmode __mode = ios_base::in | ios_base::out);
281 // Internal function for correctly updating the internal buffer
282 // for a particular _M_string, due to initialization or re-sizing
283 // of an existing _M_string.
285 _M_sync(char_type* __base, __size_type __i, __size_type __o);
287 // Internal function for correctly updating egptr() to the actual
292 const bool __testin = _M_mode & ios_base::in;
293 if (this->pptr() && this->pptr() > this->egptr())
296 this->setg(this->eback(), this->gptr(), this->pptr());
298 this->setg(this->pptr(), this->pptr(), this->pptr());
302 // Works around the issue with pbump, part of the protected
303 // interface of basic_streambuf, taking just an int.
305 _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off);
308 #if __cplusplus >= 201103L
309 #if _GLIBCXX_USE_CXX11_ABI
310 // This type captures the state of the gptr / pptr pointers as offsets
311 // so they can be restored in another object after moving the string.
312 struct __xfer_bufptrs
314 __xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to)
315 : _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1}
317 const _CharT* const __str = __from._M_string.data();
318 const _CharT* __end = nullptr;
321 _M_goff[0] = __from.eback() - __str;
322 _M_goff[1] = __from.gptr() - __str;
323 _M_goff[2] = __from.egptr() - __str;
324 __end = __from.egptr();
328 _M_poff[0] = __from.pbase() - __str;
329 _M_poff[1] = __from.pptr() - __from.pbase();
330 _M_poff[2] = __from.epptr() - __str;
331 if (__from.pptr() > __end)
332 __end = __from.pptr();
335 // Set _M_string length to the greater of the get and put areas.
338 // The const_cast avoids changing this constructor's signature,
339 // because it is exported from the dynamic library.
340 auto& __mut_from = const_cast<basic_stringbuf&>(__from);
341 __mut_from._M_string._M_length(__end - __str);
347 char_type* __str = const_cast<char_type*>(_M_to->_M_string.data());
348 if (_M_goff[0] != -1)
349 _M_to->setg(__str+_M_goff[0], __str+_M_goff[1], __str+_M_goff[2]);
350 if (_M_poff[0] != -1)
351 _M_to->_M_pbump(__str+_M_poff[0], __str+_M_poff[2], _M_poff[1]);
354 basic_stringbuf* _M_to;
359 // This type does nothing when using Copy-On-Write strings.
360 struct __xfer_bufptrs
362 __xfer_bufptrs(const basic_stringbuf&, basic_stringbuf*) { }
366 // The move constructor initializes an __xfer_bufptrs temporary then
367 // delegates to this constructor to performs moves during its lifetime.
368 basic_stringbuf(basic_stringbuf&& __rhs, __xfer_bufptrs&&)
369 : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)),
370 _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string))
376 // [27.7.2] Template class basic_istringstream
378 * @brief Controlling input for std::string.
381 * @tparam _CharT Type of character stream.
382 * @tparam _Traits Traits for character type, defaults to
383 * char_traits<_CharT>.
384 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
386 * This class supports reading from objects of type std::basic_string,
387 * using the inherited functions from std::basic_istream. To control
388 * the associated sequence, an instance of std::basic_stringbuf is used,
389 * which this page refers to as @c sb.
391 template<typename _CharT, typename _Traits, typename _Alloc>
392 class basic_istringstream : public basic_istream<_CharT, _Traits>
396 typedef _CharT char_type;
397 typedef _Traits traits_type;
398 // _GLIBCXX_RESOLVE_LIB_DEFECTS
399 // 251. basic_stringbuf missing allocator_type
400 typedef _Alloc allocator_type;
401 typedef typename traits_type::int_type int_type;
402 typedef typename traits_type::pos_type pos_type;
403 typedef typename traits_type::off_type off_type;
405 // Non-standard types:
406 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
407 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type;
408 typedef basic_istream<char_type, traits_type> __istream_type;
411 __stringbuf_type _M_stringbuf;
417 * @brief Default constructor starts with an empty string buffer.
419 * Initializes @c sb using @c in, and passes @c &sb to the base
420 * class initializer. Does not allocate any buffer.
422 * That's a lie. We initialize the base class with NULL, because the
423 * string class does its own memory management.
425 basic_istringstream()
426 : __istream_type(), _M_stringbuf(ios_base::in)
427 { this->init(&_M_stringbuf); }
430 * @brief Starts with an empty string buffer.
431 * @param __mode Whether the buffer can read, or write, or both.
433 * @c ios_base::in is automatically included in @a __mode.
435 * Initializes @c sb using @c __mode|in, and passes @c &sb to the base
436 * class initializer. Does not allocate any buffer.
438 * That's a lie. We initialize the base class with NULL, because the
439 * string class does its own memory management.
442 basic_istringstream(ios_base::openmode __mode)
443 : __istream_type(), _M_stringbuf(__mode | ios_base::in)
444 { this->init(&_M_stringbuf); }
447 * @brief Starts with an existing string buffer.
448 * @param __str A string to copy as a starting buffer.
449 * @param __mode Whether the buffer can read, or write, or both.
451 * @c ios_base::in is automatically included in @a mode.
453 * Initializes @c sb using @a str and @c mode|in, and passes @c &sb
454 * to the base class initializer.
456 * That's a lie. We initialize the base class with NULL, because the
457 * string class does its own memory management.
460 basic_istringstream(const __string_type& __str,
461 ios_base::openmode __mode = ios_base::in)
462 : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in)
463 { this->init(&_M_stringbuf); }
466 * @brief The destructor does nothing.
468 * The buffer is deallocated by the stringbuf object, not the
471 ~basic_istringstream()
474 #if __cplusplus >= 201103L
475 basic_istringstream(const basic_istringstream&) = delete;
477 basic_istringstream(basic_istringstream&& __rhs)
478 : __istream_type(std::move(__rhs)),
479 _M_stringbuf(std::move(__rhs._M_stringbuf))
480 { __istream_type::set_rdbuf(&_M_stringbuf); }
482 // 27.8.3.2 Assign and swap:
485 operator=(const basic_istringstream&) = delete;
488 operator=(basic_istringstream&& __rhs)
490 __istream_type::operator=(std::move(__rhs));
491 _M_stringbuf = std::move(__rhs._M_stringbuf);
496 swap(basic_istringstream& __rhs)
498 __istream_type::swap(__rhs);
499 _M_stringbuf.swap(__rhs._M_stringbuf);
505 * @brief Accessing the underlying buffer.
506 * @return The current basic_stringbuf buffer.
508 * This hides both signatures of std::basic_ios::rdbuf().
512 { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
515 * @brief Copying out the string buffer.
516 * @return @c rdbuf()->str()
520 { return _M_stringbuf.str(); }
523 * @brief Setting a new buffer.
524 * @param __s The string to use as a new sequence.
526 * Calls @c rdbuf()->str(s).
529 str(const __string_type& __s)
530 { _M_stringbuf.str(__s); }
534 // [27.7.3] Template class basic_ostringstream
536 * @brief Controlling output for std::string.
539 * @tparam _CharT Type of character stream.
540 * @tparam _Traits Traits for character type, defaults to
541 * char_traits<_CharT>.
542 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
544 * This class supports writing to objects of type std::basic_string,
545 * using the inherited functions from std::basic_ostream. To control
546 * the associated sequence, an instance of std::basic_stringbuf is used,
547 * which this page refers to as @c sb.
549 template <typename _CharT, typename _Traits, typename _Alloc>
550 class basic_ostringstream : public basic_ostream<_CharT, _Traits>
554 typedef _CharT char_type;
555 typedef _Traits traits_type;
556 // _GLIBCXX_RESOLVE_LIB_DEFECTS
557 // 251. basic_stringbuf missing allocator_type
558 typedef _Alloc allocator_type;
559 typedef typename traits_type::int_type int_type;
560 typedef typename traits_type::pos_type pos_type;
561 typedef typename traits_type::off_type off_type;
563 // Non-standard types:
564 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
565 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type;
566 typedef basic_ostream<char_type, traits_type> __ostream_type;
569 __stringbuf_type _M_stringbuf;
572 // Constructors/destructor:
575 * @brief Default constructor starts with an empty string buffer.
577 * Initializes @c sb using @c mode|out, and passes @c &sb to the base
578 * class initializer. Does not allocate any buffer.
580 * That's a lie. We initialize the base class with NULL, because the
581 * string class does its own memory management.
583 basic_ostringstream()
584 : __ostream_type(), _M_stringbuf(ios_base::out)
585 { this->init(&_M_stringbuf); }
588 * @brief Starts with an empty string buffer.
589 * @param __mode Whether the buffer can read, or write, or both.
591 * @c ios_base::out is automatically included in @a mode.
593 * Initializes @c sb using @c mode|out, and passes @c &sb to the base
594 * class initializer. Does not allocate any buffer.
596 * That's a lie. We initialize the base class with NULL, because the
597 * string class does its own memory management.
600 basic_ostringstream(ios_base::openmode __mode)
601 : __ostream_type(), _M_stringbuf(__mode | ios_base::out)
602 { this->init(&_M_stringbuf); }
605 * @brief Starts with an existing string buffer.
606 * @param __str A string to copy as a starting buffer.
607 * @param __mode Whether the buffer can read, or write, or both.
609 * @c ios_base::out is automatically included in @a mode.
611 * Initializes @c sb using @a str and @c mode|out, and passes @c &sb
612 * to the base class initializer.
614 * That's a lie. We initialize the base class with NULL, because the
615 * string class does its own memory management.
618 basic_ostringstream(const __string_type& __str,
619 ios_base::openmode __mode = ios_base::out)
620 : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out)
621 { this->init(&_M_stringbuf); }
624 * @brief The destructor does nothing.
626 * The buffer is deallocated by the stringbuf object, not the
629 ~basic_ostringstream()
632 #if __cplusplus >= 201103L
633 basic_ostringstream(const basic_ostringstream&) = delete;
635 basic_ostringstream(basic_ostringstream&& __rhs)
636 : __ostream_type(std::move(__rhs)),
637 _M_stringbuf(std::move(__rhs._M_stringbuf))
638 { __ostream_type::set_rdbuf(&_M_stringbuf); }
640 // 27.8.3.2 Assign and swap:
643 operator=(const basic_ostringstream&) = delete;
646 operator=(basic_ostringstream&& __rhs)
648 __ostream_type::operator=(std::move(__rhs));
649 _M_stringbuf = std::move(__rhs._M_stringbuf);
654 swap(basic_ostringstream& __rhs)
656 __ostream_type::swap(__rhs);
657 _M_stringbuf.swap(__rhs._M_stringbuf);
663 * @brief Accessing the underlying buffer.
664 * @return The current basic_stringbuf buffer.
666 * This hides both signatures of std::basic_ios::rdbuf().
670 { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
673 * @brief Copying out the string buffer.
674 * @return @c rdbuf()->str()
678 { return _M_stringbuf.str(); }
681 * @brief Setting a new buffer.
682 * @param __s The string to use as a new sequence.
684 * Calls @c rdbuf()->str(s).
687 str(const __string_type& __s)
688 { _M_stringbuf.str(__s); }
692 // [27.7.4] Template class basic_stringstream
694 * @brief Controlling input and output for std::string.
697 * @tparam _CharT Type of character stream.
698 * @tparam _Traits Traits for character type, defaults to
699 * char_traits<_CharT>.
700 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
702 * This class supports reading from and writing to objects of type
703 * std::basic_string, using the inherited functions from
704 * std::basic_iostream. To control the associated sequence, an instance
705 * of std::basic_stringbuf is used, which this page refers to as @c sb.
707 template <typename _CharT, typename _Traits, typename _Alloc>
708 class basic_stringstream : public basic_iostream<_CharT, _Traits>
712 typedef _CharT char_type;
713 typedef _Traits traits_type;
714 // _GLIBCXX_RESOLVE_LIB_DEFECTS
715 // 251. basic_stringbuf missing allocator_type
716 typedef _Alloc allocator_type;
717 typedef typename traits_type::int_type int_type;
718 typedef typename traits_type::pos_type pos_type;
719 typedef typename traits_type::off_type off_type;
721 // Non-standard Types:
722 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
723 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type;
724 typedef basic_iostream<char_type, traits_type> __iostream_type;
727 __stringbuf_type _M_stringbuf;
730 // Constructors/destructors
733 * @brief Default constructor starts with an empty string buffer.
735 * Initializes @c sb using the mode @c in|out, and passes @c &sb
736 * to the base class initializer. Does not allocate any buffer.
738 * That's a lie. We initialize the base class with NULL, because the
739 * string class does its own memory management.
742 : __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in)
743 { this->init(&_M_stringbuf); }
746 * @brief Starts with an empty string buffer.
747 * @param __m Whether the buffer can read, or write, or both.
749 * Initializes @c sb using the mode from @c __m, and passes @c &sb
750 * to the base class initializer. Does not allocate any buffer.
752 * That's a lie. We initialize the base class with NULL, because the
753 * string class does its own memory management.
756 basic_stringstream(ios_base::openmode __m)
757 : __iostream_type(), _M_stringbuf(__m)
758 { this->init(&_M_stringbuf); }
761 * @brief Starts with an existing string buffer.
762 * @param __str A string to copy as a starting buffer.
763 * @param __m Whether the buffer can read, or write, or both.
765 * Initializes @c sb using @a __str and @c __m, and passes @c &sb
766 * to the base class initializer.
768 * That's a lie. We initialize the base class with NULL, because the
769 * string class does its own memory management.
772 basic_stringstream(const __string_type& __str,
773 ios_base::openmode __m = ios_base::out | ios_base::in)
774 : __iostream_type(), _M_stringbuf(__str, __m)
775 { this->init(&_M_stringbuf); }
778 * @brief The destructor does nothing.
780 * The buffer is deallocated by the stringbuf object, not the
783 ~basic_stringstream()
786 #if __cplusplus >= 201103L
787 basic_stringstream(const basic_stringstream&) = delete;
789 basic_stringstream(basic_stringstream&& __rhs)
790 : __iostream_type(std::move(__rhs)),
791 _M_stringbuf(std::move(__rhs._M_stringbuf))
792 { __iostream_type::set_rdbuf(&_M_stringbuf); }
794 // 27.8.3.2 Assign and swap:
797 operator=(const basic_stringstream&) = delete;
800 operator=(basic_stringstream&& __rhs)
802 __iostream_type::operator=(std::move(__rhs));
803 _M_stringbuf = std::move(__rhs._M_stringbuf);
808 swap(basic_stringstream& __rhs)
810 __iostream_type::swap(__rhs);
811 _M_stringbuf.swap(__rhs._M_stringbuf);
817 * @brief Accessing the underlying buffer.
818 * @return The current basic_stringbuf buffer.
820 * This hides both signatures of std::basic_ios::rdbuf().
824 { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
827 * @brief Copying out the string buffer.
828 * @return @c rdbuf()->str()
832 { return _M_stringbuf.str(); }
835 * @brief Setting a new buffer.
836 * @param __s The string to use as a new sequence.
838 * Calls @c rdbuf()->str(s).
841 str(const __string_type& __s)
842 { _M_stringbuf.str(__s); }
845 #if __cplusplus >= 201103L
846 /// Swap specialization for stringbufs.
847 template <class _CharT, class _Traits, class _Allocator>
849 swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x,
850 basic_stringbuf<_CharT, _Traits, _Allocator>& __y)
853 /// Swap specialization for istringstreams.
854 template <class _CharT, class _Traits, class _Allocator>
856 swap(basic_istringstream<_CharT, _Traits, _Allocator>& __x,
857 basic_istringstream<_CharT, _Traits, _Allocator>& __y)
860 /// Swap specialization for ostringstreams.
861 template <class _CharT, class _Traits, class _Allocator>
863 swap(basic_ostringstream<_CharT, _Traits, _Allocator>& __x,
864 basic_ostringstream<_CharT, _Traits, _Allocator>& __y)
867 /// Swap specialization for stringstreams.
868 template <class _CharT, class _Traits, class _Allocator>
870 swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x,
871 basic_stringstream<_CharT, _Traits, _Allocator>& __y)
875 _GLIBCXX_END_NAMESPACE_CXX11
876 _GLIBCXX_END_NAMESPACE_VERSION
879 #include <bits/sstream.tcc>
881 #endif /* _GLIBCXX_SSTREAM */