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