On Thu, 5 Jun 2025 at 07:39, Jonathan Wakely <jwakely....@gmail.com> wrote: > > There was no need to revert this, it wasn't breaking bootstrap, only causing > a handful of test failures. > > The new wchar_t tests just need the same { dg-do run { target c++26 } } > directives as the char tests. > > Dejagnu only looks for directives in the main file, not in included files.
Pre-approved to re-push it with the dg-do lines added to the wchar_t tests, assuming that a 'make check' (with the default options) works. > > > > On Thu, 5 Jun 2025, 04:23 Nathan Myers, <n...@cantrip.org> wrote: >> >> On 6/4/25 20:30, H.J. Lu wrote: >> > On Wed, Jun 4, 2025 at 8:02 PM Jonathan Wakely <jwak...@redhat.com> wrote: >> >> >> >> On Thu, 29 May 2025 at 20:30, Nathan Myers <n...@cantrip.org> wrote: >> >>> >> >>> Change in V4: >> >>> * Rename tests to string_view.cc >> >>> * Adapt tests to cons/wchar_t directories >> >>> * Define symbol __cpp_lib_sstream_from_string_view as 202406 >> >>> * Define symbol __glibcxx_want_sstream_from_string_view before >> >>> version.h >> >>> * Include version.h after other includes >> >>> * No include type_traits >> >>> * Drive-by comment moved to commit message >> >>> * Each `explicit` on its own line >> >>> * Run tests even when using old COW string >> >>> >> >>> Change in V3: >> >>> * Comment that p2495 specifies a drive-by constraint omitted as >> >>> redundant >> >>> * Adjust whitespace to fit in 80 columns >> >>> >> >>> Change in V2: >> >>> * Apply all review comments >> >>> * Remove redundant drive-by "requires" on ctor from string allocator >> >>> arg >> >>> * Check allocators are plumbed through >> >> >> >> Looks great now, thanks for iterating on it. >> >> >> >> Please push to trunk (you'll probably need to rebase first, which will >> >> have a merge conflict in bits/version.h but just regenerating it again >> >> will resolve that). >> > >> > On Fedora 42/x86-64, I got >> > >> > FAIL: 27_io/basic_istringstream/cons/wchar_t/string_view.cc >> > -std=gnu++17 (test for excess errors) >> > Excess errors: >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:39: >> > error: 'requires' only available with '-std=c++20' or '-fconcepts' >> > [-Wtemplate-body] >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:39: >> > error: expected ',' before '{' token [-Wtemplate-body] >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:39: >> > warning: 'static_assert' with non-string message only available with >> > '-std=c++2c' or '-std=gnu++2c' [-Wc++26-extensions] >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:39: >> > error: expected primary-expression before '{' token [-Wtemplate-body] >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:39: >> > error: expected ')' before '{' token [-Wtemplate-body] >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:41: >> > error: 'requires' only available with '-std=c++20' or '-fconcepts' >> > [-Wtemplate-body] >> > /export/gnu/import/git/gitlab/x86-gcc-test/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/../char/string_view.cc:41: >> > error: expected ',' before '{' token [-Wtemplate-body] >> >> Reverted a31e76a2643. >> >> >>> -- >8 -- >> >>> >> >>> Implement PR libstdc++/119741 (P2495R3). >> >>> Add constructors to stringbuf, stringstream, istringstream, and >> >>> ostringstream, >> >>> and a matching overload of str(sv) in each, that take anything >> >>> convertible to >> >>> a string_view in places where the existing ctors and function take a >> >>> string. >> >>> Note this change omits the constraint applied to the istringstream >> >>> constructor >> >>> from string cited as a "drive-by" in P2495R3, as we have determined it is >> >>> redundant. >> >>> >> >>> libstdc++-v3/ChangeLog: >> >>> >> >>> PR libstdc++/119741 >> >>> * include/std/sstream: full implementation, really just >> >>> decls, requires clause and plumbing. >> >>> * include/bits/version.def, include/bits/version.h: >> >>> new preprocessor symbol >> >>> __cpp_lib_sstream_from_string_view. >> >>> * testsuite/27_io/basic_stringbuf/cons/char/string_view.cc: >> >>> New tests. >> >>> * testsuite/27_io/basic_istringstream/cons/char/string_view.cc: >> >>> New tests. >> >>> * testsuite/27_io/basic_ostringstream/cons/char/string_view.cc: >> >>> New tests. >> >>> * testsuite/27_io/basic_stringstream/cons/char/string_view.cc: >> >>> New tests. >> >>> * testsuite/27_io/basic_stringbuf/cons/wchar_t/string_view.cc: >> >>> New tests. >> >>> * >> >>> testsuite/27_io/basic_istringstream/cons/wchar_t/string_view.cc: >> >>> New tests. >> >>> * >> >>> testsuite/27_io/basic_ostringstream/cons/wchar_t/string_view.cc: >> >>> New tests. >> >>> * >> >>> testsuite/27_io/basic_stringstream/cons/wchar_t/string_view.cc: >> >>> New tests. >> >>> --- >> >>> libstdc++-v3/include/bits/version.def | 11 +- >> >>> libstdc++-v3/include/bits/version.h | 10 + >> >>> libstdc++-v3/include/std/sstream | 198 +++++++++++++++-- >> >>> .../cons/char/string_view.cc | 195 +++++++++++++++++ >> >>> .../cons/wchar_t/string_view.cc | 3 + >> >>> .../cons/char/string_view.cc | 194 +++++++++++++++++ >> >>> .../cons/wchar_t/string_view.cc | 3 + >> >>> .../basic_stringbuf/cons/char/string_view.cc | 205 ++++++++++++++++++ >> >>> .../cons/wchar_t/string_view.cc | 3 + >> >>> .../cons/char/string_view.cc | 204 +++++++++++++++++ >> >>> .../cons/wchar_t/string_view.cc | 3 + >> >>> 11 files changed, 1010 insertions(+), 19 deletions(-) >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_istringstream/cons/char/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/char/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/wchar_t/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/char/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/wchar_t/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_stringstream/cons/char/string_view.cc >> >>> create mode 100644 >> >>> libstdc++-v3/testsuite/27_io/basic_stringstream/cons/wchar_t/string_view.cc >> >>> >> >>> diff --git a/libstdc++-v3/include/bits/version.def >> >>> b/libstdc++-v3/include/bits/version.def >> >>> index 282667eabda..53bf72d95c2 100644 >> >>> --- a/libstdc++-v3/include/bits/version.def >> >>> +++ b/libstdc++-v3/include/bits/version.def >> >>> @@ -649,7 +649,7 @@ ftms = { >> >>> }; >> >>> values = { >> >>> v = 1; >> >>> - /* For when there's no gthread. */ >> >>> + // For when there is no gthread. >> >>> cxxmin = 17; >> >>> hosted = yes; >> >>> gthread = no; >> >>> @@ -1945,6 +1945,15 @@ ftms = { >> >>> }; >> >>> }; >> >>> >> >>> +ftms = { >> >>> + name = sstream_from_string_view; >> >>> + values = { >> >>> + v = 202306; >> >>> + cxxmin = 26; >> >>> + hosted = yes; >> >>> + }; >> >>> +}; >> >>> + >> >>> // Standard test specifications. >> >>> stds[97] = ">= 199711L"; >> >>> stds[03] = ">= 199711L"; >> >>> diff --git a/libstdc++-v3/include/bits/version.h >> >>> b/libstdc++-v3/include/bits/version.h >> >>> index bb7c0479c72..0b932183e5b 100644 >> >>> --- a/libstdc++-v3/include/bits/version.h >> >>> +++ b/libstdc++-v3/include/bits/version.h >> >>> @@ -2174,4 +2174,14 @@ >> >>> #endif /* !defined(__cpp_lib_modules) && >> >>> defined(__glibcxx_want_modules) */ >> >>> #undef __glibcxx_want_modules >> >>> >> >>> +#if !defined(__cpp_lib_sstream_from_string_view) >> >>> +# if (__cplusplus >= 202306L) && _GLIBCXX_HOSTED >> >>> +# define __glibcxx_sstream_from_string_view 202306L >> >>> +# if defined(__glibcxx_want_all) || >> >>> defined(__glibcxx_want_sstream_from_string_view) >> >>> +# define __cpp_lib_sstream_from_string_view 202306L >> >>> +# endif >> >>> +# endif >> >>> +#endif /* !defined(__cpp_lib_sstream_from_string_view) && >> >>> defined(__glibcxx_want_sstream_from_string_view) */ >> >>> +#undef __glibcxx_want_sstream_from_string_view >> >>> + >> >>> #undef __glibcxx_want_all >> >>> diff --git a/libstdc++-v3/include/std/sstream >> >>> b/libstdc++-v3/include/std/sstream >> >>> index ad0c16a91e8..edef599bd6f 100644 >> >>> --- a/libstdc++-v3/include/std/sstream >> >>> +++ b/libstdc++-v3/include/std/sstream >> >>> @@ -41,8 +41,12 @@ >> >>> >> >>> #include <istream> >> >>> #include <ostream> >> >>> + >> >>> #include <bits/alloc_traits.h> // allocator_traits, __allocator_like >> >>> >> >>> +#define __glibcxx_want_sstream_from_string_view >> >>> +#include <bits/version.h> >> >>> + >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> # define _GLIBCXX_LVAL_REF_QUAL & >> >>> # define _GLIBCXX_SSTREAM_ALWAYS_INLINE >> >>> @@ -52,8 +56,6 @@ >> >>> # define _GLIBCXX_SSTREAM_ALWAYS_INLINE [[__gnu__::__always_inline__]] >> >>> #endif >> >>> >> >>> - >> >>> - >> >>> namespace std _GLIBCXX_VISIBILITY(default) >> >>> { >> >>> _GLIBCXX_BEGIN_NAMESPACE_VERSION >> >>> @@ -159,6 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), >> >>> 0, 0); } >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> + // P0408 Efficient access to basic_stringbuf buffer >> >>> explicit >> >>> basic_stringbuf(const allocator_type& __a) >> >>> : basic_stringbuf(ios_base::in | std::ios_base::out, __a) >> >>> @@ -197,7 +200,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> | ios_base::out) >> >>> : basic_stringbuf(__s, __mode, allocator_type{}) >> >>> { } >> >>> +#endif >> >>> + >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template<typename _Tp> >> >>> + explicit >> >>> + basic_stringbuf(const _Tp& __t, >> >>> + ios_base::openmode __mode = ios_base::in | ios_base::out) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_stringbuf(__t, __mode, allocator_type{}) >> >>> + { } >> >>> + >> >>> + template<typename _Tp> >> >>> + basic_stringbuf(const _Tp& __t, const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_stringbuf(__t, ios_base::in | ios_base::out, __a) >> >>> + { } >> >>> >> >>> + template<typename _Tp> >> >>> + basic_stringbuf(const _Tp& __t, ios_base::openmode __mode, >> >>> + const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : _M_string(__t, __a) >> >>> + { _M_stringbuf_init(__mode); } >> >>> +#endif // C++26 >> >>> + >> >>> +#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> + // P0408 Efficient access to basic_stringbuf buffer >> >>> basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& >> >>> __a) >> >>> : basic_stringbuf(std::move(__rhs), __a, __xfer_bufptrs(__rhs, >> >>> this)) >> >>> { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), >> >>> 0, 0); } >> >>> @@ -262,6 +294,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> #if __cplusplus > 201703L >> >>> #if _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> _GLIBCXX_NODISCARD >> >>> basic_string<_CharT, _Traits, _SAlloc> >> >>> @@ -317,6 +350,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> requires (!is_same_v<_SAlloc, _Alloc>) >> >>> void >> >>> @@ -335,6 +369,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> } >> >>> #endif >> >>> >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template <typename _Tp> >> >>> + void >> >>> + str(const _Tp& __t) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + { >> >>> + basic_string_view<_CharT, _Traits> __sv{__t}; >> >>> + _M_string = __sv; >> >>> + _M_stringbuf_init(_M_mode); >> >>> + } >> >>> +#endif // C++26 >> >>> + >> >>> protected: >> >>> // Common initialization code goes here. >> >>> void >> >>> @@ -521,6 +568,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> { } >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> + // P0408 Efficient access to basic_stringbuf buffer >> >>> + >> >>> // The move constructor initializes an __xfer_bufptrs temporary >> >>> then >> >>> // delegates to this constructor to performs moves during its >> >>> lifetime. >> >>> basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& >> >>> __a, >> >>> @@ -584,7 +633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> */ >> >>> basic_istringstream() >> >>> : __istream_type(), _M_stringbuf(ios_base::in) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Starts with an empty string buffer. >> >>> @@ -601,7 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> explicit >> >>> basic_istringstream(ios_base::openmode __mode) >> >>> : __istream_type(), _M_stringbuf(__mode | ios_base::in) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Starts with an existing string buffer. >> >>> @@ -620,7 +669,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> basic_istringstream(const __string_type& __str, >> >>> ios_base::openmode __mode = ios_base::in) >> >>> : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief The destructor does nothing. >> >>> @@ -637,9 +686,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> basic_istringstream(basic_istringstream&& __rhs) >> >>> : __istream_type(std::move(__rhs)), >> >>> _M_stringbuf(std::move(__rhs._M_stringbuf)) >> >>> - { __istream_type::set_rdbuf(&_M_stringbuf); } >> >>> + { __istream_type::set_rdbuf(std::__addressof(_M_stringbuf)); } >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> + // P0408 Efficient access to basic_stringbuf buffer >> >>> basic_istringstream(ios_base::openmode __mode, const >> >>> allocator_type& __a) >> >>> : __istream_type(), _M_stringbuf(__mode | ios_base::in, __a) >> >>> { this->init(std::__addressof(_M_stringbuf)); } >> >>> @@ -671,6 +721,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> { } >> >>> #endif // C++20 >> >>> >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template <typename _Tp> >> >>> + explicit >> >>> + basic_istringstream(const _Tp& __t, >> >>> + ios_base::openmode __mode = ios_base::in) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_istringstream(__t, __mode, allocator_type{}) >> >>> + { } >> >>> + >> >>> + template <typename _Tp> >> >>> + basic_istringstream(const _Tp& __t, const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_istringstream(__t, ios_base::in, __a) >> >>> + { } >> >>> + >> >>> + template <typename _Tp> >> >>> + basic_istringstream(const _Tp& __t, ios_base::openmode __mode, >> >>> + const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : __istream_type(), _M_stringbuf(__t, __mode | ios_base::in, >> >>> __a) >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> +#endif // C++26 >> >>> + >> >>> // 27.8.3.2 Assign and swap: >> >>> >> >>> basic_istringstream& >> >>> @@ -702,7 +778,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> _GLIBCXX_NODISCARD >> >>> __stringbuf_type* >> >>> rdbuf() const >> >>> - { return const_cast<__stringbuf_type*>(&_M_stringbuf); } >> >>> + { return >> >>> const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Copying out the string buffer. >> >>> @@ -716,6 +792,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> #if __cplusplus > 201703L >> >>> #if _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> _GLIBCXX_NODISCARD >> >>> basic_string<_CharT, _Traits, _SAlloc> >> >>> @@ -747,6 +824,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> requires (!is_same_v<_SAlloc, _Alloc>) >> >>> void >> >>> @@ -758,6 +836,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> str(__string_type&& __s) >> >>> { _M_stringbuf.str(std::move(__s)); } >> >>> #endif >> >>> + >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template<typename _Tp> >> >>> + void >> >>> + str(const _Tp& __t) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + { _M_stringbuf.str(__t); } >> >>> +#endif // C++26 >> >>> }; >> >>> >> >>> >> >>> @@ -812,7 +899,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> */ >> >>> basic_ostringstream() >> >>> : __ostream_type(), _M_stringbuf(ios_base::out) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Starts with an empty string buffer. >> >>> @@ -829,7 +916,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> explicit >> >>> basic_ostringstream(ios_base::openmode __mode) >> >>> : __ostream_type(), _M_stringbuf(__mode | ios_base::out) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Starts with an existing string buffer. >> >>> @@ -848,7 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> basic_ostringstream(const __string_type& __str, >> >>> ios_base::openmode __mode = ios_base::out) >> >>> : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief The destructor does nothing. >> >>> @@ -865,9 +952,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> basic_ostringstream(basic_ostringstream&& __rhs) >> >>> : __ostream_type(std::move(__rhs)), >> >>> _M_stringbuf(std::move(__rhs._M_stringbuf)) >> >>> - { __ostream_type::set_rdbuf(&_M_stringbuf); } >> >>> + { __ostream_type::set_rdbuf(std::__addressof(_M_stringbuf)); } >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> + // P0408 Efficient access to basic_stringbuf buffer >> >>> basic_ostringstream(ios_base::openmode __mode, const >> >>> allocator_type& __a) >> >>> : __ostream_type(), _M_stringbuf(__mode | ios_base::out, __a) >> >>> { this->init(std::__addressof(_M_stringbuf)); } >> >>> @@ -899,6 +987,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> { } >> >>> #endif // C++20 >> >>> >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template <typename _Tp> >> >>> + explicit >> >>> + basic_ostringstream( >> >>> + const _Tp& __t, ios_base::openmode __mode = ios_base::out) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_ostringstream(__t, __mode, allocator_type{}) >> >>> + { } >> >>> + >> >>> + template <typename _Tp> >> >>> + basic_ostringstream(const _Tp& __t, const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_ostringstream(__t, ios_base::out, __a) >> >>> + { } >> >>> + >> >>> + template <typename _Tp> >> >>> + basic_ostringstream(const _Tp& __t, ios_base::openmode __mode, >> >>> + const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : __ostream_type(), _M_stringbuf(__t, __mode | ios_base::out, >> >>> __a) >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> +#endif // C++26 >> >>> + >> >>> // 27.8.3.2 Assign and swap: >> >>> >> >>> basic_ostringstream& >> >>> @@ -930,7 +1044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> _GLIBCXX_NODISCARD >> >>> __stringbuf_type* >> >>> rdbuf() const >> >>> - { return const_cast<__stringbuf_type*>(&_M_stringbuf); } >> >>> + { return >> >>> const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Copying out the string buffer. >> >>> @@ -944,6 +1058,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> #if __cplusplus > 201703L >> >>> #if _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> _GLIBCXX_NODISCARD >> >>> basic_string<_CharT, _Traits, _SAlloc> >> >>> @@ -975,6 +1090,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> requires (!is_same_v<_SAlloc, _Alloc>) >> >>> void >> >>> @@ -986,6 +1102,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> str(__string_type&& __s) >> >>> { _M_stringbuf.str(std::move(__s)); } >> >>> #endif >> >>> + >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template<typename _Tp> >> >>> + void >> >>> + str(const _Tp& __t) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + { _M_stringbuf.str(__t); } >> >>> +#endif // C++26 >> >>> }; >> >>> >> >>> >> >>> @@ -1040,7 +1165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> */ >> >>> basic_stringstream() >> >>> : __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Starts with an empty string buffer. >> >>> @@ -1055,7 +1180,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> explicit >> >>> basic_stringstream(ios_base::openmode __m) >> >>> : __iostream_type(), _M_stringbuf(__m) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Starts with an existing string buffer. >> >>> @@ -1072,7 +1197,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> basic_stringstream(const __string_type& __str, >> >>> ios_base::openmode __m = ios_base::out | >> >>> ios_base::in) >> >>> : __iostream_type(), _M_stringbuf(__str, __m) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief The destructor does nothing. >> >>> @@ -1089,12 +1214,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> basic_stringstream(basic_stringstream&& __rhs) >> >>> : __iostream_type(std::move(__rhs)), >> >>> _M_stringbuf(std::move(__rhs._M_stringbuf)) >> >>> - { __iostream_type::set_rdbuf(&_M_stringbuf); } >> >>> + { __iostream_type::set_rdbuf(std::__addressof(_M_stringbuf)); } >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> + // P0408 Efficient access to basic_stringbuf buffer >> >>> basic_stringstream(ios_base::openmode __mode, const >> >>> allocator_type& __a) >> >>> : __iostream_type(), _M_stringbuf(__mode, __a) >> >>> - { this->init(&_M_stringbuf); } >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> >> >>> explicit >> >>> basic_stringstream(__string_type&& __str, >> >>> @@ -1125,6 +1251,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> { } >> >>> #endif // C++20 >> >>> >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template <typename _Tp> >> >>> + explicit >> >>> + basic_stringstream(const _Tp& __t, >> >>> + ios_base::openmode __mode = ios_base::in | ios_base::out) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_stringstream(__t, __mode, allocator_type{}) >> >>> + { } >> >>> + >> >>> + template <typename _Tp> >> >>> + basic_stringstream(const _Tp& __t, const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + : basic_stringstream(__t, ios_base::in | ios_base::out, __a) >> >>> + { } >> >>> + >> >>> + template <typename _Tp> >> >>> + basic_stringstream(const _Tp& __t, ios_base::openmode __mode, >> >>> + const allocator_type& __a) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> basic_string_view<_CharT, _Traits>>) >> >>> + : __iostream_type(), _M_stringbuf(__t, __mode, __a) >> >>> + { this->init(std::__addressof(_M_stringbuf)); } >> >>> +#endif // C++26 >> >>> + >> >>> // 27.8.3.2 Assign and swap: >> >>> >> >>> basic_stringstream& >> >>> @@ -1156,7 +1307,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> _GLIBCXX_NODISCARD >> >>> __stringbuf_type* >> >>> rdbuf() const >> >>> - { return const_cast<__stringbuf_type*>(&_M_stringbuf); } >> >>> + { return >> >>> const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); } >> >>> >> >>> /** >> >>> * @brief Copying out the string buffer. >> >>> @@ -1170,6 +1321,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> #if __cplusplus > 201703L >> >>> #if _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> _GLIBCXX_NODISCARD >> >>> basic_string<_CharT, _Traits, _SAlloc> >> >>> @@ -1201,6 +1353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> >> >>> #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI >> >>> #if __cpp_concepts >> >>> + // P0407 Allocator-aware basic_streambuf >> >>> template<__allocator_like _SAlloc> >> >>> requires (!is_same_v<_SAlloc, _Alloc>) >> >>> void >> >>> @@ -1212,6 +1365,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 >> >>> str(__string_type&& __s) >> >>> { _M_stringbuf.str(std::move(__s)); } >> >>> #endif >> >>> + >> >>> +#ifdef __cpp_lib_sstream_from_string_view >> >>> + template<typename _Tp> >> >>> + void >> >>> + str(const _Tp& __t) >> >>> + requires (is_convertible_v<const _Tp&, >> >>> + basic_string_view<_CharT, _Traits>>) >> >>> + { _M_stringbuf.str(__t); } >> >>> +#endif // C++26 >> >>> }; >> >>> >> >>> #if __cplusplus >= 201103L >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/char/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/char/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..27f65aa9437 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/char/string_view.cc >> >>> @@ -0,0 +1,195 @@ >> >>> +// C++26 [istringstream.general] >> >>> + >> >>> +// { dg-do run { target c++26 } } >> >>> + >> >>> +#include <sstream> >> >>> +#include <string> >> >>> +#include <string_view> >> >>> +#include <testsuite_allocator.h> >> >>> +#include <testsuite_hooks.h> >> >>> + >> >>> +// Check C++26 P2495 istringstream ctors and members str(s) that accept >> >>> a >> >>> +// string_view, or anything convertible to a string_view, in place of a >> >>> +// string object. Mostly just verify plumbing. >> >>> + >> >>> +#ifndef C >> >>> +# define C char >> >>> +# define L(a) a >> >>> +#endif >> >>> + >> >>> +using string = std::basic_string<C>; >> >>> +using string_view = std::basic_string_view<C>; >> >>> +using istringstream = std::basic_istringstream<C>; >> >>> + >> >>> +struct convertible_to_string_view { >> >>> + string s; >> >>> + operator string_view() const { return s; } >> >>> +}; >> >>> + >> >>> +const string str(L("This is a test string")); >> >>> +convertible_to_string_view cstr{str}; // a copy >> >>> +const convertible_to_string_view ccstr{str}; // another copy >> >>> + >> >>> +template <typename istringstream = std::basic_istringstream<C>> >> >>> +void >> >>> +test01() >> >>> +{ >> >>> + // Test C++26 constructor and str(s) taking a generalized string_view >> >>> + >> >>> + static_assert(! requires { istringstream(1); }, >> >>> + "istringstream ctor should reject what cannot be converted to a >> >>> string_view"); >> >>> + static_assert(! requires { istringstream().str(1); }, >> >>> + "istringstream::str(s) should reject what cannot be converted to >> >>> a string_view"); >> >>> + >> >>> + static_assert(!std::is_convertible_v<string_view, istringstream>, >> >>> + "istringstream(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<const string_view, >> >>> istringstream>, >> >>> + "istringstream(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<convertible_to_string_view, >> >>> istringstream>, >> >>> + "istringstream(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + static_assert(!std::is_convertible_v<const >> >>> convertible_to_string_view, istringstream>, >> >>> + "istringstream(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + >> >>> + { >> >>> + istringstream istr(cstr); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + } >> >>> + { >> >>> + istringstream istr(ccstr); >> >>> + VERIFY( istr.str() == ccstr.s ); >> >>> + VERIFY( istr.get() == ccstr.s[0] ); >> >>> + } >> >>> + { >> >>> + istringstream istr(cstr, std::ios_base::in); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') != 'X' ); >> >>> + } >> >>> + { >> >>> + istringstream istr(cstr, std::ios_base::out); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') == 'X' ); >> >>> + } >> >>> +} >> >>> + >> >>> +void >> >>> +test02() >> >>> +{ >> >>> + // Test various C++26 constructors taking string views >> >>> + // and mix of other arguments >> >>> + >> >>> + auto const mode = std::ios_base::in | std::ios_base::out; >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_istringstream(const T&, ios_base::openmode, const >> >>> allocator_type&) >> >>> + >> >>> + istringstream::allocator_type a; >> >>> + { >> >>> + istringstream istr(cstr, mode, a); // ={} checks for non-explicit >> >>> ctor >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + istringstream istr(cstr, std::ios::in, a); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') != 'X' ); >> >>> + } >> >>> + { >> >>> + istringstream istr(cstr, std::ios::out, a); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') == 'X' ); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_istringstream(const T&, ios_base::openmode) >> >>> + { >> >>> + istringstream istr(cstr, mode); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') == 'X' ); >> >>> + } >> >>> + { >> >>> + istringstream istr(cstr, std::ios::in); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') != 'X' ); >> >>> + } >> >>> + { >> >>> + istringstream istr(cstr, std::ios::out); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') == 'X' ); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // explicit >> >>> + // basic_istringstream(const T&, ios_base::openmode = ios_base::in) >> >>> + >> >>> + istringstream istr(cstr); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') != 'X' ); >> >>> + } >> >>> +} >> >>> + >> >>> +using alloc_type = __gnu_test::uneq_allocator<C>; >> >>> + >> >>> +template<typename Alloc, typename CC = typename Alloc::value_type> >> >>> + using istringstream_with_alloc >> >>> + = std::basic_istringstream<CC, std::char_traits<CC>, Alloc>; >> >>> + >> >>> +void test03() >> >>> +{ >> >>> + alloc_type a{1}; >> >>> + { >> >>> + istringstream_with_alloc<alloc_type> istr(cstr, a); >> >>> + VERIFY( istr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{istr.str()} == cstr ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + } >> >>> + { >> >>> + istringstream_with_alloc<alloc_type> istr(cstr, std::ios::in, a); >> >>> + VERIFY( istr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{istr.str()} == cstr ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') != 'X' ); >> >>> + } >> >>> + { >> >>> + istringstream_with_alloc<alloc_type> istr(cstr, std::ios::out, a); >> >>> + VERIFY( istr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{istr.str()} == cstr ); >> >>> + VERIFY( istr.get() == cstr.s[0] ); >> >>> + VERIFY( istr.rdbuf()->sputc('X') == 'X' ); >> >>> + } >> >>> +} >> >>> + >> >>> +void test04() >> >>> +{ >> >>> + { >> >>> + istringstream istr; >> >>> + istr.str( cstr ); >> >>> + VERIFY( istr.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + istringstream istr; >> >>> + istr.str( ccstr ); >> >>> + VERIFY( istr.str() == ccstr.s ); >> >>> + } >> >>> +} >> >>> + >> >>> +int >> >>> +main() >> >>> +{ >> >>> + test01(); >> >>> + test02(); >> >>> + test03(); >> >>> + test04(); >> >>> +} >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..cfb73c4c510 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_istringstream/cons/wchar_t/string_view.cc >> >>> @@ -0,0 +1,3 @@ >> >>> +#define C wchar_t >> >>> +#define L(a) L##a >> >>> +#include "../char/string_view.cc" >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/char/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/char/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..731e97e4aa2 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/char/string_view.cc >> >>> @@ -0,0 +1,194 @@ >> >>> +// C++26 [ostringstream.general] >> >>> + >> >>> +// { dg-do run { target c++26 } } >> >>> + >> >>> +#include <sstream> >> >>> +#include <string> >> >>> +#include <string_view> >> >>> +#include <testsuite_allocator.h> >> >>> +#include <testsuite_hooks.h> >> >>> + >> >>> +// Check C++26 P2495 ostringstream ctors and members str(s) that accept >> >>> a >> >>> +// string_view, or anything convertible to a string_view, in place of a >> >>> +// string object. Mostly just verify plumbing. >> >>> + >> >>> +#ifndef C >> >>> +# define C char >> >>> +# define L(a) a >> >>> +#endif >> >>> + >> >>> +using string = std::basic_string<C>; >> >>> +using string_view = std::basic_string_view<C>; >> >>> +using ostringstream = std::basic_ostringstream<C>; >> >>> + >> >>> +struct convertible_to_string_view { >> >>> + string s; >> >>> + operator string_view() const { return s; } >> >>> +}; >> >>> + >> >>> +const string str(L("This is a test string")); >> >>> +convertible_to_string_view cstr{str}; // a copy >> >>> +const convertible_to_string_view ccstr{str}; // another copy >> >>> + >> >>> +template <typename ostringstream = std::basic_ostringstream<C>> >> >>> +void >> >>> +test01() >> >>> +{ >> >>> + // Test C++26 constructor and str(s) taking a generalized string_view >> >>> + >> >>> + static_assert(! requires { ostringstream(1); }, >> >>> + "ostringstream ctor should reject what cannot be converted to a >> >>> string_view"); >> >>> + static_assert(! requires { ostringstream().str(1); }, >> >>> + "ostringstream::str(s) should reject what cannot be converted to >> >>> a string_view"); >> >>> + >> >>> + static_assert(!std::is_convertible_v<string_view, ostringstream>, >> >>> + "ostringstream(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<const string_view, >> >>> ostringstream>, >> >>> + "ostringstream(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<convertible_to_string_view, >> >>> ostringstream>, >> >>> + "ostringstream(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + static_assert(!std::is_convertible_v<const >> >>> convertible_to_string_view, ostringstream>, >> >>> + "ostringstream(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + >> >>> + { >> >>> + ostringstream ostrstr(cstr); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(ccstr); >> >>> + VERIFY( ostrstr.str() == ccstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(cstr, std::ios_base::in); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == cstr.s[0]); >> >>> + VERIFY( ostrstr.put('Y').rdstate() == ostrstr.goodbit ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(cstr, std::ios_base::out); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + VERIFY( ostrstr.put('Y').rdstate() == ostrstr.goodbit ); >> >>> + } >> >>> +} >> >>> + >> >>> +void >> >>> +test02() >> >>> +{ >> >>> + // Test plumbing of C++26 various constructors taking string views >> >>> + >> >>> + auto const mode = std::ios_base::in | std::ios_base::out; >> >>> + >> >>> + { >> >>> + ostringstream::allocator_type a; >> >>> + // template <typename T> >> >>> + // basic_ostringstream(const T&, ios_base::openmode, const >> >>> allocator_type&) >> >>> + { >> >>> + ostringstream ostrstr(cstr, mode, a); // ={} checks for >> >>> non-explicit ctor >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(cstr, std::ios::in, a); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == cstr.s[0]); >> >>> + VERIFY( ostrstr.put('Y').rdstate() == ostrstr.goodbit ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(cstr, std::ios::out, a); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + VERIFY( ostrstr.put('Y').rdstate() == ostrstr.goodbit ); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_ostringstream(const T&, ios_base::openmode) >> >>> + { >> >>> + ostringstream ostrstr(cstr, mode); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == cstr.s[0]); >> >>> + VERIFY( ostrstr.put('Y').good() ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(cstr, std::ios::in); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == cstr.s[0]); >> >>> + VERIFY( ostrstr.put('X').good() ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr(cstr, std::ios::out); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + VERIFY( ostrstr.put('Y').rdstate() == ostrstr.goodbit ); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // explicit >> >>> + // basic_ostringstream(const T&, ios_base::openmode = ios_base::out) >> >>> + >> >>> + ostringstream ostrstr(cstr); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + VERIFY( ostrstr.put('Y').good() ); >> >>> + } >> >>> +} >> >>> + >> >>> +using alloc_type = __gnu_test::uneq_allocator<C>; >> >>> + >> >>> +template<typename Alloc, typename CC = typename Alloc::value_type> >> >>> + using ostringstream_with_alloc >> >>> + = std::basic_ostringstream<CC, std::char_traits<CC>, Alloc>; >> >>> + >> >>> +void test03() >> >>> +{ >> >>> + alloc_type a{1}; >> >>> + { >> >>> + ostringstream_with_alloc<alloc_type> ostrstr(cstr, a); >> >>> + VERIFY( ostrstr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{ostrstr.str()} == cstr ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + VERIFY( ostrstr.put('X').good() ); >> >>> + } >> >>> + { >> >>> + ostringstream_with_alloc<alloc_type> ostrstr(cstr, std::ios::in, a); >> >>> + VERIFY( ostrstr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{ostrstr.str()} == cstr ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == cstr.s[0]); >> >>> + VERIFY( ostrstr.put('X').good() ); >> >>> + } >> >>> + { >> >>> + ostringstream_with_alloc<alloc_type> ostrstr(cstr, std::ios::out, >> >>> a); >> >>> + VERIFY( ostrstr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{ostrstr.str()} == cstr ); >> >>> + VERIFY( ostrstr.rdbuf()->sgetc() == >> >>> ostringstream::traits_type::eof() ); >> >>> + VERIFY( ostrstr.put('Y').rdstate() == ostrstr.goodbit ); >> >>> + } >> >>> +} >> >>> + >> >>> +void test04() >> >>> +{ >> >>> + { >> >>> + ostringstream ostrstr; >> >>> + ostrstr.str(cstr); >> >>> + VERIFY( ostrstr.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + ostringstream ostrstr; >> >>> + ostrstr.str(ccstr); >> >>> + VERIFY( ostrstr.str() == ccstr.s ); >> >>> + } >> >>> +} >> >>> + >> >>> +int >> >>> +main() >> >>> +{ >> >>> + test01(); >> >>> + test02(); >> >>> + test03(); >> >>> + test04(); >> >>> +} >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/wchar_t/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/wchar_t/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..cfb73c4c510 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_ostringstream/cons/wchar_t/string_view.cc >> >>> @@ -0,0 +1,3 @@ >> >>> +#define C wchar_t >> >>> +#define L(a) L##a >> >>> +#include "../char/string_view.cc" >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/char/string_view.cc >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/char/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..7843269c48f >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/char/string_view.cc >> >>> @@ -0,0 +1,205 @@ >> >>> +// C++26 31.8.2.1 [stringbuf.general] >> >>> + >> >>> +// { dg-do run { target c++26 } } >> >>> + >> >>> +#include <sstream> >> >>> +#include <string> >> >>> +#include <string_view> >> >>> +#include <testsuite_allocator.h> >> >>> +#include <testsuite_hooks.h> >> >>> + >> >>> +// Check C++26 P2495 stringbuf ctors and members str(s) that accept a >> >>> +// string_view, or anything convertible to a string_view, in place of a >> >>> +// string object. >> >>> + >> >>> +#ifndef C >> >>> +# define C char >> >>> +# define L(a) a >> >>> +#endif >> >>> + >> >>> +using string = std::basic_string<C>; >> >>> +using string_view = std::basic_string_view<C>; >> >>> +using stringbuf = std::basic_stringbuf<C>; >> >>> + >> >>> +struct convertible_to_string_view { >> >>> + string s; >> >>> + operator string_view() const { return s; } >> >>> +}; >> >>> + >> >>> +const string str(L("This is a test string")); >> >>> +convertible_to_string_view cstr{str}; // a copy >> >>> +const convertible_to_string_view ccstr{str}; // another copy >> >>> + >> >>> +template <typename stringbuf = std::basic_stringbuf<C>> >> >>> +void >> >>> +test01() >> >>> +{ >> >>> + // Test C++26 constructor and str(s) taking a generalized string_view >> >>> + >> >>> + static_assert(! requires { stringbuf(1); }, >> >>> + "stringbuf ctor should reject what cannot be converted to a >> >>> string_view"); >> >>> + static_assert(! requires { stringbuf().str(1); }, >> >>> + "stringbuf::str(s) should reject what cannot be converted to a >> >>> string_view"); >> >>> + >> >>> + static_assert(!std::is_convertible_v<string_view, stringbuf>, >> >>> + "stringbuf(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<const string_view, stringbuf>, >> >>> + "stringbuf(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<convertible_to_string_view, >> >>> stringbuf>, >> >>> + "stringbuf(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + static_assert( >> >>> + !std::is_convertible_v<const convertible_to_string_view, >> >>> stringbuf>, >> >>> + "stringbuf(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + >> >>> + { >> >>> + stringbuf sbuf(cstr); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(ccstr); >> >>> + VERIFY( sbuf.str() == ccstr.s ); >> >>> + VERIFY( sbuf.sgetc() == ccstr.s[0] ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(cstr, std::ios_base::in); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + VERIFY( sbuf.sputc('X') == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(ccstr, std::ios_base::in); >> >>> + VERIFY( sbuf.str() == ccstr.s ); >> >>> + VERIFY( sbuf.sgetc() == ccstr.s[0] ); >> >>> + VERIFY( sbuf.sputc('X') == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(cstr, std::ios_base::out); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sputc('Y') == 'Y' ); >> >>> + VERIFY( sbuf.sgetc() == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(ccstr, std::ios_base::out); >> >>> + VERIFY( sbuf.str() == ccstr.s ); >> >>> + VERIFY( sbuf.sputc('Y') == 'Y' ); >> >>> + VERIFY( sbuf.sgetc() == stringbuf::traits_type::eof() ); >> >>> + } >> >>> +} >> >>> + >> >>> +void >> >>> +test02() >> >>> +{ >> >>> + // Test C++26 constructors taking string views using different >> >>> allocators >> >>> + >> >>> + auto const mode = std::ios_base::in | std::ios_base::out; >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_stringbuf(const T&, ios_base::openmode, const >> >>> allocator_type&) >> >>> + >> >>> + stringbuf::allocator_type a; >> >>> + { >> >>> + stringbuf sbuf(cstr, mode, a); // ={} checks for non-explicit ctor >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(cstr, std::ios::in, a); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + VERIFY( sbuf.sputc('X') == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + >> >>> + { >> >>> + stringbuf sbuf(cstr, std::ios::out, a); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sputc('X') == 'X' ); >> >>> + VERIFY( sbuf.sgetc() == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_stringbuf(const T&, ios_base::openmode) >> >>> + { >> >>> + stringbuf sbuf(cstr, mode); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(cstr, std::ios::in); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + VERIFY( sbuf.sputc('X') == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf(cstr, std::ios::out); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sputc('X') == 'X' ); >> >>> + VERIFY( sbuf.sgetc() == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // explicit >> >>> + // basic_stringbuf(const T&, ios_base::openmode = >> >>> ios_base::in|ios_base::out) >> >>> + >> >>> + stringbuf sbuf(cstr); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + } >> >>> +} >> >>> + >> >>> +using alloc_type = __gnu_test::uneq_allocator<C>; >> >>> + >> >>> +template<typename Alloc, typename CC = typename Alloc::value_type> >> >>> + using stringbuf_with_alloc >> >>> + = std::basic_stringbuf<CC, std::char_traits<CC>, Alloc>; >> >>> + >> >>> +void test03() >> >>> +{ >> >>> + alloc_type a{1}; >> >>> + { >> >>> + stringbuf_with_alloc<alloc_type> sbuf(cstr, a); >> >>> + VERIFY( sbuf.get_allocator() == a ); >> >>> + VERIFY( string_view{sbuf.str()} == cstr ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + } >> >>> + { >> >>> + stringbuf_with_alloc<alloc_type> sbuf(cstr, std::ios::in, a); >> >>> + VERIFY( sbuf.get_allocator() == a ); >> >>> + VERIFY( string_view{sbuf.str()} == cstr ); >> >>> + VERIFY( sbuf.sgetc() == cstr.s[0] ); >> >>> + VERIFY( sbuf.sputc('X') == stringbuf::traits_type::eof() ); >> >>> + } >> >>> + { >> >>> + stringbuf_with_alloc<alloc_type> sbuf(cstr, std::ios::out, a); >> >>> + VERIFY( sbuf.get_allocator() == a ); >> >>> + VERIFY( string_view{sbuf.str()} == cstr ); >> >>> + VERIFY( sbuf.sputc('X') == 'X' ); >> >>> + VERIFY( sbuf.sgetc() == stringbuf::traits_type::eof() ); >> >>> + } >> >>> +} >> >>> + >> >>> +void test04() >> >>> +{ >> >>> + { >> >>> + stringbuf sbuf; >> >>> + sbuf.str(cstr); >> >>> + VERIFY( sbuf.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + stringbuf sbuf; >> >>> + sbuf.str(ccstr); >> >>> + VERIFY( sbuf.str() == ccstr.s ); >> >>> + } >> >>> +} >> >>> + >> >>> +int >> >>> +main() >> >>> +{ >> >>> + test01(); >> >>> + test02(); >> >>> + test03(); >> >>> + test04(); >> >>> +} >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/wchar_t/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/wchar_t/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..cfb73c4c510 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/wchar_t/string_view.cc >> >>> @@ -0,0 +1,3 @@ >> >>> +#define C wchar_t >> >>> +#define L(a) L##a >> >>> +#include "../char/string_view.cc" >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_stringstream/cons/char/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringstream/cons/char/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..72085230442 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringstream/cons/char/string_view.cc >> >>> @@ -0,0 +1,204 @@ >> >>> +// C++26 31.8.2.1 [stringstream.general] >> >>> + >> >>> +// { dg-do run { target c++26 } } >> >>> + >> >>> +#include <sstream> >> >>> +#include <string> >> >>> +#include <string_view> >> >>> +#include <testsuite_allocator.h> >> >>> +#include <testsuite_hooks.h> >> >>> + >> >>> +// Check C++26 P2495 stringstream ctors and members str(s) that accept a >> >>> +// string_view, or anything convertible to a string_view, in place of a >> >>> +// string object. Mostly just verify plumbing. >> >>> + >> >>> +#ifndef C >> >>> +# define C char >> >>> +# define L(a) a >> >>> +#endif >> >>> + >> >>> +using string = std::basic_string<C>; >> >>> +using string_view = std::basic_string_view<C>; >> >>> +using stringstream = std::basic_stringstream<C>; >> >>> + >> >>> +struct convertible_to_string_view { >> >>> + string s; >> >>> + operator string_view() const { return s; } >> >>> +}; >> >>> + >> >>> +const string str(L("This is a test string")); >> >>> +convertible_to_string_view cstr{str}; // a copy >> >>> +const convertible_to_string_view ccstr{str}; // another copy >> >>> + >> >>> +template <typename stringstream = std::basic_stringstream<C>> >> >>> +void >> >>> +test01() >> >>> +{ >> >>> + // Test C++26 constructor and str(s) taking a generalized string_view >> >>> + >> >>> + static_assert(! requires { stringstream(1); }, >> >>> + "stringstream ctor should reject what cannot be converted to a >> >>> string_view"); >> >>> + static_assert(! requires { stringstream().str(1); }, >> >>> + "stringstream::str(s) should reject what cannot be converted to a >> >>> string_view"); >> >>> + >> >>> + static_assert(!std::is_convertible_v<string_view, stringstream>, >> >>> + "stringstream(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<const string_view, stringstream>, >> >>> + "stringstream(string_view, ios::openmode) is explicit"); >> >>> + static_assert(!std::is_convertible_v<convertible_to_string_view, >> >>> stringstream>, >> >>> + "stringstream(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + static_assert(!std::is_convertible_v<const >> >>> convertible_to_string_view, stringstream>, >> >>> + "stringstream(convertible_to_string_view, ios::openmode) is >> >>> explicit"); >> >>> + >> >>> + { >> >>> + stringstream strstr(cstr); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(ccstr); >> >>> + VERIFY( strstr.str() == ccstr.s ); >> >>> + VERIFY( strstr.get() == ccstr.s[0] ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(cstr, std::ios_base::in); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + VERIFY( strstr.put('X').rdstate() == strstr.badbit ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(cstr, std::ios_base::out); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.put('Y').good() ); >> >>> + VERIFY( strstr.get() == stringstream::traits_type::eof()); >> >>> + } >> >>> +} >> >>> + >> >>> +void >> >>> +test02() >> >>> +{ >> >>> + // Test C++26 various constructors taking string views >> >>> + >> >>> + auto const mode = std::ios_base::in | std::ios_base::out; >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_stringstream(const T&, ios_base::openmode, const >> >>> allocator_type&) >> >>> + >> >>> + stringstream::allocator_type a; >> >>> + { >> >>> + stringstream strstr(cstr, mode, a); // ={} checks for >> >>> non-explicit ctor >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(cstr, std::ios::in, a); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + VERIFY( strstr.put('X').rdstate() == strstr.badbit ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(cstr, std::ios::out, a); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.put('X').good() ); >> >>> + VERIFY( strstr.get() == stringstream::traits_type::eof()); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // basic_stringstream(const T&, ios_base::openmode) >> >>> + >> >>> + { >> >>> + stringstream strstr(cstr, mode); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + VERIFY( strstr.put('X').good() ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(cstr, std::ios::in); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + VERIFY( strstr.put('X').rdstate() == strstr.badbit ); >> >>> + } >> >>> + { >> >>> + stringstream strstr(cstr, std::ios::out); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.put('X').good() ); >> >>> + VERIFY( strstr.get() == stringstream::traits_type::eof()); >> >>> + } >> >>> + } >> >>> + >> >>> + { >> >>> + // template <typename T> >> >>> + // explicit >> >>> + // basic_stringstream(const T&, ios_base::openmode = >> >>> ios_base::in|ios_base::out) >> >>> + >> >>> + stringstream strstr(cstr); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + VERIFY( strstr.put('X').good() ); >> >>> + } >> >>> +} >> >>> + >> >>> +// A minimal allocator with no default constructor >> >>> +template<typename T> >> >>> + struct NoDefaultCons : __gnu_test::SimpleAllocator<T> >> >>> + { >> >>> + using __gnu_test::SimpleAllocator<T>::SimpleAllocator; >> >>> + NoDefaultCons() = delete; >> >>> + NoDefaultCons(int) { } >> >>> + }; >> >>> + >> >>> +using alloc_type = __gnu_test::uneq_allocator<C>; >> >>> + >> >>> +template<typename Alloc, typename CC = typename Alloc::value_type> >> >>> + using stringstream_with_alloc >> >>> + = std::basic_stringstream<CC, std::char_traits<CC>, Alloc>; >> >>> + >> >>> +void test03() >> >>> +{ >> >>> + alloc_type a{1}; >> >>> + { >> >>> + stringstream_with_alloc<alloc_type> strstr(cstr, a); >> >>> + VERIFY( strstr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{strstr.str()} == cstr ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + } >> >>> + { >> >>> + stringstream_with_alloc<alloc_type> strstr(cstr, std::ios::in, a); >> >>> + VERIFY( strstr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{strstr.str()} == cstr ); >> >>> + VERIFY( strstr.get() == cstr.s[0] ); >> >>> + VERIFY( strstr.put('X').rdstate() == strstr.badbit ); >> >>> + } >> >>> + { >> >>> + stringstream_with_alloc<alloc_type> strstr(cstr, std::ios::out, a); >> >>> + VERIFY( strstr.rdbuf()->get_allocator() == a ); >> >>> + VERIFY( string_view{strstr.str()} == cstr ); >> >>> + VERIFY( strstr.put('X').good() ); >> >>> + VERIFY( strstr.get() == stringstream::traits_type::eof()); >> >>> + } >> >>> +} >> >>> + >> >>> +void test04() >> >>> +{ >> >>> + { >> >>> + stringstream strstr; >> >>> + strstr.str( cstr ); >> >>> + VERIFY( strstr.str() == cstr.s ); >> >>> + } >> >>> + { >> >>> + stringstream strstr; >> >>> + strstr.str( ccstr ); >> >>> + VERIFY( strstr.str() == ccstr.s ); >> >>> + } >> >>> +} >> >>> + >> >>> +int >> >>> +main() >> >>> +{ >> >>> + test01(); >> >>> + test02(); >> >>> + test03(); >> >>> + test04(); >> >>> +} >> >>> diff --git >> >>> a/libstdc++-v3/testsuite/27_io/basic_stringstream/cons/wchar_t/string_view.cc >> >>> >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringstream/cons/wchar_t/string_view.cc >> >>> new file mode 100644 >> >>> index 00000000000..cfb73c4c510 >> >>> --- /dev/null >> >>> +++ >> >>> b/libstdc++-v3/testsuite/27_io/basic_stringstream/cons/wchar_t/string_view.cc >> >>> @@ -0,0 +1,3 @@ >> >>> +#define C wchar_t >> >>> +#define L(a) L##a >> >>> +#include "../char/string_view.cc" >> >>> -- >> >>> 2.49.0 >> >>> >> >> >> > >> > >>