mclow.lists added a reviewer: EricWF.
mclow.lists added a subscriber: cfe-commits.

Update the noexcept-ness of move-construction and move-assignment for 
`basic_string`. Use the new "is_always_equal" type trait for noexcept stuff 
when we're building with C++17. Preserve the conforming extension that we had 
before for C++14 and before.

Note that in C++17, if POCMA is true, then move-assigning an allocator cannot 
throw an exception.

http://reviews.llvm.org/D10963

Files:
  include/string
  test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
  test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp

Index: test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
===================================================================
--- test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
+++ test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
@@ -10,18 +10,27 @@
 // <string>
 
 // void swap(basic_string& s);
-
+//    noexcept(allocator_traits<Allocator>::propogate_on_container_swap::value ||
+//             allocator_traits<Allocator>::is_always_equal::value); // C++17
+//   before C++17, we used:
+//      noexcept(!allocator_type::propagate_on_container_swap::value ||
+//               __is_nothrow_swappable<allocator_type>::value)
+               
 #include <string>
 #include <stdexcept>
 #include <algorithm>
 #include <cassert>
 
+#include "test_macros.h"
 #include "min_allocator.h"
 
 template <class S>
 void
 test(S s1, S s2)
 {
+#if TEST_STD_VER > 14
+	static_assert(std::__is_nothrow_swappable<S>::value, "");
+#endif
     S s1_ = s1;
     S s2_ = s2;
     s1.swap(s2);
@@ -52,7 +61,7 @@
     test(S("abcdefghijklmnopqrst"), S("1234567890"));
     test(S("abcdefghijklmnopqrst"), S("12345678901234567890"));
     }
-#if __cplusplus >= 201103L
+#if TEST_STD_VER >= 11
     {
     typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
     test(S(""), S(""));
Index: test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
===================================================================
--- test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
+++ test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
@@ -11,14 +11,18 @@
 
 // basic_string& operator=(basic_string&& c)
 //     noexcept(
-//          allocator_type::propagate_on_container_move_assignment::value &&
-//          is_nothrow_move_assignable<allocator_type>::value);
+//         allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
+//         allocator_traits<allocator_type>::is_always_equal::value); // C++17
+//
+//	before C++17, we use the conforming extension
+//     noexcept(
+//         allocator_type::propagate_on_container_move_assignment::value &&
+//         is_nothrow_move_assignable<allocator_type>::value);
 
-// This tests a conforming extension
-
 #include <string>
 #include <cassert>
 
+#include "test_macros.h"
 #include "test_allocator.h"
 
 template <class T>
@@ -41,7 +45,11 @@
     }
     {
         typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
+#if TEST_STD_VER <= 14
         static_assert(!std::is_nothrow_move_assignable<C>::value, "");
+#else
+        static_assert( std::is_nothrow_move_assignable<C>::value, "");
+#endif
     }
 #endif
 }
Index: include/string
===================================================================
--- include/string
+++ include/string
@@ -115,8 +115,8 @@
     basic_string& operator=(const basic_string& str);
     basic_string& operator=(basic_string&& str)
         noexcept(
-             allocator_type::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value);
+             allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
+             allocator_traits<allocator_type>::is_always_equal::value); // C++17
     basic_string& operator=(const value_type* s);
     basic_string& operator=(value_type c);
     basic_string& operator=(initializer_list<value_type>);
@@ -1377,9 +1377,14 @@
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     _LIBCPP_INLINE_VISIBILITY
     basic_string& operator=(basic_string&& __str)
-        _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value &&
-                   is_nothrow_move_assignable<allocator_type>::value);
+        _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value
+#if _LIBCPP_STD_VER <= 14
+                   && is_nothrow_move_assignable<allocator_type>::value
+#else
+                   || __alloc_traits::is_always_equal::value
 #endif
+                );
+#endif
     _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);}
     basic_string& operator=(value_type __c);
 #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
@@ -1841,11 +1846,16 @@
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     _LIBCPP_INLINE_VISIBILITY
-    void __move_assign(basic_string& __str, false_type);
+    void __move_assign(basic_string& __str, false_type)
+        _NOEXCEPT_(__alloc_traits::is_always_equal::value);
     _LIBCPP_INLINE_VISIBILITY
     void __move_assign(basic_string& __str, true_type)
+#if _LIBCPP_STD_VER <= 14
         _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
+#else
+        _NOEXCEPT;
 #endif
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     void
@@ -2439,6 +2449,7 @@
 inline _LIBCPP_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type)
+    _NOEXCEPT_(__alloc_traits::is_always_equal::value)
 {
     if (__alloc() != __str.__alloc())
         assign(__str);
@@ -2450,7 +2461,11 @@
 inline _LIBCPP_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
+#if _LIBCPP_STD_VER <= 14
     _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
+#else
+    _NOEXCEPT
+#endif
 {
     clear();
     shrink_to_fit();
@@ -2463,8 +2478,13 @@
 inline _LIBCPP_INLINE_VISIBILITY
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str)
-    _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value &&
-               is_nothrow_move_assignable<allocator_type>::value)
+    _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value
+#if _LIBCPP_STD_VER <= 14
+               && is_nothrow_move_assignable<allocator_type>::value
+#else
+               || __alloc_traits::is_always_equal::value
+#endif
+            )
 {
     __move_assign(__str, integral_constant<bool,
           __alloc_traits::propagate_on_container_move_assignment::value>());
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to