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