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 +_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 +_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 +_LIBCPP_INLINE_VISIBILITY +void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {} + + +// --- Helper for container move assign -- +template +_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 +_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 +_LIBCPP_INLINE_VISIBILITY +void __move_assign_allocator(_Alloc &, _Alloc &&, false_type) _NOEXCEPT {} + +// --- Helper for container copy assign -- +template +_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 +_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 +_LIBCPP_INLINE_VISIBILITY +void __copy_assign_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_MEMORY Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -385,14 +385,6 @@ is_nothrow_move_assignable::value) {__move_assign_alloc(__c, integral_constant());} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(allocator_type& __x, allocator_type& __y) - _NOEXCEPT_( - !__alloc_traits::propagate_on_container_swap::value || - __is_nothrow_swappable::value) - {__swap_alloc(__x, __y, integral_constant());} 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::value) - { - using _VSTD::swap; - swap(__x, __y); - } - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(allocator_type&, allocator_type&, false_type) - _NOEXCEPT - {} }; template @@ -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::value); +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT; +#else + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + __is_nothrow_swappable::value); +#endif bool __invariants() const; @@ -2016,8 +2000,12 @@ template void vector<_Tp, _Allocator>::swap(vector& __x) - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || - __is_nothrow_swappable::value) +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT +#else + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + __is_nothrow_swappable::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()); #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::value); +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT; +#else + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + __is_nothrow_swappable::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::value) - {__swap_alloc(__x, __y, integral_constant());} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__storage_allocator& __x, __storage_allocator& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable::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; @@ -3155,13 +3128,18 @@ template void vector::swap(vector& __x) - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || - __is_nothrow_swappable::value) +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT +#else + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + __is_nothrow_swappable::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()); } template 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> 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> 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 }