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::value); + allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); // C++17 basic_string& operator=(const value_type* s); basic_string& operator=(value_type c); basic_string& operator=(initializer_list); @@ -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::value); + _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value +#if _LIBCPP_STD_VER <= 14 + && is_nothrow_move_assignable::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::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::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::value) + _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value +#if _LIBCPP_STD_VER <= 14 + && is_nothrow_move_assignable::value +#else + || __alloc_traits::is_always_equal::value +#endif + ) { __move_assign(__str, integral_constant()); 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::value); +// allocator_traits::propagate_on_container_move_assignment::value || +// allocator_traits::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::value); -// This tests a conforming extension - #include #include +#include "test_macros.h" #include "test_allocator.h" template @@ -41,7 +45,11 @@ } { typedef std::basic_string, some_alloc> C; +#if TEST_STD_VER <= 14 static_assert(!std::is_nothrow_move_assignable::value, ""); +#else + static_assert( std::is_nothrow_move_assignable::value, ""); +#endif } #endif } 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 @@ // // void swap(basic_string& s); - +// noexcept(allocator_traits::propogate_on_container_swap::value || +// allocator_traits::is_always_equal::value); // C++17 +// before C++17, we used: +// noexcept(!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable::value) + #include #include #include #include +#include "test_macros.h" #include "min_allocator.h" template void test(S s1, S s2) { +#if TEST_STD_VER > 14 + static_assert(std::__is_nothrow_swappable::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, min_allocator> S; test(S(""), S(""));