[libcxx-commits] [libcxx] 80f9458 - [libc++][sstream] P2495R3: Interfacing `stringstream`s with `string_view` (#80552)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Mar 4 22:49:53 PST 2024


Author: Hristo Hristov
Date: 2024-03-05T08:49:49+02:00
New Revision: 80f9458cf30d13eef21b09042ea590945c5e64db

URL: https://github.com/llvm/llvm-project/commit/80f9458cf30d13eef21b09042ea590945c5e64db
DIFF: https://github.com/llvm/llvm-project/commit/80f9458cf30d13eef21b09042ea590945c5e64db.diff

LOG: [libc++][sstream] P2495R3: Interfacing `stringstream`s with `string_view` (#80552)

Implements P2495R3 <https://wg21.link/P2495R3>
- https://eel.is/c++draft/version.syn#headerref:%3csstream%3e
- https://eel.is/c++draft/stringbuf
- https://eel.is/c++draft/stringbuf.general
- https://eel.is/c++draft/stringbuf.cons
- https://eel.is/c++draft/stringbuf.members
- https://eel.is/c++draft/istringstream
- https://eel.is/c++draft/istringstream.general
- https://eel.is/c++draft/istringstream.cons
- https://eel.is/c++draft/istringstream.members
- https://eel.is/c++draft/ostringstream
- https://eel.is/c++draft/ostringstream.general
- https://eel.is/c++draft/ostringstream.cons
- https://eel.is/c++draft/ostringstream.members
- https://eel.is/c++draft/stringstream
- https://eel.is/c++draft/stringstream.general
- https://eel.is/c++draft/stringstream.cons
- https://eel.is/c++draft/stringstream.members

References:
- https://eel.is/c++draft/string.streams

Added: 
    libcxx/test/std/input.output/string.streams/helper_concepts.h
    libcxx/test/std/input.output/string.streams/helper_string_macros.h
    libcxx/test/std/input.output/string.streams/helper_types.h
    libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.pass.cpp
    libcxx/test/std/input.output/string.streams/istringstream/istringstream.members/str.string_view.pass.cpp
    libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.pass.cpp
    libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string_view.pass.cpp
    libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.pass.cpp
    libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.members/str.string_view.pass.cpp
    libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.alloc.pass.cpp
    libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.pass.cpp
    libcxx/test/std/input.output/string.streams/stringstream/stringstream.members/str.string_view.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/docs/ReleaseNotes/19.rst
    libcxx/docs/Status/Cxx2cPapers.csv
    libcxx/include/sstream
    libcxx/include/version
    libcxx/test/libcxx/transitive_includes/cxx03.csv
    libcxx/test/libcxx/transitive_includes/cxx11.csv
    libcxx/test/libcxx/transitive_includes/cxx14.csv
    libcxx/test/libcxx/transitive_includes/cxx17.csv
    libcxx/test/libcxx/transitive_includes/cxx20.csv
    libcxx/test/libcxx/transitive_includes/cxx23.csv
    libcxx/test/libcxx/transitive_includes/cxx26.csv
    libcxx/test/std/language.support/support.limits/support.limits.general/sstream.version.compile.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 60e0aea9768b4f..b213f430aa5922 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -442,7 +442,7 @@ Status
     --------------------------------------------------- -----------------
     ``__cpp_lib_span_initializer_list``                 ``202311L``
     --------------------------------------------------- -----------------
-    ``__cpp_lib_sstream_from_string_view``              *unimplemented*
+    ``__cpp_lib_sstream_from_string_view``              ``202306L``
     --------------------------------------------------- -----------------
     ``__cpp_lib_submdspan``                             *unimplemented*
     --------------------------------------------------- -----------------

diff  --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 0d381df5f0442c..b068325b35c9bb 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -41,6 +41,7 @@ Implemented Papers
 - P2637R3 - Member ``visit``
 - P2652R2 - Disallow User Specialization of ``allocator_traits``
 - P2819R2 - Add ``tuple`` protocol to ``complex``
+- P2495R3 - Interfacing ``stringstream``s with ``string_view``
 - P2302R4 - ``std::ranges::contains``
 - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
 

diff  --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 1c895f79a4c0f1..febb0977255b41 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -6,7 +6,7 @@
 "`P2545R4 <https://wg21.link/P2545R4>`__","LWG","Read-Copy Update (RCU)","Varna June 2023","","",""
 "`P2530R3 <https://wg21.link/P2530R3>`__","LWG","Hazard Pointers for C++26","Varna June 2023","","",""
 "`P2538R1 <https://wg21.link/P2538R1>`__","LWG","ADL-proof ``std::projected``","Varna June 2023","|Complete|","18.0","|ranges|"
-"`P2495R3 <https://wg21.link/P2495R3>`__","LWG","Interfacing ``stringstreams`` with ``string_view``","Varna June 2023","","",""
+"`P2495R3 <https://wg21.link/P2495R3>`__","LWG","Interfacing ``stringstream``s with ``string_view``","Varna June 2023","|Complete|","19.0",""
 "`P2510R3 <https://wg21.link/P2510R3>`__","LWG","Formatting pointers","Varna June 2023","|Complete| [#note-P2510R3]_","17.0","|format|"
 "`P2198R7 <https://wg21.link/P2198R7>`__","LWG","Freestanding Feature-Test Macros and Implementation-Defined Extensions","Varna June 2023","","",""
 "`P2338R4 <https://wg21.link/P2338R4>`__","LWG","Freestanding Library: Character primitives and the C library","Varna June 2023","","",""

diff  --git a/libcxx/include/sstream b/libcxx/include/sstream
index 60bec52209d75e..5873deb8318ecf 100644
--- a/libcxx/include/sstream
+++ b/libcxx/include/sstream
@@ -48,6 +48,13 @@ public:
     template <class SAlloc>
     explicit basic_stringbuf(const basic_string<char_type, traits_type, SAlloc>& s,
                              ios_base::openmode which = ios_base::in | ios_base::out); // C++20
+    template<class T>
+      explicit basic_stringbuf(const T& t,
+                               ios_base::openmode which = ios_base::in | ios_base::out); // Since C++26
+    template<class T>
+      basic_stringbuf(const T& t, const Allocator& a);                                   // Since C++26
+    template<class T>
+      basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a);         // Since C++26
     basic_stringbuf(const basic_stringbuf&) = delete;
     basic_stringbuf(basic_stringbuf&& rhs);
     basic_stringbuf(basic_stringbuf&& rhs, const allocator_type& a);                   // C++20
@@ -69,6 +76,8 @@ public:
     template <class SAlloc>
     void str(const basic_string<char_type, traits_type, SAlloc>& s);                   // C++20
     void str(basic_string<char_type, traits_type, allocator_type>&& s);                // C++20
+    template<class T>
+      void str(const T& t);                                                            // Since C++26
 
 protected:
     // [stringbuf.virtuals] Overridden virtual functions:
@@ -121,6 +130,12 @@ public:
     template <class SAlloc>
     explicit basic_istringstream(const basic_string<char_type, traits_type, SAlloc>& s,
                                  ios_base::openmode which = ios_base::in);             // C++20
+    template<class T>
+      explicit basic_istringstream(const T& t, ios_base::openmode which = ios_base::in); // Since C++26
+    template<class T>
+      basic_istringstream(const T& t, const Allocator& a);                               // Since C++26
+    template<class T>
+      basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a);     // Since C++26
     basic_istringstream(const basic_istringstream&) = delete;
     basic_istringstream(basic_istringstream&& rhs);
 
@@ -141,6 +156,8 @@ public:
     template <class SAlloc>
     void str(const basic_string<char_type, traits_type, SAlloc>& s);                   // C++20
     void str(basic_string<char_type, traits_type, allocator_type>&& s);                // C++20
+    template<class T>
+      void str(const T& t);                                                            // Since C++26
 };
 
 template <class charT, class traits, class Allocator>
@@ -182,6 +199,12 @@ public:
     template <class SAlloc>
     explicit basic_ostringstream(const basic_string<char_type, traits_type, SAlloc>& s,
                                  ios_base::openmode which = ios_base::out);            // C++20
+    template<class T>
+      explicit basic_ostringstream(const T& t, ios_base::openmode which = ios_base::out); // Since C++26
+    template<class T>
+      basic_ostringstream(const T& t, const Allocator& a);                                // Since C++26
+    template<class T>
+      basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a);      // Since C++26
     basic_ostringstream(const basic_ostringstream&) = delete;                             
     basic_ostringstream(basic_ostringstream&& rhs);
 
@@ -202,6 +225,8 @@ public:
     template <class SAlloc>
     void str(const basic_string<char_type, traits_type, SAlloc>& s);                   // C++20
     void str(basic_string<char_type, traits_type, allocator_type>&& s);                // C++20
+    template<class T>
+      void str(const T& t);                                                            // Since C++26
 };
 
 template <class charT, class traits, class Allocator>
@@ -243,6 +268,13 @@ public:
     template <class SAlloc>
     explicit basic_stringstream(const basic_string<char_type, traits_type, SAlloc>& s,
                                 ios_base::openmode which = ios_base::out | ios_base::in); // C++20
+    template<class T>
+      explicit basic_stringstream(const T& t,
+                                  ios_base::openmode which = ios_base::out | ios_base::in); // Since C++26
+    template<class T>
+      basic_stringstream(const T& t, const Allocator& a);                                   // Since C++26
+    template<class T>
+      basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a);         // Since C++26
     basic_stringstream(const basic_stringstream&) = delete;
     basic_stringstream(basic_stringstream&& rhs);
 
@@ -263,6 +295,8 @@ public:
     template <class SAlloc>
     void str(const basic_string<char_type, traits_type, SAlloc>& s);                      // C++20
     void str(basic_string<char_type, traits_type, allocator_type>&& s);                   // C++20
+    template<class T>
+      void str(const T& t);                                                               // Since C++26
 };
 
 template <class charT, class traits, class Allocator>
@@ -281,10 +315,12 @@ typedef basic_stringstream<wchar_t> wstringstream;
 #include <__availability>
 #include <__config>
 #include <__fwd/sstream.h>
+#include <__type_traits/is_convertible.h>
 #include <__utility/swap.h>
 #include <istream>
 #include <ostream>
 #include <string>
+#include <string_view>
 #include <version>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -371,6 +407,30 @@ public:
   }
 #endif // _LIBCPP_STD_VER >= 20
 
+#if _LIBCPP_STD_VER >= 26
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI explicit basic_stringbuf(const _Tp& __t,
+                                                 ios_base::openmode __which = ios_base::in | ios_base::out)
+      : basic_stringbuf(__t, __which, _Allocator()) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_stringbuf(const _Tp& __t, const _Allocator& __a)
+      : basic_stringbuf(__t, ios_base::in | ios_base::out, __a) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_stringbuf(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a)
+      : __hm_(nullptr), __mode_(__which) {
+    basic_string_view<_CharT, _Traits> __sv = __t;
+    __str_                                  = string_type(__sv, __a);
+    __init_buf_ptrs();
+  }
+
+#endif //  _LIBCPP_STD_VER >= 26
+
   basic_stringbuf(const basic_stringbuf&) = delete;
   basic_stringbuf(basic_stringbuf&& __rhs) : __mode_(__rhs.__mode_) { __move_init(std::move(__rhs)); }
 
@@ -444,6 +504,18 @@ public:
   }
 #endif // _LIBCPP_STD_VER >= 20
 
+#if _LIBCPP_STD_VER >= 26
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) {
+    basic_string_view<_CharT, _Traits> __sv = __t;
+    __str_                                  = __sv;
+    __init_buf_ptrs();
+  }
+
+#endif //  _LIBCPP_STD_VER >= 26
+
 protected:
   // [stringbuf.virtuals] Overridden virtual functions:
   int_type underflow() override;
@@ -831,6 +903,25 @@ public:
       : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::in) {}
 #endif // _LIBCPP_STD_VER >= 20
 
+#if _LIBCPP_STD_VER >= 26
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI explicit basic_istringstream(const _Tp& __t, ios_base::openmode __which = ios_base::in)
+      : basic_istringstream(__t, __which, _Allocator()) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_istringstream(const _Tp& __t, const _Allocator& __a)
+      : basic_istringstream(__t, ios_base::in, __a) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_istringstream(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a)
+      : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__t, __which | ios_base::in, __a) {}
+
+#endif //  _LIBCPP_STD_VER >= 26
+
   basic_istringstream(const basic_istringstream&) = delete;
   _LIBCPP_HIDE_FROM_ABI basic_istringstream(basic_istringstream&& __rhs)
       : basic_istream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
@@ -882,6 +973,14 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); }
 #endif // _LIBCPP_STD_VER >= 20
+
+#if _LIBCPP_STD_VER >= 26
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) {
+    rdbuf()->str(__t);
+  }
+#endif //  _LIBCPP_STD_VER >= 26
 };
 
 template <class _CharT, class _Traits, class _Allocator>
@@ -940,6 +1039,25 @@ public:
       : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out) {}
 #endif // _LIBCPP_STD_VER >= 20
 
+#if _LIBCPP_STD_VER >= 26
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(const _Tp& __t, ios_base::openmode __which = ios_base::out)
+      : basic_ostringstream(__t, __which | ios_base::out, _Allocator()) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_ostringstream(const _Tp& __t, const _Allocator& __a)
+      : basic_ostringstream(__t, ios_base::out, __a) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_ostringstream(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a)
+      : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__t, __which | ios_base::out, __a) {}
+
+#endif //  _LIBCPP_STD_VER >= 26
+
   basic_ostringstream(const basic_ostringstream&) = delete;
   _LIBCPP_HIDE_FROM_ABI basic_ostringstream(basic_ostringstream&& __rhs)
       : basic_ostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
@@ -992,6 +1110,14 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); }
 #endif // _LIBCPP_STD_VER >= 20
+
+#if _LIBCPP_STD_VER >= 26
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) {
+    rdbuf()->str(__t);
+  }
+#endif //  _LIBCPP_STD_VER >= 26
 };
 
 template <class _CharT, class _Traits, class _Allocator>
@@ -1053,6 +1179,26 @@ public:
       : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch) {}
 #endif // _LIBCPP_STD_VER >= 20
 
+#if _LIBCPP_STD_VER >= 26
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI explicit basic_stringstream(const _Tp& __t,
+                                                    ios_base::openmode __which = ios_base::out | ios_base::in)
+      : basic_stringstream(__t, __which, _Allocator()) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_stringstream(const _Tp& __t, const _Allocator& __a)
+      : basic_stringstream(__t, ios_base::out | ios_base::in, __a) {}
+
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI basic_stringstream(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a)
+      : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__t, __which, __a) {}
+
+#endif //  _LIBCPP_STD_VER >= 26
+
   basic_stringstream(const basic_stringstream&) = delete;
   _LIBCPP_HIDE_FROM_ABI basic_stringstream(basic_stringstream&& __rhs)
       : basic_iostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
@@ -1104,6 +1250,14 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); }
 #endif // _LIBCPP_STD_VER >= 20
+
+#if _LIBCPP_STD_VER >= 26
+  template <class _Tp>
+    requires is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>
+  _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) {
+    rdbuf()->str(__t);
+  }
+#endif //  _LIBCPP_STD_VER >= 26
 };
 
 template <class _CharT, class _Traits, class _Allocator>

diff  --git a/libcxx/include/version b/libcxx/include/version
index 055d0f30f9c438..3bd296e34aa4e3 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -515,7 +515,7 @@ __cpp_lib_within_lifetime                               202306L <type_traits>
 // # define __cpp_lib_smart_ptr_owner_equality             202306L
 # define __cpp_lib_span_at                              202311L
 # define __cpp_lib_span_initializer_list                202311L
-// # define __cpp_lib_sstream_from_string_view             202306L
+# define __cpp_lib_sstream_from_string_view             202306L
 // # define __cpp_lib_submdspan                            202306L
 // # define __cpp_lib_text_encoding                        202306L
 # undef  __cpp_lib_to_chars

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index 0acc48c80eb7af..678a986e522aa0 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -745,6 +745,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream type_traits
 sstream version
 stack compare

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index d2acb1356d13d2..c3875fa2cfc06f 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -751,6 +751,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream type_traits
 sstream version
 stack compare

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index ccba63f44cb2b6..e28e0cd44fed95 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -753,6 +753,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream type_traits
 sstream version
 stack compare

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index ccba63f44cb2b6..e28e0cd44fed95 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -753,6 +753,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream type_traits
 sstream version
 stack compare

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index aa9239bda21f6b..eec71f4fc6282e 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -758,6 +758,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream type_traits
 sstream version
 stack compare

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index ce11a358fc3e27..64ff9261820a96 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -519,6 +519,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream version
 stack compare
 stack cstddef

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index ce11a358fc3e27..64ff9261820a96 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -519,6 +519,7 @@ sstream cstddef
 sstream istream
 sstream ostream
 sstream string
+sstream string_view
 sstream version
 stack compare
 stack cstddef

diff  --git a/libcxx/test/std/input.output/string.streams/helper_concepts.h b/libcxx/test/std/input.output/string.streams/helper_concepts.h
new file mode 100644
index 00000000000000..18f6e5474164c5
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/helper_concepts.h
@@ -0,0 +1,17 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_CONCEPTS_H
+#define TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_CONCEPTS_H
+
+template <typename S, typename T>
+concept is_valid_argument_for_str_member = requires(S s, const T& sv) {
+  { s.str(sv) };
+};
+
+#endif // TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_CONCEPTS_H

diff  --git a/libcxx/test/std/input.output/string.streams/helper_string_macros.h b/libcxx/test/std/input.output/string.streams/helper_string_macros.h
new file mode 100644
index 00000000000000..4a7d22daa788cb
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/helper_string_macros.h
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_MACROS_H
+#define TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_MACROS_H
+
+#include "make_string.h"
+
+#define CS(S) MAKE_CSTRING(CharT, S)
+#define ST(S, a) std::basic_string<CharT, TraitsT, AllocT>(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a)
+#define SV(S) std::basic_string_view<CharT, TraitsT>(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S))
+
+#endif // TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_MACROS_H

diff  --git a/libcxx/test/std/input.output/string.streams/helper_types.h b/libcxx/test/std/input.output/string.streams/helper_types.h
new file mode 100644
index 00000000000000..8bd830d0fbda3b
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/helper_types.h
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_TYPES_H
+#define TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_TYPES_H
+
+#include <string_view>
+#include <concepts>
+
+#include "test_macros.h"
+
+template <typename CharT, class Traits = std::char_traits<CharT>>
+class ConstConvertibleStringView {
+public:
+  explicit ConstConvertibleStringView(const CharT* cs) : cs_{cs} {}
+
+  operator std::basic_string_view<CharT, Traits>() = delete;
+  operator std::basic_string_view<CharT, Traits>() const { return std::basic_string_view<CharT, Traits>(cs_); }
+
+private:
+  const CharT* cs_;
+};
+
+static_assert(!std::constructible_from<std::basic_string_view<char>, ConstConvertibleStringView<char>>);
+static_assert(!std::convertible_to<ConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+static_assert(std::constructible_from<std::basic_string_view<char>, const ConstConvertibleStringView<char>>);
+static_assert(std::convertible_to<const ConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, ConstConvertibleStringView<wchar_t>>);
+static_assert(!std::convertible_to<ConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+
+static_assert(std::constructible_from<std::basic_string_view<wchar_t>, const ConstConvertibleStringView<wchar_t>>);
+static_assert(std::convertible_to<const ConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+#endif
+
+template <typename CharT, class Traits = std::char_traits<CharT>>
+class NonConstConvertibleStringView {
+public:
+  explicit NonConstConvertibleStringView(const CharT* cs) : cs_{cs} {}
+
+  operator std::basic_string_view<CharT, Traits>() { return std::basic_string_view<CharT, Traits>(cs_); }
+  operator std::basic_string_view<CharT, Traits>() const = delete;
+
+private:
+  const CharT* cs_;
+};
+
+static_assert(std::constructible_from<std::basic_string_view<char>, NonConstConvertibleStringView<char>>);
+static_assert(std::convertible_to<NonConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+static_assert(!std::constructible_from<std::basic_string_view<char>, const NonConstConvertibleStringView<char>>);
+static_assert(!std::convertible_to<const NonConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(std::constructible_from<std::basic_string_view<wchar_t>, NonConstConvertibleStringView<wchar_t>>);
+static_assert(std::convertible_to<NonConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+
+static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, const NonConstConvertibleStringView<wchar_t>>);
+static_assert(!std::convertible_to<const NonConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+#endif
+
+struct SomeObject {};
+
+struct NonMode {};
+
+struct NonAllocator {};
+
+#endif // TEST_STD_INPUTOUTPUT_STRINGSTREAMS_HELPER_TYPES_H

diff  --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.alloc.pass.cpp
new file mode 100644
index 00000000000000..f087aa3d9119db
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.alloc.pass.cpp
@@ -0,0 +1,145 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_istringstream
+
+// template<class T>
+//   basic_istringstream(const T& t, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrStream = std::basic_istringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrStream, nasty_char*, const AllocT>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrStream, const nasty_char*, const AllocT>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, const AllocT>);
+  static_assert(test_convertible<StrStream, CharT*, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, const AllocT>);
+  static_assert(test_convertible<StrStream, const CharT*, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, std::basic_string_view<CharT, TraitsT>, const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, const AllocT>);
+  static_assert(!test_convertible<StrStream, const SomeObject, const AllocT>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.alloc.pass.cpp
new file mode 100644
index 00000000000000..35309bdb038985
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.alloc.pass.cpp
@@ -0,0 +1,189 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_istringstream
+
+// template<class T>
+//   basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrStream = std::basic_istringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(test_convertible<NStrStream, nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(
+      test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, AllocT>);
+  static_assert(test_convertible<StrStream, CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, AllocT>);
+  static_assert(test_convertible<StrStream, const CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrStream,
+                                        const std::basic_string_view<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrStream,
+                                 const std::basic_string_view<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream,
+                                        const std::basic_string<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(
+      test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrStream,
+                                        const ConstConvertibleStringView<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrStream,
+                                 const ConstConvertibleStringView<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrStream,
+                                         NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrStream,
+                                  NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream,
+                                         const NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrStream,
+                                  const NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream, const int, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrStream, const int, std::ios_base::openmode, const AllocT>());
+
+  // Non-mode
+  static_assert(
+      !std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>);
+  static_assert(
+      !test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrStream,
+                                         const std::basic_string_view<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const NonAllocator>);
+  static_assert(!test_convertible<StrStream,
+                                  const std::basic_string_view<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.pass.cpp
new file mode 100644
index 00000000000000..b54972f423f219
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string_view.mode.pass.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_istringstream
+
+// template<class T>
+//   explicit basic_istringstream(const T& t, ios_base::openmode which);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  //  nasty_char*
+  using NStrStream = std::basic_istringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, nasty_char*, std::ios_base::openmode>());
+
+  // const nasty_char*
+  using NStrStream = std::basic_istringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, CharT*, std::ios_base::openmode>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const CharT*, std::ios_base::openmode>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(
+      std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(
+      std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(
+      !std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  static_assert(
+      !std::
+          constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode>());
+
+  // Non-mode
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.members/str.string_view.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.members/str.string_view.pass.cpp
new file mode 100644
index 00000000000000..0b8b5fdd93c294
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.members/str.string_view.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_istringstream
+
+// template<class T>
+//   void str(const T& t);
+
+#include <cassert>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#include "../../helper_concepts.h"
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  using NStrStream = std::basic_istringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<NStrStream, nasty_char*>);
+  static_assert(is_valid_argument_for_str_member<NStrStream, const nasty_char*>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_istringstream<CharT, TraitsT, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<StrStream, CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrStream, const CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrStream, std::basic_string_view<CharT, TraitsT>>);
+  static_assert(is_valid_argument_for_str_member<StrStream, std::basic_string<CharT, TraitsT, AllocT>>);
+  static_assert(is_valid_argument_for_str_member<StrStream, ConstConvertibleStringView<CharT, TraitsT>>);
+
+  static_assert(!is_valid_argument_for_str_member<StrStream, CharT>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, int>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, SomeObject>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, std::nullptr_t>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, NonConstConvertibleStringView<CharT, TraitsT>>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  AllocT allocator;
+
+  std::basic_istringstream<CharT, TraitsT, AllocT> ss(std::ios_base::binary, allocator);
+  assert(ss.str().empty());
+
+  // const CharT*
+  ss.str(CS("ba"));
+  assert(ss.str() == CS("ba"));
+
+  // std::basic_string_view<CharT>
+  ss.str(SV("ma"));
+  assert(ss.str() == CS("ma"));
+
+  // std::basic_string<CharT>
+  ss.str(ST("zmt", allocator));
+  assert(ss.str() == CS("zmt"));
+
+  // ConstConvertibleStringView<CharT>
+  ss.str(ConstConvertibleStringView<CharT, TraitsT>{CS("da")});
+  assert(ss.str() == CS("da"));
+
+  const std::basic_string<CharT, TraitsT, AllocT> s(allocator);
+  ss.str(s);
+  assert(ss.str().empty());
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.alloc.pass.cpp
new file mode 100644
index 00000000000000..c4e68916022ff3
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.alloc.pass.cpp
@@ -0,0 +1,145 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_ostringstream
+
+// template<class T>
+//   basic_ostringstream(const T& t, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrStream = std::basic_ostringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrStream, nasty_char*, const AllocT>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrStream, const nasty_char*, const AllocT>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, const AllocT>);
+  static_assert(test_convertible<StrStream, CharT*, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, const AllocT>);
+  static_assert(test_convertible<StrStream, const CharT*, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, std::basic_string_view<CharT, TraitsT>, const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, const AllocT>);
+  static_assert(!test_convertible<StrStream, const SomeObject, const AllocT>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.alloc.pass.cpp
new file mode 100644
index 00000000000000..f41311b6625000
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.alloc.pass.cpp
@@ -0,0 +1,189 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_ostringstream
+
+// template<class T>
+//   basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrStream = std::basic_ostringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(test_convertible<NStrStream, nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(
+      test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, AllocT>);
+  static_assert(test_convertible<StrStream, CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, AllocT>);
+  static_assert(test_convertible<StrStream, const CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrStream,
+                                        const std::basic_string_view<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrStream,
+                                 const std::basic_string_view<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream,
+                                        const std::basic_string<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(
+      test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrStream,
+                                        const ConstConvertibleStringView<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrStream,
+                                 const ConstConvertibleStringView<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrStream,
+                                         NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrStream,
+                                  NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream,
+                                         const NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrStream,
+                                  const NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream, const int, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrStream, const int, std::ios_base::openmode, const AllocT>());
+
+  // Non-mode
+  static_assert(
+      !std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>);
+  static_assert(
+      !test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrStream,
+                                         const std::basic_string_view<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const NonAllocator>);
+  static_assert(!test_convertible<StrStream,
+                                  const std::basic_string_view<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::binary, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.pass.cpp
new file mode 100644
index 00000000000000..9eb3724da3d256
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string_view.mode.pass.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_ostringstream
+
+// template<class T>
+//   explicit basic_ostringstream(const T& t, ios_base::openmode which);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  //  nasty_char*
+  using NStrStream = std::basic_ostringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, nasty_char*, std::ios_base::openmode>());
+
+  // const nasty_char*
+  using NStrStream = std::basic_ostringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, CharT*, std::ios_base::openmode>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const CharT*, std::ios_base::openmode>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(
+      std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(
+      std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(
+      !std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  static_assert(
+      !std::
+          constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode>());
+
+  // Non-mode
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::binary);
+    assert(ss.str() == CS("zmt"));
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string_view.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string_view.pass.cpp
new file mode 100644
index 00000000000000..ec7106726300ee
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string_view.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_ostringstream
+
+// template<class T>
+//   void str(const T& t);
+
+#include <cassert>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#include "../../helper_concepts.h"
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  using NStrStream = std::basic_ostringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<NStrStream, nasty_char*>);
+  static_assert(is_valid_argument_for_str_member<NStrStream, const nasty_char*>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<StrStream, CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrStream, const CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrStream, std::basic_string_view<CharT, TraitsT>>);
+  static_assert(is_valid_argument_for_str_member<StrStream, std::basic_string<CharT, TraitsT, AllocT>>);
+  static_assert(is_valid_argument_for_str_member<StrStream, ConstConvertibleStringView<CharT, TraitsT>>);
+
+  static_assert(!is_valid_argument_for_str_member<StrStream, CharT>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, int>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, SomeObject>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, std::nullptr_t>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, NonConstConvertibleStringView<CharT, TraitsT>>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  AllocT allocator;
+
+  std::basic_ostringstream<CharT, TraitsT, AllocT> ss(std::ios_base::binary, allocator);
+  assert(ss.str().empty());
+
+  // const CharT*
+  ss.str(CS("ba"));
+  assert(ss.str() == CS("ba"));
+
+  // std::basic_string_view<CharT>
+  ss.str(SV("ma"));
+  assert(ss.str() == CS("ma"));
+
+  // std::basic_string<CharT>
+  ss.str(ST("zmt", allocator));
+  assert(ss.str() == CS("zmt"));
+
+  // ConstConvertibleStringView<CharT>
+  ss.str(ConstConvertibleStringView<CharT, TraitsT>{CS("da")});
+  assert(ss.str() == CS("da"));
+
+  const std::basic_string<CharT, TraitsT, AllocT> s(allocator);
+  ss.str(s);
+  assert(ss.str().empty());
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.alloc.pass.cpp
new file mode 100644
index 00000000000000..de07e3a6d23a9c
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.alloc.pass.cpp
@@ -0,0 +1,145 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringbuf
+
+// template<class T>
+//   basic_stringbuf(const T& t, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrBuf = std::basic_istringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(std::constructible_from<NStrBuf, nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrBuf, nasty_char*, const AllocT>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrBuf, const nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrBuf, const nasty_char*, const AllocT>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrBuf = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrBuf, CharT*, const AllocT>);
+  static_assert(test_convertible<StrBuf, CharT*, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrBuf, const CharT*, const AllocT>);
+  static_assert(test_convertible<StrBuf, const CharT*, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrBuf, const std::basic_string_view<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrBuf, std::basic_string_view<CharT, TraitsT>, const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrBuf, const std::basic_string<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrBuf, const std::basic_string<CharT, TraitsT>, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrBuf, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrBuf, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrBuf, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrBuf, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  static_assert(!std::constructible_from<StrBuf, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrBuf, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrBuf, const SomeObject, const AllocT>);
+  static_assert(!test_convertible<StrBuf, const SomeObject, const AllocT>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrBuf, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>);
+  static_assert(!test_convertible<StrBuf, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrBuf = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrBuf ss(CS("zmt"), allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrBuf ss(csv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrBuf ss(cs, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrBuf ss(sv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.alloc.pass.cpp
new file mode 100644
index 00000000000000..fa06e82318cd08
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.alloc.pass.cpp
@@ -0,0 +1,184 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringbuf
+
+// template<class T>
+//   basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrBuf = std::basic_stringbuf<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrBuf, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(test_convertible<NStrBuf, nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrBuf, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(
+      test_convertible<NStrBuf, const nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrBuf = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrBuf, CharT*, AllocT>);
+  static_assert(test_convertible<StrBuf, CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrBuf, const CharT*, AllocT>);
+  static_assert(test_convertible<StrBuf, const CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrBuf,
+                                        const std::basic_string_view<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(
+      test_convertible<StrBuf, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(
+      std::constructible_from<StrBuf, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>);
+  static_assert(
+      test_convertible<StrBuf, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrBuf,
+                                        const ConstConvertibleStringView<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrBuf,
+                                 const ConstConvertibleStringView<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrBuf,
+                                         NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrBuf,
+                                  NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  static_assert(!std::constructible_from<StrBuf,
+                                         const NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrBuf,
+                                  const NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrBuf, const SomeObject, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrBuf, const SomeObject, std::ios_base::openmode, const AllocT>());
+
+  static_assert(!std::constructible_from<StrBuf, const int, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrBuf, const int, std::ios_base::openmode, const AllocT>());
+
+  // Non-mode
+  static_assert(
+      !std::constructible_from<StrBuf, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>);
+  static_assert(!test_convertible<StrBuf, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrBuf,
+                                         const std::basic_string_view<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const NonAllocator>);
+  static_assert(!test_convertible<StrBuf,
+                                  const std::basic_string_view<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrBuf = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrBuf ss(CS("zmt"), std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrBuf ss(csv, std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrBuf ss(cs, std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrBuf ss(sv, std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.pass.cpp
new file mode 100644
index 00000000000000..28bc6af737ecdb
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string_view.mode.pass.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringbuf
+
+// template<class T>
+//   explicit basic_stringbuf(const T& t, ios_base::openmode which);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  //  nasty_char*
+  using NStrStream = std::basic_stringbuf<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, nasty_char*, std::ios_base::openmode>());
+
+  // const nasty_char*
+  using NStrStream = std::basic_stringbuf<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, CharT*, std::ios_base::openmode>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const CharT*, std::ios_base::openmode>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(
+      std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(
+      std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(
+      !std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  static_assert(
+      !std::
+          constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode>());
+
+  // Non-mode
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.members/str.string_view.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.members/str.string_view.pass.cpp
new file mode 100644
index 00000000000000..2a880b93f5ec6c
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.members/str.string_view.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringbuf
+
+// template<class T>
+//   void str(const T& t);
+
+#include <cassert>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#include "../../helper_concepts.h"
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  using NStrBuf = std::basic_stringbuf<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<NStrBuf, nasty_char*>);
+  static_assert(is_valid_argument_for_str_member<NStrBuf, const nasty_char*>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrBuff = std::basic_stringbuf<CharT, TraitsT, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<StrBuff, CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrBuff, const CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrBuff, std::basic_string_view<CharT, TraitsT>>);
+  static_assert(is_valid_argument_for_str_member<StrBuff, std::basic_string<CharT, TraitsT, AllocT>>);
+  static_assert(is_valid_argument_for_str_member<StrBuff, ConstConvertibleStringView<CharT, TraitsT>>);
+
+  static_assert(!is_valid_argument_for_str_member<StrBuff, CharT>);
+  static_assert(!is_valid_argument_for_str_member<StrBuff, int>);
+  static_assert(!is_valid_argument_for_str_member<StrBuff, SomeObject>);
+  static_assert(!is_valid_argument_for_str_member<StrBuff, std::nullptr_t>);
+  static_assert(!is_valid_argument_for_str_member<StrBuff, NonConstConvertibleStringView<CharT, TraitsT>>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  AllocT allocator;
+
+  std::basic_stringbuf<CharT, TraitsT, AllocT> ss(std::ios_base::in | std::ios_base::out, allocator);
+  assert(ss.str().empty());
+
+  // const CharT*
+  ss.str(CS("ba"));
+  assert(ss.str() == CS("ba"));
+
+  // std::basic_string_view<CharT>
+  ss.str(SV("ma"));
+  assert(ss.str() == CS("ma"));
+
+  // std::basic_string<CharT>
+  ss.str(ST("zmt", allocator));
+  assert(ss.str() == CS("zmt"));
+
+  // ConstConvertibleStringView<CharT>
+  ss.str(ConstConvertibleStringView<CharT, TraitsT>{CS("da")});
+  assert(ss.str() == CS("da"));
+
+  const std::basic_string<CharT, TraitsT, AllocT> s(allocator);
+  ss.str(s);
+  assert(ss.str().empty());
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.alloc.pass.cpp
new file mode 100644
index 00000000000000..0aa05b17be6f12
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.alloc.pass.cpp
@@ -0,0 +1,145 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringstream
+
+// template<class T>
+//   basic_stringstream(const T& t, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrStream = std::basic_stringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrStream, nasty_char*, const AllocT>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, AllocT>);
+  static_assert(test_convertible<NStrStream, const nasty_char*, const AllocT>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, const AllocT>);
+  static_assert(test_convertible<StrStream, CharT*, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, const AllocT>);
+  static_assert(test_convertible<StrStream, const CharT*, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, std::basic_string_view<CharT, TraitsT>, const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>);
+  static_assert(!test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, const AllocT>);
+  static_assert(!test_convertible<StrStream, const SomeObject, const AllocT>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.alloc.pass.cpp
new file mode 100644
index 00000000000000..18164b072cf594
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.alloc.pass.cpp
@@ -0,0 +1,189 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringstream
+
+// template<class T>
+//   basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  // nasty_char*
+  using NStrStream = std::basic_stringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(test_convertible<NStrStream, nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+
+  // const nasty_char*
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(
+      test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, AllocT>);
+  static_assert(test_convertible<StrStream, CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, AllocT>);
+  static_assert(test_convertible<StrStream, const CharT*, std::ios_base::openmode, const AllocT>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(std::constructible_from<StrStream,
+                                        const std::basic_string_view<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrStream,
+                                 const std::basic_string_view<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream,
+                                        const std::basic_string<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(
+      test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(std::constructible_from<StrStream,
+                                        const ConstConvertibleStringView<CharT, TraitsT>,
+                                        std::ios_base::openmode,
+                                        const AllocT>);
+  static_assert(test_convertible<StrStream,
+                                 const ConstConvertibleStringView<CharT, TraitsT>,
+                                 std::ios_base::openmode,
+                                 const AllocT>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(!std::constructible_from<StrStream,
+                                         NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrStream,
+                                  NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream,
+                                         const NonConstConvertibleStringView<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const AllocT>);
+  static_assert(!test_convertible<StrStream,
+                                  const NonConstConvertibleStringView<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const AllocT>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>());
+
+  static_assert(!std::constructible_from<StrStream, const int, std::ios_base::openmode, const AllocT>);
+  static_assert(!test_convertible<StrStream, const int, std::ios_base::openmode, const AllocT>());
+
+  // Non-mode
+  static_assert(
+      !std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>);
+  static_assert(
+      !test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>());
+
+  // Non-allocator
+  static_assert(!std::constructible_from<StrStream,
+                                         const std::basic_string_view<CharT, TraitsT>,
+                                         std::ios_base::openmode,
+                                         const NonAllocator>);
+  static_assert(!test_convertible<StrStream,
+                                  const std::basic_string_view<CharT, TraitsT>,
+                                  std::ios_base::openmode,
+                                  const NonAllocator>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::out | std::ios_base::in, allocator);
+    assert(ss.str() == CS("zmt"));
+    assert(ss.rdbuf()->get_allocator() == allocator);
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.pass.cpp
new file mode 100644
index 00000000000000..b7b56f9123b96c
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string_view.mode.pass.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringstream
+
+// template<class T>
+//   explicit basic_stringstream(const T& t, ios_base::openmode which);
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  //  nasty_char*
+  using NStrStream = std::basic_stringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, nasty_char*, std::ios_base::openmode>());
+
+  // const nasty_char*
+  using NStrStream = std::basic_stringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
+
+  static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
+  static_assert(!test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  // `CharT*`
+  static_assert(std::constructible_from<StrStream, CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, CharT*, std::ios_base::openmode>());
+
+  // `const CharT*`
+  static_assert(std::constructible_from<StrStream, const CharT*, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const CharT*, std::ios_base::openmode>());
+
+  // `std::basic_string_view<CharT>`
+  static_assert(
+      std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // `std::basic_string<CharT>`
+  static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // ConstConvertibleStringView<CharT>
+  static_assert(
+      std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // NonConstConvertibleStringView<CharT>
+  static_assert(
+      !std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  static_assert(
+      !std::
+          constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
+  static_assert(
+      !test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
+
+  // Non-`string-view-like`
+  static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode>);
+  static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode>());
+
+  // Non-mode
+  static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>);
+  static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>());
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  const AllocT allocator;
+
+  // const CharT*
+  {
+    StrStream ss(CS("zmt"), std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string_view<CharT>
+  {
+    const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
+    StrStream ss(csv, std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+  // std::basic_string<CharT>
+  {
+    const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
+    StrStream ss(cs, std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+  // ConstConvertibleStringView<CharT>
+  {
+    const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
+    StrStream ss(sv, std::ios_base::out | std::ios_base::in);
+    assert(ss.str() == CS("zmt"));
+  }
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.members/str.string_view.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.members/str.string_view.pass.cpp
new file mode 100644
index 00000000000000..22ea3c6d56e028
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.members/str.string_view.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
+// class basic_stringstream
+
+// template<class T>
+//   void str(const T& t);
+
+#include <cassert>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+#include "constexpr_char_traits.h"
+#include "nasty_string.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#include "../../helper_concepts.h"
+#include "../../helper_string_macros.h"
+#include "../../helper_types.h"
+
+template <typename AllocT = std::allocator<nasty_char>>
+void test_sfinae_with_nasty_char() {
+  using NStrStream = std::basic_stringstream<nasty_char, nasty_char_traits, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<NStrStream, nasty_char*>);
+  static_assert(is_valid_argument_for_str_member<NStrStream, const nasty_char*>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test_sfinae() {
+  using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
+
+  static_assert(is_valid_argument_for_str_member<StrStream, CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrStream, const CharT*>);
+  static_assert(is_valid_argument_for_str_member<StrStream, std::basic_string_view<CharT, TraitsT>>);
+  static_assert(is_valid_argument_for_str_member<StrStream, std::basic_string<CharT, TraitsT, AllocT>>);
+  static_assert(is_valid_argument_for_str_member<StrStream, ConstConvertibleStringView<CharT, TraitsT>>);
+
+  static_assert(!is_valid_argument_for_str_member<StrStream, CharT>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, int>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, SomeObject>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, std::nullptr_t>);
+  static_assert(!is_valid_argument_for_str_member<StrStream, NonConstConvertibleStringView<CharT, TraitsT>>);
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+void test() {
+  AllocT allocator;
+
+  std::basic_stringstream<CharT, TraitsT, AllocT> ss(std::ios_base::out | std::ios_base::in, allocator);
+  assert(ss.str().empty());
+
+  // const CharT*
+  ss.str(CS("ba"));
+  assert(ss.str() == CS("ba"));
+
+  // std::basic_string_view<CharT>
+  ss.str(SV("ma"));
+  assert(ss.str() == CS("ma"));
+
+  // std::basic_string<CharT>
+  ss.str(ST("zmt", allocator));
+  assert(ss.str() == CS("zmt"));
+
+  // ConstConvertibleStringView<CharT>
+  ss.str(ConstConvertibleStringView<CharT, TraitsT>{CS("da")});
+  assert(ss.str() == CS("da"));
+
+  const std::basic_string<CharT, TraitsT, AllocT> s(allocator);
+  ss.str(s);
+  assert(ss.str().empty());
+}
+
+int main(int, char**) {
+  test_sfinae_with_nasty_char();
+  test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
+  test_sfinae<char>();
+  test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
+  test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
+  test<char>();
+  test<char, constexpr_char_traits<char>, std::allocator<char>>();
+  test<char, std::char_traits<char>, test_allocator<char>>();
+  test<char, constexpr_char_traits<char>, test_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_sfinae<wchar_t>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
+  test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+  test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/sstream.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/sstream.version.compile.pass.cpp
index 78e17e5f1ddb56..ad3c8e4012ecff 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/sstream.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/sstream.version.compile.pass.cpp
@@ -56,17 +56,11 @@
 
 #elif TEST_STD_VER > 23
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_sstream_from_string_view
-#     error "__cpp_lib_sstream_from_string_view should be defined in c++26"
-#   endif
-#   if __cpp_lib_sstream_from_string_view != 202306L
-#     error "__cpp_lib_sstream_from_string_view should have the value 202306L in c++26"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_sstream_from_string_view
-#     error "__cpp_lib_sstream_from_string_view should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_sstream_from_string_view
+#   error "__cpp_lib_sstream_from_string_view should be defined in c++26"
+# endif
+# if __cpp_lib_sstream_from_string_view != 202306L
+#   error "__cpp_lib_sstream_from_string_view should have the value 202306L in c++26"
 # endif
 
 #endif // TEST_STD_VER > 23

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 20804d835015e2..5501587915ffa0 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -7394,17 +7394,11 @@
 #   error "__cpp_lib_ssize should have the value 201902L in c++26"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_sstream_from_string_view
-#     error "__cpp_lib_sstream_from_string_view should be defined in c++26"
-#   endif
-#   if __cpp_lib_sstream_from_string_view != 202306L
-#     error "__cpp_lib_sstream_from_string_view should have the value 202306L in c++26"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_sstream_from_string_view
-#     error "__cpp_lib_sstream_from_string_view should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_sstream_from_string_view
+#   error "__cpp_lib_sstream_from_string_view should be defined in c++26"
+# endif
+# if __cpp_lib_sstream_from_string_view != 202306L
+#   error "__cpp_lib_sstream_from_string_view should have the value 202306L in c++26"
 # endif
 
 # if !defined(_LIBCPP_VERSION)

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 16d2fc6a532dbc..c55f5c7d19004a 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1118,7 +1118,6 @@ def add_version_header(tc):
                 "c++26": 202306  # P2495R3 Interfacing stringstreams with string_view
             },
             "headers": ["sstream"],
-            "unimplemented": True,
         },
         {
             "name": "__cpp_lib_stacktrace",


        


More information about the libcxx-commits mailing list