[libcxx] r245330 - implement more of N4258 - Cleaning up noexcept in the standard library. Specifically add new noexcept stuff to vector and string's move-assignment operations

Marshall Clow via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 18 11:57:00 PDT 2015


Author: marshall
Date: Tue Aug 18 13:57:00 2015
New Revision: 245330

URL: http://llvm.org/viewvc/llvm-project?rev=245330&view=rev
Log:
implement more of N4258 - Cleaning up noexcept in the standard library. Specifically add new noexcept stuff to vector and string's move-assignment operations

Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/include/string
    libcxx/trunk/include/vector
    libcxx/trunk/test/std/containers/sequences/vector.bool/move_assign_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=245330&r1=245329&r2=245330&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Tue Aug 18 13:57:00 2015
@@ -5574,6 +5574,15 @@ template <typename _Alloc>
 _LIBCPP_INLINE_VISIBILITY
 void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
 
+template <typename _Alloc, typename _Traits=allocator_traits<_Alloc>>
+struct __noexcept_move_assign_container : public integral_constant<bool, 
+    _Traits::propagate_on_container_move_assignment::value
+#if _LIBCPP_STD_VER > 14
+        || _Traits::is_always_equal::value
+#else
+        && is_nothrow_move_assignable<_Alloc>::value
+#endif
+    > {};
 
 _LIBCPP_END_NAMESPACE_STD
 

Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=245330&r1=245329&r2=245330&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Tue Aug 18 13:57:00 2015
@@ -115,8 +115,8 @@ public:
     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_type::propagate_on_container_move_assignment::value ||
+             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,8 +1377,7 @@ public:
 #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_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
 #endif
     _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);}
     basic_string& operator=(value_type __c);
@@ -1845,11 +1844,16 @@ private:
 
 #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;
+#else
         _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
 #endif
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     void
@@ -2430,6 +2434,7 @@ template <class _CharT, class _Traits, c
 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);
@@ -2441,7 +2446,11 @@ template <class _CharT, class _Traits, c
 inline _LIBCPP_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
+#if _LIBCPP_STD_VER > 14
+    _NOEXCEPT
+#else
     _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
+#endif
 {
     clear();
     shrink_to_fit();
@@ -2454,8 +2463,7 @@ template <class _CharT, class _Traits, c
 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_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
 {
     __move_assign(__str, integral_constant<bool,
           __alloc_traits::propagate_on_container_move_assignment::value>());

Modified: libcxx/trunk/include/vector
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/vector?rev=245330&r1=245329&r2=245330&view=diff
==============================================================================
--- libcxx/trunk/include/vector (original)
+++ libcxx/trunk/include/vector Tue Aug 18 13:57:00 2015
@@ -51,8 +51,8 @@ public:
     vector& operator=(const vector& x);
     vector& operator=(vector&& x)
         noexcept(
-             allocator_type::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value);
+             allocator_type::propagate_on_container_move_assignment::value ||
+             allocator_type::is_always_equal::value); // C++17
     vector& operator=(initializer_list<value_type> il);
     template <class InputIterator>
         void assign(InputIterator first, InputIterator last);
@@ -175,8 +175,8 @@ public:
     vector& operator=(const vector& x);
     vector& operator=(vector&& x)
         noexcept(
-             allocator_type::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value);
+             allocator_type::propagate_on_container_move_assignment::value ||
+             allocator_type::is_always_equal::value); // C++17
     vector& operator=(initializer_list<value_type> il);
     template <class InputIterator>
         void assign(InputIterator first, InputIterator last);
@@ -562,9 +562,7 @@ public:
     vector(vector&& __x, const allocator_type& __a);
     _LIBCPP_INLINE_VISIBILITY
     vector& operator=(vector&& __x)
-        _NOEXCEPT_(
-             __alloc_traits::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value);
+        _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
     _LIBCPP_INLINE_VISIBILITY
@@ -787,7 +785,8 @@ private:
     void __move_range(pointer __from_s, pointer __from_e, pointer __to);
     void __move_assign(vector& __c, true_type)
         _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
-    void __move_assign(vector& __c, false_type);
+    void __move_assign(vector& __c, false_type)
+        _NOEXCEPT_(__alloc_traits::is_always_equal::value);
     _LIBCPP_INLINE_VISIBILITY
     void __destruct_at_end(pointer __new_last) _NOEXCEPT
     {
@@ -1303,9 +1302,7 @@ template <class _Tp, class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY
 vector<_Tp, _Allocator>&
 vector<_Tp, _Allocator>::operator=(vector&& __x)
-        _NOEXCEPT_(
-             __alloc_traits::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value)
+    _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
 {
     __move_assign(__x, integral_constant<bool,
           __alloc_traits::propagate_on_container_move_assignment::value>());
@@ -1315,6 +1312,7 @@ vector<_Tp, _Allocator>::operator=(vecto
 template <class _Tp, class _Allocator>
 void
 vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
+    _NOEXCEPT_(__alloc_traits::is_always_equal::value)
 {
     if (__base::__alloc() != __c.__alloc())
     {
@@ -2213,9 +2211,7 @@ public:
     vector(vector&& __v, const allocator_type& __a);
     _LIBCPP_INLINE_VISIBILITY
     vector& operator=(vector&& __v)
-        _NOEXCEPT_(
-             __alloc_traits::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value);
+        _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
     _LIBCPP_INLINE_VISIBILITY
@@ -2838,9 +2834,7 @@ template <class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY
 vector<bool, _Allocator>&
 vector<bool, _Allocator>::operator=(vector&& __v)
-        _NOEXCEPT_(
-             __alloc_traits::propagate_on_container_move_assignment::value &&
-             is_nothrow_move_assignable<allocator_type>::value)
+    _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
 {
     __move_assign(__v, integral_constant<bool,
           __storage_traits::propagate_on_container_move_assignment::value>());

Modified: libcxx/trunk/test/std/containers/sequences/vector.bool/move_assign_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/vector.bool/move_assign_noexcept.pass.cpp?rev=245330&r1=245329&r2=245330&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/vector.bool/move_assign_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/vector.bool/move_assign_noexcept.pass.cpp Tue Aug 18 13:57:00 2015
@@ -28,6 +28,32 @@ struct some_alloc
     some_alloc(const some_alloc&);
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_move_assignment;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_move_assignment;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -45,7 +71,22 @@ int main()
     }
     {
         typedef std::vector<bool, some_alloc<bool>> 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
     }
+#if TEST_STD_VER > 14
+    {  // POCMA false, is_always_equal true
+        typedef std::vector<bool, some_alloc2<bool>> C;
+        static_assert( std::is_nothrow_move_assignable<C>::value, "");
+    }
+    {  // POCMA false, is_always_equal false
+        typedef std::vector<bool, some_alloc3<bool>> C;
+        static_assert(!std::is_nothrow_move_assignable<C>::value, "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp?rev=245330&r1=245329&r2=245330&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/vector/vector.cons/move_assign_noexcept.pass.cpp Tue Aug 18 13:57:00 2015
@@ -29,6 +29,33 @@ struct some_alloc
     some_alloc(const some_alloc&);
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_move_assignment;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_move_assignment;
+    typedef std::false_type is_always_equal;
+};
+
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -46,7 +73,24 @@ int main()
     }
     {
         typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C;
+    //  In C++17, move assignment for allocators are not allowed to throw
+#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
+    }
+
+#if TEST_STD_VER > 14
+    {  // POCMA false, is_always_equal true
+        typedef std::vector<MoveOnly, some_alloc2<MoveOnly>> C;
+        static_assert( std::is_nothrow_move_assignable<C>::value, "");
+    }
+    {  // POCMA false, is_always_equal false
+        typedef std::vector<MoveOnly, some_alloc3<MoveOnly>> C;
         static_assert(!std::is_nothrow_move_assignable<C>::value, "");
     }
 #endif
+
+#endif
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp?rev=245330&r1=245329&r2=245330&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp Tue Aug 18 13:57:00 2015
@@ -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);
-
-// This tests a conforming extension
+//         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);
 
 #include <string>
 #include <cassert>
 
+#include "test_macros.h"
 #include "test_allocator.h"
 
 template <class T>
@@ -28,6 +32,32 @@ struct some_alloc
     some_alloc(const some_alloc&);
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_move_assignment;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_move_assignment;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -41,7 +71,25 @@ int main()
     }
     {
         typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
+#if TEST_STD_VER > 14
+    //  if the allocators are always equal, then the move assignment can be noexcept
+        static_assert( std::is_nothrow_move_assignable<C>::value, "");
+#else
         static_assert(!std::is_nothrow_move_assignable<C>::value, "");
+#endif
+    }
+#if TEST_STD_VER > 14
+    {
+    //	POCMA is false, always equal
+        typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C;
+        static_assert( std::is_nothrow_move_assignable<C>::value, "");
     }
+    {
+    //	POCMA is false, not always equal
+        typedef std::basic_string<char, std::char_traits<char>, some_alloc3<char>> C;
+        static_assert(!std::is_nothrow_move_assignable<C>::value, "");
+    }
+#endif
+
 #endif
 }




More information about the cfe-commits mailing list