Home | History | Annotate | Line # | Download | only in std
      1 // String based streams -*- C++ -*-
      2 
      3 // Copyright (C) 1997-2022 Free Software Foundation, Inc.
      4 //
      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)
      9 // any later version.
     10 
     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.
     15 
     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.
     19 
     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/>.
     24 
     25 /** @file include/sstream
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 //
     30 // ISO C++ 14882: 27.7  String-based streams
     31 //
     32 
     33 #ifndef _GLIBCXX_SSTREAM
     34 #define _GLIBCXX_SSTREAM 1
     35 
     36 #pragma GCC system_header
     37 
     38 #include <istream>
     39 #include <ostream>
     40 #include <bits/alloc_traits.h> // allocator_traits, __allocator_like
     41 
     42 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
     43 # define _GLIBCXX_LVAL_REF_QUAL &
     44 # define _GLIBCXX_SSTREAM_ALWAYS_INLINE
     45 #else
     46 # define _GLIBCXX_LVAL_REF_QUAL
     47 // For symbols that are not exported from libstdc++.so for the COW string ABI.
     48 # define _GLIBCXX_SSTREAM_ALWAYS_INLINE [[__gnu__::__always_inline__]]
     49 #endif
     50 
     51 
     52 
     53 namespace std _GLIBCXX_VISIBILITY(default)
     54 {
     55 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     56 _GLIBCXX_BEGIN_NAMESPACE_CXX11
     57 
     58   // [27.7.1] template class basic_stringbuf
     59   /**
     60    *  @brief  The actual work of input and output (for std::string).
     61    *  @ingroup io
     62    *
     63    *  @tparam _CharT  Type of character stream.
     64    *  @tparam _Traits  Traits for character type, defaults to
     65    *                   char_traits<_CharT>.
     66    *  @tparam _Alloc  Allocator type, defaults to allocator<_CharT>.
     67    *
     68    *  This class associates either or both of its input and output sequences
     69    *  with a sequence of characters, which can be initialized from, or made
     70    *  available as, a @c std::basic_string.  (Paraphrased from [27.7.1]/1.)
     71    *
     72    *  For this class, open modes (of type @c ios_base::openmode) have
     73    *  @c in set if the input sequence can be read, and @c out set if the
     74    *  output sequence can be written.
     75   */
     76   template<typename _CharT, typename _Traits, typename _Alloc>
     77     class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
     78     {
     79       struct __xfer_bufptrs;
     80 
     81 #if __cplusplus >= 201103L
     82       using allocator_traits = std::allocator_traits<_Alloc>;
     83       using _Noexcept_swap
     84 	= __or_<typename allocator_traits::propagate_on_container_swap,
     85 		typename allocator_traits::is_always_equal>;
     86 #endif
     87 
     88     public:
     89       // Types:
     90       typedef _CharT 					char_type;
     91       typedef _Traits 					traits_type;
     92       // _GLIBCXX_RESOLVE_LIB_DEFECTS
     93       // 251. basic_stringbuf missing allocator_type
     94       typedef _Alloc				       	allocator_type;
     95       typedef typename traits_type::int_type 		int_type;
     96       typedef typename traits_type::pos_type 		pos_type;
     97       typedef typename traits_type::off_type 		off_type;
     98 
     99       typedef basic_streambuf<char_type, traits_type>  	__streambuf_type;
    100       typedef basic_string<char_type, _Traits, _Alloc> 	__string_type;
    101       typedef typename __string_type::size_type		__size_type;
    102 
    103     protected:
    104       /// Place to stash in || out || in | out settings for current stringbuf.
    105       ios_base::openmode 	_M_mode;
    106 
    107       // Data Members:
    108       __string_type 		_M_string;
    109 
    110     public:
    111       // Constructors:
    112 
    113       /**
    114        *  @brief  Starts with an empty string buffer.
    115        *
    116        *  The default constructor initializes the parent class using its
    117        *  own default ctor.
    118       */
    119       basic_stringbuf()
    120       : __streambuf_type(), _M_mode(ios_base::in | ios_base::out), _M_string()
    121       { }
    122 
    123       /**
    124        *  @brief  Starts with an empty string buffer.
    125        *  @param  __mode  Whether the buffer can read, or write, or both.
    126        *
    127        *  The default constructor initializes the parent class using its
    128        *  own default ctor.
    129       */
    130       explicit
    131       basic_stringbuf(ios_base::openmode __mode)
    132       : __streambuf_type(), _M_mode(__mode), _M_string()
    133       { }
    134 
    135       /**
    136        *  @brief  Starts with an existing string buffer.
    137        *  @param  __str  A string to copy as a starting buffer.
    138        *  @param  __mode  Whether the buffer can read, or write, or both.
    139        *
    140        *  This constructor initializes the parent class using its
    141        *  own default ctor.
    142       */
    143       explicit
    144       basic_stringbuf(const __string_type& __str,
    145 		      ios_base::openmode __mode = ios_base::in | ios_base::out)
    146       : __streambuf_type(), _M_mode(),
    147 	_M_string(__str.data(), __str.size(), __str.get_allocator())
    148       { _M_stringbuf_init(__mode); }
    149 
    150 #if __cplusplus >= 201103L
    151       basic_stringbuf(const basic_stringbuf&) = delete;
    152 
    153       basic_stringbuf(basic_stringbuf&& __rhs)
    154       : basic_stringbuf(std::move(__rhs), __xfer_bufptrs(__rhs, this))
    155       { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); }
    156 
    157 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    158       explicit
    159       basic_stringbuf(const allocator_type& __a)
    160       : basic_stringbuf(ios_base::in | std::ios_base::out, __a)
    161       { }
    162 
    163       basic_stringbuf(ios_base::openmode __mode,
    164 		      const allocator_type& __a)
    165       : __streambuf_type(), _M_mode(__mode), _M_string(__a)
    166       { }
    167 
    168       explicit
    169       basic_stringbuf(__string_type&& __s,
    170 		      ios_base::openmode __mode = ios_base::in
    171 						  | ios_base::out)
    172       : __streambuf_type(), _M_mode(__mode), _M_string(std::move(__s))
    173       { _M_stringbuf_init(__mode); }
    174 
    175       template<typename _SAlloc>
    176 	basic_stringbuf(const basic_string<_CharT, _Traits, _SAlloc>& __s,
    177 			const allocator_type& __a)
    178 	: basic_stringbuf(__s, ios_base::in | std::ios_base::out, __a)
    179 	{ }
    180 
    181       template<typename _SAlloc>
    182 	basic_stringbuf(const basic_string<_CharT, _Traits, _SAlloc>& __s,
    183 			ios_base::openmode __mode,
    184 			const allocator_type& __a)
    185 	: __streambuf_type(), _M_mode(__mode),
    186 	  _M_string(__s.data(), __s.size(), __a)
    187 	{ _M_stringbuf_init(__mode); }
    188 
    189       template<typename _SAlloc>
    190 	explicit
    191 	basic_stringbuf(const basic_string<_CharT, _Traits, _SAlloc>& __s,
    192 			ios_base::openmode __mode = ios_base::in
    193 						    | ios_base::out)
    194 	: basic_stringbuf(__s, __mode, allocator_type{})
    195 	{ }
    196 
    197       basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a)
    198       : basic_stringbuf(std::move(__rhs), __a, __xfer_bufptrs(__rhs, this))
    199       { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); }
    200 
    201       allocator_type get_allocator() const noexcept
    202       { return _M_string.get_allocator(); }
    203 #endif // C++20
    204 
    205       // 27.8.2.2 Assign and swap:
    206 
    207       basic_stringbuf&
    208       operator=(const basic_stringbuf&) = delete;
    209 
    210       basic_stringbuf&
    211       operator=(basic_stringbuf&& __rhs)
    212       {
    213 	__xfer_bufptrs __st{__rhs, this};
    214 	const __streambuf_type& __base = __rhs;
    215 	__streambuf_type::operator=(__base);
    216 	this->pubimbue(__rhs.getloc());
    217 	_M_mode = __rhs._M_mode;
    218 	_M_string = std::move(__rhs._M_string);
    219 	__rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0);
    220 	return *this;
    221       }
    222 
    223       void
    224       swap(basic_stringbuf& __rhs) noexcept(_Noexcept_swap::value)
    225       {
    226 	__xfer_bufptrs __l_st{*this, std::__addressof(__rhs)};
    227 	__xfer_bufptrs __r_st{__rhs, this};
    228 	__streambuf_type& __base = __rhs;
    229 	__streambuf_type::swap(__base);
    230 	__rhs.pubimbue(this->pubimbue(__rhs.getloc()));
    231 	std::swap(_M_mode, __rhs._M_mode);
    232 	std::swap(_M_string, __rhs._M_string); // XXX not exception safe
    233       }
    234 #endif // C++11
    235 
    236       // Getters and setters:
    237 
    238       /**
    239        *  @brief  Copying out the string buffer.
    240        *  @return  A copy of one of the underlying sequences.
    241        *
    242        *  <em>If the buffer is only created in input mode, the underlying
    243        *  character sequence is equal to the input sequence; otherwise, it
    244        *  is equal to the output sequence.</em> [27.7.1.2]/1
    245       */
    246       __string_type
    247       str() const _GLIBCXX_LVAL_REF_QUAL
    248       {
    249 	__string_type __ret(_M_string.get_allocator());
    250 	if (char_type* __hi = _M_high_mark())
    251 	  __ret.assign(this->pbase(), __hi);
    252 	else
    253 	  __ret = _M_string;
    254 	return __ret;
    255       }
    256 
    257 #if __cplusplus > 201703L
    258 #if _GLIBCXX_USE_CXX11_ABI
    259 #if __cpp_concepts
    260       template<__allocator_like _SAlloc>
    261 	basic_string<_CharT, _Traits, _SAlloc>
    262 	str(const _SAlloc& __sa) const
    263 	{
    264 	  auto __sv = view();
    265 	  return { __sv.data(), __sv.size(), __sa };
    266 	}
    267 #endif
    268 
    269       __string_type
    270       str() &&
    271       {
    272 	if (char_type* __hi = _M_high_mark())
    273 	  {
    274 	    // Set length to end of character sequence and add null terminator.
    275 	    _M_string._M_set_length(_M_high_mark() - this->pbase());
    276 	  }
    277 	auto __str = std::move(_M_string);
    278 	_M_string.clear();
    279 	_M_sync(_M_string.data(), 0, 0);
    280 	return __str;
    281       }
    282 #endif // cxx11 ABI
    283 
    284       _GLIBCXX_SSTREAM_ALWAYS_INLINE
    285       basic_string_view<char_type, traits_type>
    286       view() const noexcept
    287       {
    288 	if (char_type* __hi = _M_high_mark())
    289 	  return { this->pbase(), __hi };
    290 	else
    291 	  return _M_string;
    292       }
    293 #endif // C++20
    294 
    295       /**
    296        *  @brief  Setting a new buffer.
    297        *  @param  __s  The string to use as a new sequence.
    298        *
    299        *  Deallocates any previous stored sequence, then copies @a s to
    300        *  use as a new one.
    301       */
    302       void
    303       str(const __string_type& __s)
    304       {
    305 	// Cannot use _M_string = __s, since v3 strings are COW
    306 	// (not always true now but assign() always works).
    307 	_M_string.assign(__s.data(), __s.size());
    308 	_M_stringbuf_init(_M_mode);
    309       }
    310 
    311 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    312 #if __cpp_concepts
    313       template<__allocator_like _SAlloc>
    314 	requires (!is_same_v<_SAlloc, _Alloc>)
    315 	void
    316 	str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
    317 	{
    318 	  _M_string.assign(__s.data(), __s.size());
    319 	  _M_stringbuf_init(_M_mode);
    320 	}
    321 #endif
    322 
    323       void
    324       str(__string_type&& __s)
    325       {
    326 	_M_string = std::move(__s);
    327 	_M_stringbuf_init(_M_mode);
    328       }
    329 #endif
    330 
    331     protected:
    332       // Common initialization code goes here.
    333       void
    334       _M_stringbuf_init(ios_base::openmode __mode)
    335       {
    336 	_M_mode = __mode;
    337 	__size_type __len = 0;
    338 	if (_M_mode & (ios_base::ate | ios_base::app))
    339 	  __len = _M_string.size();
    340 	_M_sync(const_cast<char_type*>(_M_string.data()), 0, __len);
    341       }
    342 
    343       virtual streamsize
    344       showmanyc()
    345       {
    346 	streamsize __ret = -1;
    347 	if (_M_mode & ios_base::in)
    348 	  {
    349 	    _M_update_egptr();
    350 	    __ret = this->egptr() - this->gptr();
    351 	  }
    352 	return __ret;
    353       }
    354 
    355       virtual int_type
    356       underflow();
    357 
    358       virtual int_type
    359       pbackfail(int_type __c = traits_type::eof());
    360 
    361       virtual int_type
    362       overflow(int_type __c = traits_type::eof());
    363 
    364       /**
    365        *  @brief  Manipulates the buffer.
    366        *  @param  __s  Pointer to a buffer area.
    367        *  @param  __n  Size of @a __s.
    368        *  @return  @c this
    369        *
    370        *  If no buffer has already been created, and both @a __s and @a __n are
    371        *  non-zero, then @c __s is used as a buffer; see
    372        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering
    373        *  for more.
    374       */
    375       virtual __streambuf_type*
    376       setbuf(char_type* __s, streamsize __n)
    377       {
    378 	if (__s && __n >= 0)
    379 	  {
    380 	    // This is implementation-defined behavior, and assumes
    381 	    // that an external char_type array of length __n exists
    382 	    // and has been pre-allocated. If this is not the case,
    383 	    // things will quickly blow up.
    384 
    385 	    // Step 1: Destroy the current internal array.
    386 	    _M_string.clear();
    387 
    388 	    // Step 2: Use the external array.
    389 	    _M_sync(__s, __n, 0);
    390 	  }
    391 	return this;
    392       }
    393 
    394       virtual pos_type
    395       seekoff(off_type __off, ios_base::seekdir __way,
    396 	      ios_base::openmode __mode = ios_base::in | ios_base::out);
    397 
    398       virtual pos_type
    399       seekpos(pos_type __sp,
    400 	      ios_base::openmode __mode = ios_base::in | ios_base::out);
    401 
    402       // Internal function for correctly updating the internal buffer
    403       // for a particular _M_string, due to initialization or re-sizing
    404       // of an existing _M_string.
    405       void
    406       _M_sync(char_type* __base, __size_type __i, __size_type __o);
    407 
    408       // Internal function for correctly updating egptr() to the actual
    409       // string end.
    410       void
    411       _M_update_egptr()
    412       {
    413 	if (char_type* __pptr = this->pptr())
    414 	  {
    415 	    char_type* __egptr = this->egptr();
    416 	    if (!__egptr || __pptr > __egptr)
    417 	      {
    418 		if (_M_mode & ios_base::in)
    419 		  this->setg(this->eback(), this->gptr(), __pptr);
    420 		else
    421 		  this->setg(__pptr, __pptr, __pptr);
    422 	      }
    423 	  }
    424       }
    425 
    426       // Works around the issue with pbump, part of the protected
    427       // interface of basic_streambuf, taking just an int.
    428       void
    429       _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off);
    430 
    431     private:
    432       // Return a pointer to the end of the underlying character sequence.
    433       // This might not be the same character as _M_string.end() because
    434       // basic_stringbuf::overflow might have written to unused capacity
    435       // in _M_string without updating its length.
    436       __attribute__((__always_inline__))
    437       char_type*
    438       _M_high_mark() const _GLIBCXX_NOEXCEPT
    439       {
    440 	if (char_type* __pptr = this->pptr())
    441 	  {
    442 	    char_type* __egptr = this->egptr();
    443 	    if (!__egptr || __pptr > __egptr)
    444 	      return __pptr;  // Underlying sequence is [pbase, pptr).
    445 	    else
    446 	      return __egptr; // Underlying sequence is [pbase, egptr).
    447 	  }
    448 	return 0; // Underlying character sequence is just _M_string.
    449       }
    450 
    451 #if __cplusplus >= 201103L
    452 #if _GLIBCXX_USE_CXX11_ABI
    453       // This type captures the state of the gptr / pptr pointers as offsets
    454       // so they can be restored in another object after moving the string.
    455       struct __xfer_bufptrs
    456       {
    457 	__xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to)
    458 	: _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1}
    459 	{
    460 	  const _CharT* const __str = __from._M_string.data();
    461 	  const _CharT* __end = nullptr;
    462 	  if (__from.eback())
    463 	    {
    464 	      _M_goff[0] = __from.eback() - __str;
    465 	      _M_goff[1] = __from.gptr() - __str;
    466 	      _M_goff[2] = __from.egptr() - __str;
    467 	      __end = __from.egptr();
    468 	    }
    469 	  if (__from.pbase())
    470 	    {
    471 	      _M_poff[0] = __from.pbase() - __str;
    472 	      _M_poff[1] = __from.pptr() - __from.pbase();
    473 	      _M_poff[2] = __from.epptr() - __str;
    474 	      if (!__end || __from.pptr() > __end)
    475 		__end = __from.pptr();
    476 	    }
    477 
    478 	  // Set _M_string length to the greater of the get and put areas.
    479 	  if (__end)
    480 	    {
    481 	      // The const_cast avoids changing this constructor's signature,
    482 	      // because it is exported from the dynamic library.
    483 	      auto& __mut_from = const_cast<basic_stringbuf&>(__from);
    484 	      __mut_from._M_string._M_length(__end - __str);
    485 	    }
    486 	}
    487 
    488 	~__xfer_bufptrs()
    489 	{
    490 	  char_type* __str = const_cast<char_type*>(_M_to->_M_string.data());
    491 	  if (_M_goff[0] != -1)
    492 	    _M_to->setg(__str+_M_goff[0], __str+_M_goff[1], __str+_M_goff[2]);
    493 	  if (_M_poff[0] != -1)
    494 	    _M_to->_M_pbump(__str+_M_poff[0], __str+_M_poff[2], _M_poff[1]);
    495 	}
    496 
    497 	basic_stringbuf* _M_to;
    498 	off_type _M_goff[3];
    499 	off_type _M_poff[3];
    500       };
    501 #else
    502       // This type does nothing when using Copy-On-Write strings.
    503       struct __xfer_bufptrs
    504       {
    505 	__xfer_bufptrs(const basic_stringbuf&, basic_stringbuf*) { }
    506       };
    507 #endif
    508 
    509       // The move constructor initializes an __xfer_bufptrs temporary then
    510       // delegates to this constructor to performs moves during its lifetime.
    511       basic_stringbuf(basic_stringbuf&& __rhs, __xfer_bufptrs&&)
    512       : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)),
    513       _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string))
    514       { }
    515 
    516 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    517       // The move constructor initializes an __xfer_bufptrs temporary then
    518       // delegates to this constructor to performs moves during its lifetime.
    519       basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a,
    520 		      __xfer_bufptrs&&)
    521       : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)),
    522       _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string), __a)
    523       { }
    524 #endif
    525 #endif // C++11
    526     };
    527 
    528 
    529   // [27.7.2] Template class basic_istringstream
    530   /**
    531    *  @brief  Controlling input for std::string.
    532    *  @ingroup io
    533    *
    534    *  @tparam _CharT  Type of character stream.
    535    *  @tparam _Traits  Traits for character type, defaults to
    536    *                   char_traits<_CharT>.
    537    *  @tparam _Alloc  Allocator type, defaults to allocator<_CharT>.
    538    *
    539    *  This class supports reading from objects of type std::basic_string,
    540    *  using the inherited functions from std::basic_istream.  To control
    541    *  the associated sequence, an instance of std::basic_stringbuf is used,
    542    *  which this page refers to as @c sb.
    543   */
    544   template<typename _CharT, typename _Traits, typename _Alloc>
    545     class basic_istringstream : public basic_istream<_CharT, _Traits>
    546     {
    547     public:
    548       // Types:
    549       typedef _CharT 					char_type;
    550       typedef _Traits 					traits_type;
    551       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    552       // 251. basic_stringbuf missing allocator_type
    553       typedef _Alloc				       	allocator_type;
    554       typedef typename traits_type::int_type 		int_type;
    555       typedef typename traits_type::pos_type 		pos_type;
    556       typedef typename traits_type::off_type 		off_type;
    557 
    558       // Non-standard types:
    559       typedef basic_string<_CharT, _Traits, _Alloc> 	__string_type;
    560       typedef basic_stringbuf<_CharT, _Traits, _Alloc> 	__stringbuf_type;
    561       typedef basic_istream<char_type, traits_type>	__istream_type;
    562 
    563     private:
    564       __stringbuf_type	_M_stringbuf;
    565 
    566     public:
    567       // Constructors:
    568 
    569       /**
    570        *  @brief  Default constructor starts with an empty string buffer.
    571        *
    572        *  Initializes @c sb using @c in, and passes @c &sb to the base
    573        *  class initializer.  Does not allocate any buffer.
    574        *
    575        *  That's a lie.  We initialize the base class with NULL, because the
    576        *  string class does its own memory management.
    577       */
    578       basic_istringstream()
    579       : __istream_type(), _M_stringbuf(ios_base::in)
    580       { this->init(&_M_stringbuf); }
    581 
    582       /**
    583        *  @brief  Starts with an empty string buffer.
    584        *  @param  __mode  Whether the buffer can read, or write, or both.
    585        *
    586        *  @c ios_base::in is automatically included in @a __mode.
    587        *
    588        *  Initializes @c sb using @c __mode|in, and passes @c &sb to the base
    589        *  class initializer.  Does not allocate any buffer.
    590        *
    591        *  That's a lie.  We initialize the base class with NULL, because the
    592        *  string class does its own memory management.
    593       */
    594       explicit
    595       basic_istringstream(ios_base::openmode __mode)
    596       : __istream_type(), _M_stringbuf(__mode | ios_base::in)
    597       { this->init(&_M_stringbuf); }
    598 
    599       /**
    600        *  @brief  Starts with an existing string buffer.
    601        *  @param  __str  A string to copy as a starting buffer.
    602        *  @param  __mode  Whether the buffer can read, or write, or both.
    603        *
    604        *  @c ios_base::in is automatically included in @a mode.
    605        *
    606        *  Initializes @c sb using @a str and @c mode|in, and passes @c &sb
    607        *  to the base class initializer.
    608        *
    609        *  That's a lie.  We initialize the base class with NULL, because the
    610        *  string class does its own memory management.
    611       */
    612       explicit
    613       basic_istringstream(const __string_type& __str,
    614 			  ios_base::openmode __mode = ios_base::in)
    615       : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in)
    616       { this->init(&_M_stringbuf); }
    617 
    618       /**
    619        *  @brief  The destructor does nothing.
    620        *
    621        *  The buffer is deallocated by the stringbuf object, not the
    622        *  formatting stream.
    623       */
    624       ~basic_istringstream()
    625       { }
    626 
    627 #if __cplusplus >= 201103L
    628       basic_istringstream(const basic_istringstream&) = delete;
    629 
    630       basic_istringstream(basic_istringstream&& __rhs)
    631       : __istream_type(std::move(__rhs)),
    632       _M_stringbuf(std::move(__rhs._M_stringbuf))
    633       { __istream_type::set_rdbuf(&_M_stringbuf); }
    634 
    635 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    636       basic_istringstream(ios_base::openmode __mode, const allocator_type& __a)
    637       : __istream_type(), _M_stringbuf(__mode | ios_base::in, __a)
    638       { this->init(std::__addressof(_M_stringbuf)); }
    639 
    640       explicit
    641       basic_istringstream(__string_type&& __str,
    642 			  ios_base::openmode __mode = ios_base::in)
    643       : __istream_type(), _M_stringbuf(std::move(__str), __mode | ios_base::in)
    644       { this->init(std::__addressof(_M_stringbuf)); }
    645 
    646       template<typename _SAlloc>
    647 	basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
    648 			    const allocator_type& __a)
    649 	: basic_istringstream(__str, ios_base::in, __a)
    650 	{ }
    651 
    652       template<typename _SAlloc>
    653 	basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
    654 			    ios_base::openmode __mode,
    655 			    const allocator_type& __a)
    656 	: __istream_type(), _M_stringbuf(__str, __mode | ios_base::in, __a)
    657 	{ this->init(std::__addressof(_M_stringbuf)); }
    658 
    659       template<typename _SAlloc>
    660 	explicit
    661 	basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
    662 			    ios_base::openmode __mode = ios_base::in)
    663 	: basic_istringstream(__str, __mode, allocator_type())
    664 	{ }
    665 #endif // C++20
    666 
    667       // 27.8.3.2 Assign and swap:
    668 
    669       basic_istringstream&
    670       operator=(const basic_istringstream&) = delete;
    671 
    672       basic_istringstream&
    673       operator=(basic_istringstream&& __rhs)
    674       {
    675 	__istream_type::operator=(std::move(__rhs));
    676 	_M_stringbuf = std::move(__rhs._M_stringbuf);
    677 	return *this;
    678       }
    679 
    680       void
    681       swap(basic_istringstream& __rhs)
    682       {
    683 	__istream_type::swap(__rhs);
    684 	_M_stringbuf.swap(__rhs._M_stringbuf);
    685       }
    686 #endif // C++11
    687 
    688       // Members:
    689       /**
    690        *  @brief  Accessing the underlying buffer.
    691        *  @return  The current basic_stringbuf buffer.
    692        *
    693        *  This hides both signatures of std::basic_ios::rdbuf().
    694       */
    695       __stringbuf_type*
    696       rdbuf() const
    697       { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
    698 
    699       /**
    700        *  @brief  Copying out the string buffer.
    701        *  @return  @c rdbuf()->str()
    702       */
    703       __string_type
    704       str() const _GLIBCXX_LVAL_REF_QUAL
    705       { return _M_stringbuf.str(); }
    706 
    707 #if __cplusplus > 201703L
    708 #if _GLIBCXX_USE_CXX11_ABI
    709 #if __cpp_concepts
    710       template<__allocator_like _SAlloc>
    711 	basic_string<_CharT, _Traits, _SAlloc>
    712 	str(const _SAlloc& __sa) const
    713 	{ return _M_stringbuf.str(__sa); }
    714 #endif
    715 
    716       __string_type
    717       str() &&
    718       { return std::move(_M_stringbuf).str(); }
    719 #endif // cxx11 ABI
    720 
    721       _GLIBCXX_SSTREAM_ALWAYS_INLINE
    722       basic_string_view<char_type, traits_type>
    723       view() const noexcept
    724       { return _M_stringbuf.view(); }
    725 #endif // C++20
    726 
    727       /**
    728        *  @brief  Setting a new buffer.
    729        *  @param  __s  The string to use as a new sequence.
    730        *
    731        *  Calls @c rdbuf()->str(s).
    732       */
    733       void
    734       str(const __string_type& __s)
    735       { _M_stringbuf.str(__s); }
    736 
    737 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    738 #if __cpp_concepts
    739       template<__allocator_like _SAlloc>
    740 	requires (!is_same_v<_SAlloc, _Alloc>)
    741 	void
    742 	str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
    743 	{ _M_stringbuf.str(__s); }
    744 #endif
    745 
    746       void
    747       str(__string_type&& __s)
    748       { _M_stringbuf.str(std::move(__s)); }
    749 #endif
    750     };
    751 
    752 
    753   // [27.7.3] Template class basic_ostringstream
    754   /**
    755    *  @brief  Controlling output for std::string.
    756    *  @ingroup io
    757    *
    758    *  @tparam _CharT  Type of character stream.
    759    *  @tparam _Traits  Traits for character type, defaults to
    760    *                   char_traits<_CharT>.
    761    *  @tparam _Alloc  Allocator type, defaults to allocator<_CharT>.
    762    *
    763    *  This class supports writing to objects of type std::basic_string,
    764    *  using the inherited functions from std::basic_ostream.  To control
    765    *  the associated sequence, an instance of std::basic_stringbuf is used,
    766    *  which this page refers to as @c sb.
    767   */
    768   template <typename _CharT, typename _Traits, typename _Alloc>
    769     class basic_ostringstream : public basic_ostream<_CharT, _Traits>
    770     {
    771     public:
    772       // Types:
    773       typedef _CharT 					char_type;
    774       typedef _Traits 					traits_type;
    775       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    776       // 251. basic_stringbuf missing allocator_type
    777       typedef _Alloc				       	allocator_type;
    778       typedef typename traits_type::int_type 		int_type;
    779       typedef typename traits_type::pos_type 		pos_type;
    780       typedef typename traits_type::off_type 		off_type;
    781 
    782       // Non-standard types:
    783       typedef basic_string<_CharT, _Traits, _Alloc> 	__string_type;
    784       typedef basic_stringbuf<_CharT, _Traits, _Alloc> 	__stringbuf_type;
    785       typedef basic_ostream<char_type, traits_type>	__ostream_type;
    786 
    787     private:
    788       __stringbuf_type	_M_stringbuf;
    789 
    790     public:
    791       // Constructors/destructor:
    792 
    793       /**
    794        *  @brief  Default constructor starts with an empty string buffer.
    795        *
    796        *  Initializes @c sb using @c mode|out, and passes @c &sb to the base
    797        *  class initializer.  Does not allocate any buffer.
    798        *
    799        *  That's a lie.  We initialize the base class with NULL, because the
    800        *  string class does its own memory management.
    801       */
    802       basic_ostringstream()
    803       : __ostream_type(), _M_stringbuf(ios_base::out)
    804       { this->init(&_M_stringbuf); }
    805 
    806       /**
    807        *  @brief  Starts with an empty string buffer.
    808        *  @param  __mode  Whether the buffer can read, or write, or both.
    809        *
    810        *  @c ios_base::out is automatically included in @a mode.
    811        *
    812        *  Initializes @c sb using @c mode|out, and passes @c &sb to the base
    813        *  class initializer.  Does not allocate any buffer.
    814        *
    815        *  That's a lie.  We initialize the base class with NULL, because the
    816        *  string class does its own memory management.
    817       */
    818       explicit
    819       basic_ostringstream(ios_base::openmode __mode)
    820       : __ostream_type(), _M_stringbuf(__mode | ios_base::out)
    821       { this->init(&_M_stringbuf); }
    822 
    823       /**
    824        *  @brief  Starts with an existing string buffer.
    825        *  @param  __str  A string to copy as a starting buffer.
    826        *  @param  __mode  Whether the buffer can read, or write, or both.
    827        *
    828        *  @c ios_base::out is automatically included in @a mode.
    829        *
    830        *  Initializes @c sb using @a str and @c mode|out, and passes @c &sb
    831        *  to the base class initializer.
    832        *
    833        *  That's a lie.  We initialize the base class with NULL, because the
    834        *  string class does its own memory management.
    835       */
    836       explicit
    837       basic_ostringstream(const __string_type& __str,
    838 			  ios_base::openmode __mode = ios_base::out)
    839       : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out)
    840       { this->init(&_M_stringbuf); }
    841 
    842       /**
    843        *  @brief  The destructor does nothing.
    844        *
    845        *  The buffer is deallocated by the stringbuf object, not the
    846        *  formatting stream.
    847       */
    848       ~basic_ostringstream()
    849       { }
    850 
    851 #if __cplusplus >= 201103L
    852       basic_ostringstream(const basic_ostringstream&) = delete;
    853 
    854       basic_ostringstream(basic_ostringstream&& __rhs)
    855       : __ostream_type(std::move(__rhs)),
    856       _M_stringbuf(std::move(__rhs._M_stringbuf))
    857       { __ostream_type::set_rdbuf(&_M_stringbuf); }
    858 
    859 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    860       basic_ostringstream(ios_base::openmode __mode, const allocator_type& __a)
    861       : __ostream_type(), _M_stringbuf(__mode | ios_base::out, __a)
    862       { this->init(std::__addressof(_M_stringbuf)); }
    863 
    864       explicit
    865       basic_ostringstream(__string_type&& __str,
    866 			  ios_base::openmode __mode = ios_base::out)
    867       : __ostream_type(), _M_stringbuf(std::move(__str), __mode | ios_base::out)
    868       { this->init(std::__addressof(_M_stringbuf)); }
    869 
    870       template<typename _SAlloc>
    871 	basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
    872 			    const allocator_type& __a)
    873 	: basic_ostringstream(__str, ios_base::out, __a)
    874 	{ }
    875 
    876       template<typename _SAlloc>
    877 	basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
    878 			    ios_base::openmode __mode,
    879 			    const allocator_type& __a)
    880 	: __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out, __a)
    881 	{ this->init(std::__addressof(_M_stringbuf)); }
    882 
    883       template<typename _SAlloc>
    884 	explicit
    885 	basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
    886 			    ios_base::openmode __mode = ios_base::out)
    887 	: basic_ostringstream(__str, __mode, allocator_type())
    888 	{ }
    889 #endif // C++20
    890 
    891       // 27.8.3.2 Assign and swap:
    892 
    893       basic_ostringstream&
    894       operator=(const basic_ostringstream&) = delete;
    895 
    896       basic_ostringstream&
    897       operator=(basic_ostringstream&& __rhs)
    898       {
    899 	__ostream_type::operator=(std::move(__rhs));
    900 	_M_stringbuf = std::move(__rhs._M_stringbuf);
    901 	return *this;
    902       }
    903 
    904       void
    905       swap(basic_ostringstream& __rhs)
    906       {
    907 	__ostream_type::swap(__rhs);
    908 	_M_stringbuf.swap(__rhs._M_stringbuf);
    909       }
    910 #endif // C++11
    911 
    912       // Members:
    913       /**
    914        *  @brief  Accessing the underlying buffer.
    915        *  @return  The current basic_stringbuf buffer.
    916        *
    917        *  This hides both signatures of std::basic_ios::rdbuf().
    918       */
    919       __stringbuf_type*
    920       rdbuf() const
    921       { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
    922 
    923       /**
    924        *  @brief  Copying out the string buffer.
    925        *  @return  @c rdbuf()->str()
    926       */
    927       __string_type
    928       str() const _GLIBCXX_LVAL_REF_QUAL
    929       { return _M_stringbuf.str(); }
    930 
    931 #if __cplusplus > 201703L
    932 #if _GLIBCXX_USE_CXX11_ABI
    933 #if __cpp_concepts
    934       template<__allocator_like _SAlloc>
    935 	basic_string<_CharT, _Traits, _SAlloc>
    936 	str(const _SAlloc& __sa) const
    937 	{ return _M_stringbuf.str(__sa); }
    938 #endif
    939 
    940       __string_type
    941       str() &&
    942       { return std::move(_M_stringbuf).str(); }
    943 #endif // cxx11 ABI
    944 
    945       _GLIBCXX_SSTREAM_ALWAYS_INLINE
    946       basic_string_view<char_type, traits_type>
    947       view() const noexcept
    948       { return _M_stringbuf.view(); }
    949 #endif // C++20
    950 
    951       /**
    952        *  @brief  Setting a new buffer.
    953        *  @param  __s  The string to use as a new sequence.
    954        *
    955        *  Calls @c rdbuf()->str(s).
    956       */
    957       void
    958       str(const __string_type& __s)
    959       { _M_stringbuf.str(__s); }
    960 
    961 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
    962 #if __cpp_concepts
    963       template<__allocator_like _SAlloc>
    964 	requires (!is_same_v<_SAlloc, _Alloc>)
    965 	void
    966 	str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
    967 	{ _M_stringbuf.str(__s); }
    968 #endif
    969 
    970       void
    971       str(__string_type&& __s)
    972       { _M_stringbuf.str(std::move(__s)); }
    973 #endif
    974     };
    975 
    976 
    977   // [27.7.4] Template class basic_stringstream
    978   /**
    979    *  @brief  Controlling input and output for std::string.
    980    *  @ingroup io
    981    *
    982    *  @tparam _CharT  Type of character stream.
    983    *  @tparam _Traits  Traits for character type, defaults to
    984    *                   char_traits<_CharT>.
    985    *  @tparam _Alloc  Allocator type, defaults to allocator<_CharT>.
    986    *
    987    *  This class supports reading from and writing to objects of type
    988    *  std::basic_string, using the inherited functions from
    989    *  std::basic_iostream.  To control the associated sequence, an instance
    990    *  of std::basic_stringbuf is used, which this page refers to as @c sb.
    991   */
    992   template <typename _CharT, typename _Traits, typename _Alloc>
    993     class basic_stringstream : public basic_iostream<_CharT, _Traits>
    994     {
    995     public:
    996       // Types:
    997       typedef _CharT 					char_type;
    998       typedef _Traits 					traits_type;
    999       // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1000       // 251. basic_stringbuf missing allocator_type
   1001       typedef _Alloc				       	allocator_type;
   1002       typedef typename traits_type::int_type 		int_type;
   1003       typedef typename traits_type::pos_type 		pos_type;
   1004       typedef typename traits_type::off_type 		off_type;
   1005 
   1006       // Non-standard Types:
   1007       typedef basic_string<_CharT, _Traits, _Alloc> 	__string_type;
   1008       typedef basic_stringbuf<_CharT, _Traits, _Alloc> 	__stringbuf_type;
   1009       typedef basic_iostream<char_type, traits_type>	__iostream_type;
   1010 
   1011     private:
   1012       __stringbuf_type	_M_stringbuf;
   1013 
   1014     public:
   1015       // Constructors/destructors
   1016 
   1017       /**
   1018        *  @brief  Default constructor starts with an empty string buffer.
   1019        *
   1020        *  Initializes @c sb using the mode @c in|out, and passes @c &sb
   1021        *  to the base class initializer.  Does not allocate any buffer.
   1022        *
   1023        *  That's a lie.  We initialize the base class with NULL, because the
   1024        *  string class does its own memory management.
   1025       */
   1026       basic_stringstream()
   1027       : __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in)
   1028       { this->init(&_M_stringbuf); }
   1029 
   1030       /**
   1031        *  @brief  Starts with an empty string buffer.
   1032        *  @param  __m  Whether the buffer can read, or write, or both.
   1033        *
   1034        *  Initializes @c sb using the mode from @c __m, and passes @c &sb
   1035        *  to the base class initializer.  Does not allocate any buffer.
   1036        *
   1037        *  That's a lie.  We initialize the base class with NULL, because the
   1038        *  string class does its own memory management.
   1039       */
   1040       explicit
   1041       basic_stringstream(ios_base::openmode __m)
   1042       : __iostream_type(), _M_stringbuf(__m)
   1043       { this->init(&_M_stringbuf); }
   1044 
   1045       /**
   1046        *  @brief  Starts with an existing string buffer.
   1047        *  @param  __str  A string to copy as a starting buffer.
   1048        *  @param  __m  Whether the buffer can read, or write, or both.
   1049        *
   1050        *  Initializes @c sb using @a __str and @c __m, and passes @c &sb
   1051        *  to the base class initializer.
   1052        *
   1053        *  That's a lie.  We initialize the base class with NULL, because the
   1054        *  string class does its own memory management.
   1055       */
   1056       explicit
   1057       basic_stringstream(const __string_type& __str,
   1058 			 ios_base::openmode __m = ios_base::out | ios_base::in)
   1059       : __iostream_type(), _M_stringbuf(__str, __m)
   1060       { this->init(&_M_stringbuf); }
   1061 
   1062       /**
   1063        *  @brief  The destructor does nothing.
   1064        *
   1065        *  The buffer is deallocated by the stringbuf object, not the
   1066        *  formatting stream.
   1067       */
   1068       ~basic_stringstream()
   1069       { }
   1070 
   1071 #if __cplusplus >= 201103L
   1072       basic_stringstream(const basic_stringstream&) = delete;
   1073 
   1074       basic_stringstream(basic_stringstream&& __rhs)
   1075       : __iostream_type(std::move(__rhs)),
   1076       _M_stringbuf(std::move(__rhs._M_stringbuf))
   1077       { __iostream_type::set_rdbuf(&_M_stringbuf); }
   1078 
   1079 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
   1080       basic_stringstream(ios_base::openmode __mode, const allocator_type& __a)
   1081       : __iostream_type(), _M_stringbuf(__mode, __a)
   1082       { this->init(&_M_stringbuf); }
   1083 
   1084       explicit
   1085       basic_stringstream(__string_type&& __str,
   1086 			 ios_base::openmode __mode = ios_base::in
   1087 						     | ios_base::out)
   1088       : __iostream_type(), _M_stringbuf(std::move(__str), __mode)
   1089       { this->init(std::__addressof(_M_stringbuf)); }
   1090 
   1091       template<typename _SAlloc>
   1092 	basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
   1093 			   const allocator_type& __a)
   1094 	: basic_stringstream(__str, ios_base::in | ios_base::out, __a)
   1095 	{ }
   1096 
   1097       template<typename _SAlloc>
   1098 	basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
   1099 			   ios_base::openmode __mode,
   1100 			   const allocator_type& __a)
   1101 	: __iostream_type(), _M_stringbuf(__str, __mode, __a)
   1102 	{ this->init(std::__addressof(_M_stringbuf)); }
   1103 
   1104       template<typename _SAlloc>
   1105 	explicit
   1106 	basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str,
   1107 			   ios_base::openmode __mode = ios_base::in
   1108 						       | ios_base::out)
   1109 	: basic_stringstream(__str, __mode, allocator_type())
   1110 	{ }
   1111 #endif // C++20
   1112 
   1113       // 27.8.3.2 Assign and swap:
   1114 
   1115       basic_stringstream&
   1116       operator=(const basic_stringstream&) = delete;
   1117 
   1118       basic_stringstream&
   1119       operator=(basic_stringstream&& __rhs)
   1120       {
   1121 	__iostream_type::operator=(std::move(__rhs));
   1122 	_M_stringbuf = std::move(__rhs._M_stringbuf);
   1123 	return *this;
   1124       }
   1125 
   1126       void
   1127       swap(basic_stringstream& __rhs)
   1128       {
   1129 	__iostream_type::swap(__rhs);
   1130 	_M_stringbuf.swap(__rhs._M_stringbuf);
   1131       }
   1132 #endif // C++11
   1133 
   1134       // Members:
   1135       /**
   1136        *  @brief  Accessing the underlying buffer.
   1137        *  @return  The current basic_stringbuf buffer.
   1138        *
   1139        *  This hides both signatures of std::basic_ios::rdbuf().
   1140       */
   1141       __stringbuf_type*
   1142       rdbuf() const
   1143       { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
   1144 
   1145       /**
   1146        *  @brief  Copying out the string buffer.
   1147        *  @return  @c rdbuf()->str()
   1148       */
   1149       __string_type
   1150       str() const _GLIBCXX_LVAL_REF_QUAL
   1151       { return _M_stringbuf.str(); }
   1152 
   1153 #if __cplusplus > 201703L
   1154 #if _GLIBCXX_USE_CXX11_ABI
   1155 #if __cpp_concepts
   1156       template<__allocator_like _SAlloc>
   1157 	basic_string<_CharT, _Traits, _SAlloc>
   1158 	str(const _SAlloc& __sa) const
   1159 	{ return _M_stringbuf.str(__sa); }
   1160 #endif
   1161 
   1162       __string_type
   1163       str() &&
   1164       { return std::move(_M_stringbuf).str(); }
   1165 #endif // cxx11 ABI
   1166 
   1167       _GLIBCXX_SSTREAM_ALWAYS_INLINE
   1168       basic_string_view<char_type, traits_type>
   1169       view() const noexcept
   1170       { return _M_stringbuf.view(); }
   1171 #endif // C++20
   1172 
   1173       /**
   1174        *  @brief  Setting a new buffer.
   1175        *  @param  __s  The string to use as a new sequence.
   1176        *
   1177        *  Calls @c rdbuf()->str(s).
   1178       */
   1179       void
   1180       str(const __string_type& __s)
   1181       { _M_stringbuf.str(__s); }
   1182 
   1183 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
   1184 #if __cpp_concepts
   1185       template<__allocator_like _SAlloc>
   1186 	requires (!is_same_v<_SAlloc, _Alloc>)
   1187 	void
   1188 	str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
   1189 	{ _M_stringbuf.str(__s); }
   1190 #endif
   1191 
   1192       void
   1193       str(__string_type&& __s)
   1194       { _M_stringbuf.str(std::move(__s)); }
   1195 #endif
   1196     };
   1197 
   1198 #if __cplusplus >= 201103L
   1199   /// Swap specialization for stringbufs.
   1200   template <class _CharT, class _Traits, class _Allocator>
   1201     inline void
   1202     swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x,
   1203 	 basic_stringbuf<_CharT, _Traits, _Allocator>& __y)
   1204     noexcept(noexcept(__x.swap(__y)))
   1205     { __x.swap(__y); }
   1206 
   1207   /// Swap specialization for istringstreams.
   1208   template <class _CharT, class _Traits, class _Allocator>
   1209     inline void
   1210     swap(basic_istringstream<_CharT, _Traits, _Allocator>& __x,
   1211 	 basic_istringstream<_CharT, _Traits, _Allocator>& __y)
   1212     { __x.swap(__y); }
   1213 
   1214   /// Swap specialization for ostringstreams.
   1215   template <class _CharT, class _Traits, class _Allocator>
   1216     inline void
   1217     swap(basic_ostringstream<_CharT, _Traits, _Allocator>& __x,
   1218 	 basic_ostringstream<_CharT, _Traits, _Allocator>& __y)
   1219     { __x.swap(__y); }
   1220 
   1221   /// Swap specialization for stringstreams.
   1222   template <class _CharT, class _Traits, class _Allocator>
   1223     inline void
   1224     swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x,
   1225 	 basic_stringstream<_CharT, _Traits, _Allocator>& __y)
   1226     { __x.swap(__y); }
   1227 #endif // C++11
   1228 
   1229 _GLIBCXX_END_NAMESPACE_CXX11
   1230 _GLIBCXX_END_NAMESPACE_VERSION
   1231 } // namespace
   1232 
   1233 #undef _GLIBCXX_SSTREAM_ALWAYS_INLINE
   1234 #undef _GLIBCXX_LVAL_REF_QUAL
   1235 
   1236 #include <bits/sstream.tcc>
   1237 
   1238 #endif /* _GLIBCXX_SSTREAM */
   1239