[libcxx-commits] [libcxx] c0a5b14 - [libc++] Add noexcept clauses to swap per P0408R7 (Efficient Access to basic_stringbuf's Buffer)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 24 09:29:29 PDT 2023


Author: Piotr Fusik
Date: 2023-06-24T18:29:21+02:00
New Revision: c0a5b147fae97198cefd719f50fc655220985f22

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

LOG: [libc++] Add noexcept clauses to swap per P0408R7 (Efficient Access to basic_stringbuf's Buffer)

Reviewed By: #libc, Mordante

Differential Revision: https://reviews.llvm.org/D153427

Added: 
    libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
    libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp

Modified: 
    libcxx/include/sstream

Removed: 
    


################################################################################
diff  --git a/libcxx/include/sstream b/libcxx/include/sstream
index 26c8992153225..05756eb28164e 100644
--- a/libcxx/include/sstream
+++ b/libcxx/include/sstream
@@ -36,7 +36,7 @@ public:
 
     // [stringbuf.assign] Assign and swap:
     basic_stringbuf& operator=(basic_stringbuf&& rhs);
-    void swap(basic_stringbuf& rhs);
+    void swap(basic_stringbuf& rhs) noexcept(see below);                               // conditionally noexcept since C++20
 
     // [stringbuf.members] Member functions:
     basic_string<char_type, traits_type, allocator_type> str() const;
@@ -57,8 +57,8 @@ protected:
 
 // [stringbuf.assign] non member swap
 template <class charT, class traits, class Allocator>
-  void swap(basic_stringbuf<charT, traits, Allocator>& x,
-            basic_stringbuf<charT, traits, Allocator>& y);
+void swap(basic_stringbuf<charT, traits, Allocator>& x,
+          basic_stringbuf<charT, traits, Allocator>& y); // conditionally noexcept since C++20
 
 typedef basic_stringbuf<char>    stringbuf;
 typedef basic_stringbuf<wchar_t> wstringbuf;
@@ -97,8 +97,8 @@ public:
 };
 
 template <class charT, class traits, class Allocator>
-  void swap(basic_istringstream<charT, traits, Allocator>& x,
-            basic_istringstream<charT, traits, Allocator>& y);
+void swap(basic_istringstream<charT, traits, Allocator>& x,
+          basic_istringstream<charT, traits, Allocator>& y);
 
 typedef basic_istringstream<char>    istringstream;
 typedef basic_istringstream<wchar_t> wistringstream;
@@ -138,8 +138,8 @@ public:
 };
 
 template <class charT, class traits, class Allocator>
-  void swap(basic_ostringstream<charT, traits, Allocator>& x,
-            basic_ostringstream<charT, traits, Allocator>& y);
+void swap(basic_ostringstream<charT, traits, Allocator>& x,
+          basic_ostringstream<charT, traits, Allocator>& y);
 
 typedef basic_ostringstream<char>    ostringstream;
 typedef basic_ostringstream<wchar_t> wostringstream;
@@ -179,8 +179,8 @@ public:
 };
 
 template <class charT, class traits, class Allocator>
-  void swap(basic_stringstream<charT, traits, Allocator>& x,
-            basic_stringstream<charT, traits, Allocator>& y);
+void swap(basic_stringstream<charT, traits, Allocator>& x,
+          basic_stringstream<charT, traits, Allocator>& y);
 
 typedef basic_stringstream<char>    stringstream;
 typedef basic_stringstream<wchar_t> wstringstream;
@@ -252,7 +252,12 @@ public:
 
     // [stringbuf.assign] Assign and swap:
     basic_stringbuf& operator=(basic_stringbuf&& __rhs);
-    void swap(basic_stringbuf& __rhs);
+    void swap(basic_stringbuf& __rhs)
+#if _LIBCPP_STD_VER >= 20
+        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
+                 allocator_traits<allocator_type>::is_always_equal::value)
+#endif
+        ;
 
     // [stringbuf.members] Member functions:
     string_type str() const;
@@ -368,6 +373,10 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::operator=(basic_stringbuf&& __rhs)
 template <class _CharT, class _Traits, class _Allocator>
 void
 basic_stringbuf<_CharT, _Traits, _Allocator>::swap(basic_stringbuf& __rhs)
+#if _LIBCPP_STD_VER >= 20
+    noexcept(allocator_traits<_Allocator>::propagate_on_container_swap::value ||
+             allocator_traits<_Allocator>::is_always_equal::value)
+#endif
 {
     char_type* __p = const_cast<char_type*>(__rhs.__str_.data());
     ptr
diff _t __rbinp = -1;
@@ -447,6 +456,9 @@ inline _LIBCPP_INLINE_VISIBILITY
 void
 swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x,
      basic_stringbuf<_CharT, _Traits, _Allocator>& __y)
+#if _LIBCPP_STD_VER >= 20
+    noexcept(noexcept(__x.swap(__y)))
+#endif
 {
     __x.swap(__y);
 }

diff  --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
new file mode 100644
index 0000000000000..cdb09df7c7a9a
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <sstream>
+
+// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
+// class basic_stringbuf
+
+// void swap(basic_stringbuf& rhs)
+//   noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
+//            allocator_traits<allocator_type>::is_always_equal::value);
+
+#include <sstream>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class T>
+struct test_alloc {
+  using value_type = T;
+
+  [[nodiscard]] constexpr T* allocate(std::size_t) { return nullptr; }
+  void deallocate(void*, unsigned) {}
+};
+
+template <class T>
+struct test_alloc_propagate_on_container_swap : test_alloc<T> {
+  using propagate_on_container_swap = std::true_type;
+};
+
+template <class T>
+struct test_alloc_is_always_equal : test_alloc<T> {
+  using is_always_equal = std::true_type;
+};
+
+template <class T>
+struct test_alloc_propagate_on_container_swap_is_always_equal : test_alloc<T> {
+  using propagate_on_container_swap = std::true_type;
+  using is_always_equal             = std::true_type;
+};
+
+template <class T>
+struct test_alloc_not_empty : test_alloc<T> {
+  bool dummy;
+};
+
+template <class T>
+struct test_alloc_propagate_on_container_swap_not_empty : test_alloc<T> {
+  using propagate_on_container_swap = std::true_type;
+  bool dummy;
+};
+
+template <class CharT>
+static void test() {
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc<CharT>> buf;
+    static_assert(noexcept(buf.swap(buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap<CharT>> buf;
+    static_assert(noexcept(buf.swap(buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_is_always_equal<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_is_always_equal<CharT>> buf;
+    static_assert(noexcept(buf.swap(buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_is_always_equal<CharT>>
+        buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_is_always_equal<CharT>>
+        buf;
+    static_assert(noexcept(buf.swap(buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf;
+    static_assert(!noexcept(buf.swap(buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf;
+    static_assert(noexcept(buf.swap(buf1)));
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp
new file mode 100644
index 0000000000000..fdefc5ebe9af0
--- /dev/null
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp
@@ -0,0 +1,101 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <sstream>
+
+// template <class charT, class traits, class Allocator>
+// void swap(basic_stringbuf<charT, traits, Allocator>& x,
+//           basic_stringbuf<charT, traits, Allocator>& y)
+//   noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
+//            allocator_traits<allocator_type>::is_always_equal::value);
+
+#include <sstream>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class T>
+struct test_alloc {
+  using value_type = T;
+
+  [[nodiscard]] constexpr T* allocate(std::size_t) { return nullptr; }
+  void deallocate(void*, unsigned) {}
+};
+
+template <class T>
+struct test_alloc_propagate_on_container_swap : test_alloc<T> {
+  using propagate_on_container_swap = std::true_type;
+};
+
+template <class T>
+struct test_alloc_is_always_equal : test_alloc<T> {
+  using is_always_equal = std::true_type;
+};
+
+template <class T>
+struct test_alloc_propagate_on_container_swap_is_always_equal : test_alloc<T> {
+  using propagate_on_container_swap = std::true_type;
+  using is_always_equal             = std::true_type;
+};
+
+template <class T>
+struct test_alloc_not_empty : test_alloc<T> {
+  bool dummy;
+};
+
+template <class T>
+struct test_alloc_propagate_on_container_swap_not_empty : test_alloc<T> {
+  using propagate_on_container_swap = std::true_type;
+  bool dummy;
+};
+
+template <class CharT>
+static void test() {
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc<CharT>> buf;
+    static_assert(noexcept(swap(buf, buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap<CharT>> buf;
+    static_assert(noexcept(swap(buf, buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_is_always_equal<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_is_always_equal<CharT>> buf;
+    static_assert(noexcept(swap(buf, buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_is_always_equal<CharT>>
+        buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_is_always_equal<CharT>>
+        buf;
+    static_assert(noexcept(swap(buf, buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf;
+    static_assert(!noexcept(swap(buf, buf1)));
+  }
+  {
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf1;
+    std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf;
+    static_assert(noexcept(swap(buf, buf1)));
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+  return 0;
+}


        


More information about the libcxx-commits mailing list