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