mclow.lists added reviewers: EricWF, K-ballo, howard.hinnant.
mclow.lists added a subscriber: cfe-commits.

Every container in libc++ has a set of routines for handling 
`propagate_on_container_swap`, `propagate_on_container_move_assignment` and 
`propagate_on_container_copy_assignment`. They're all basically identical.

Make generic versions of these routines in <memory>, and demonstrate their use 
in `vector::swap`.

Along the way, update the noexcept() conditions on `vector::swap`

Eventually, propagate this pattern across all the containers.

http://reviews.llvm.org/D10998

Files:
  include/memory
  include/vector
  test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp
  test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp

Index: test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp
===================================================================
--- test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp
+++ test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp
@@ -53,7 +53,12 @@
     {
         typedef std::vector<bool, some_alloc<bool>> C;
         C c1, c2;
+#if _LIBCPP_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
 #endif
 }
Index: test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp
+++ test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp
@@ -54,7 +54,12 @@
     {
         typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C;
         C c1, c2;
+#if _LIBCPP_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
 #endif
 }
Index: include/vector
===================================================================
--- include/vector
+++ include/vector
@@ -385,14 +385,6 @@
             is_nothrow_move_assignable<allocator_type>::value)
         {__move_assign_alloc(__c, integral_constant<bool,
                       __alloc_traits::propagate_on_container_move_assignment::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y)
-        _NOEXCEPT_(
-            !__alloc_traits::propagate_on_container_swap::value ||
-            __is_nothrow_swappable<allocator_type>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __alloc_traits::propagate_on_container_swap::value>());}
 private:
     _LIBCPP_INLINE_VISIBILITY
     void __copy_assign_alloc(const __vector_base& __c, true_type)
@@ -421,18 +413,6 @@
     void __move_assign_alloc(__vector_base&, false_type)
         _NOEXCEPT
         {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y, true_type)
-        _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type&, allocator_type&, false_type)
-        _NOEXCEPT
-        {}
 };
 
 template <class _Tp, class _Allocator>
@@ -760,8 +740,12 @@
     void resize(size_type __sz, const_reference __x);
 
     void swap(vector&)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 
     bool __invariants() const;
 
@@ -2016,8 +2000,12 @@
 template <class _Tp, class _Allocator>
 void
 vector<_Tp, _Allocator>::swap(vector& __x)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value ||
                    this->__alloc() == __x.__alloc(),
@@ -2026,7 +2014,8 @@
     _VSTD::swap(this->__begin_, __x.__begin_);
     _VSTD::swap(this->__end_, __x.__end_);
     _VSTD::swap(this->__end_cap(), __x.__end_cap());
-    __base::__swap_alloc(this->__alloc(), __x.__alloc());
+    __swap_allocator(this->__alloc(), __x.__alloc(), 
+        integral_constant<bool,__alloc_traits::propagate_on_container_swap::value>());
 #if _LIBCPP_DEBUG_LEVEL >= 2
     __get_db()->swap(this, &__x);
 #endif  // _LIBCPP_DEBUG_LEVEL >= 2
@@ -2354,8 +2343,12 @@
     void clear() _NOEXCEPT {__size_ = 0;}
 
     void swap(vector&)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 
     void resize(size_type __sz, value_type __x = false);
     void flip() _NOEXCEPT;
@@ -2433,26 +2426,6 @@
         _NOEXCEPT
         {}
 
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__storage_allocator& __x, __storage_allocator& __y)
-        _NOEXCEPT_(
-            !__storage_traits::propagate_on_container_swap::value ||
-            __is_nothrow_swappable<allocator_type>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __storage_traits::propagate_on_container_swap::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__storage_allocator& __x, __storage_allocator& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<allocator_type>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__storage_allocator&, __storage_allocator&, false_type)
-        _NOEXCEPT
-        {}
-
     size_t __hash_code() const _NOEXCEPT;
 
     friend class __bit_reference<vector>;
@@ -3155,13 +3128,18 @@
 template <class _Allocator>
 void
 vector<bool, _Allocator>::swap(vector& __x)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     _VSTD::swap(this->__begin_, __x.__begin_);
     _VSTD::swap(this->__size_, __x.__size_);
     _VSTD::swap(this->__cap(), __x.__cap());
-    __swap_alloc(this->__alloc(), __x.__alloc());
+    __swap_allocator(this->__alloc(), __x.__alloc(), 
+        integral_constant<bool, __alloc_traits::propagate_on_container_swap::value>());
 }
 
 template <class _Allocator>
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -5543,6 +5543,98 @@
 
 _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space);
 
+// --- Helper for container swap --
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __swap_allocator(_Alloc & __a1, _Alloc & __a2)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
+#endif
+{
+    __swap_alloc(__a1, __a2, 
+                 _VSTD::allocator_traits<_Alloc>::propagate_on_container_swap());
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __swap_allocator(_Alloc & __a1, _Alloc & __a2, true_type)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
+#endif
+{
+    using _VSTD::swap;
+    swap(__a1, __a2);
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
+
+
+// --- Helper for container move assign --
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __move_assign_allocator(_Alloc & __a1, _Alloc && __a2)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(is_nothrow_move_assignable<_Alloc>::value)
+#endif
+{
+    __move_assign_allocator(__a1, __a2, 
+      _VSTD::allocator_traits<_Alloc>::propagate_on_container_move_assignment());
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __move_assign_allocator(_Alloc & __a1, _Alloc && __a2, true_type)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(is_nothrow_move_assignable<_Alloc>::value)
+#endif
+{
+    __a1 = _VSTD::move(__a2);
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __move_assign_allocator(_Alloc &, _Alloc &&, false_type) _NOEXCEPT {}
+
+// --- Helper for container copy assign --
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __copy_assign_allocator(_Alloc & __a1, const _Alloc & __a2)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(is_nothrow_copy_assignable<_Alloc>::value)
+#endif
+{
+    __copy_assign_allocator(__a1, __a2, 
+      _VSTD::allocator_traits<_Alloc>::propagate_on_container_copy_assignment());
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __copy_assign_allocator(_Alloc & __a1, _Alloc & __a2, true_type)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(is_nothrow_copy_assignable<_Alloc>::value)
+#endif
+{
+    __a1 = __a2;
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __copy_assign_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_MEMORY
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to