Index: include/__hash_table =================================================================== --- include/__hash_table +++ include/__hash_table @@ -985,12 +985,14 @@ void swap(__hash_table& __u) _NOEXCEPT_( - (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || - __is_nothrow_swappable<__pointer_allocator>::value) && - (!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value) && - __is_nothrow_swappable::value && - __is_nothrow_swappable::value); + __is_nothrow_swappable::value && __is_nothrow_swappable::value +#if _LIBCPP_STD_VER <= 11 + && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value + || __is_nothrow_swappable<__pointer_allocator>::value) + && (!__node_traits::propagate_on_container_swap::value + || __is_nothrow_swappable<__node_allocator>::value) +#endif + ); _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const _NOEXCEPT @@ -1118,38 +1120,6 @@ _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} - template - _LIBCPP_INLINE_VISIBILITY - static - void - __swap_alloc(_Ap& __x, _Ap& __y) - _NOEXCEPT_( - !allocator_traits<_Ap>::propagate_on_container_swap::value || - __is_nothrow_swappable<_Ap>::value) - { - __swap_alloc(__x, __y, - integral_constant::propagate_on_container_swap::value - >()); - } - - template - _LIBCPP_INLINE_VISIBILITY - static - void - __swap_alloc(_Ap& __x, _Ap& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value) - { - using _VSTD::swap; - swap(__x, __y); - } - - template - _LIBCPP_INLINE_VISIBILITY - static - void - __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {} - void __deallocate(__node_pointer __np) _NOEXCEPT; __node_pointer __detach() _NOEXCEPT; @@ -2382,12 +2352,14 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) _NOEXCEPT_( - (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || - __is_nothrow_swappable<__pointer_allocator>::value) && - (!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value) && - __is_nothrow_swappable::value && - __is_nothrow_swappable::value) + __is_nothrow_swappable::value && __is_nothrow_swappable::value +#if _LIBCPP_STD_VER <= 11 + && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value + || __is_nothrow_swappable<__pointer_allocator>::value) + && (!__node_traits::propagate_on_container_swap::value + || __is_nothrow_swappable<__node_allocator>::value) +#endif + ) { { __node_pointer_pointer __npp = __bucket_list_.release(); @@ -2395,9 +2367,9 @@ __u.__bucket_list_.reset(__npp); } _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size()); - __swap_alloc(__bucket_list_.get_deleter().__alloc(), + __swap_allocator(__bucket_list_.get_deleter().__alloc(), __u.__bucket_list_.get_deleter().__alloc()); - __swap_alloc(__node_alloc(), __u.__node_alloc()); + __swap_allocator(__node_alloc(), __u.__node_alloc()); _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_); __p2_.swap(__u.__p2_); __p3_.swap(__u.__p3_); Index: include/__split_buffer =================================================================== --- include/__split_buffer +++ include/__split_buffer @@ -156,25 +156,6 @@ _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__alloc_rr& __x, __alloc_rr& __y) - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| - __is_nothrow_swappable<__alloc_rr>::value) - {__swap_alloc(__x, __y, integral_constant());} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__alloc_rr& __x, __alloc_rr& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable<__alloc_rr>::value) - { - using _VSTD::swap; - swap(__x, __y); - } - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__alloc_rr&, __alloc_rr&, false_type) _NOEXCEPT - {} }; template @@ -431,7 +412,7 @@ _VSTD::swap(__begin_, __x.__begin_); _VSTD::swap(__end_, __x.__end_); _VSTD::swap(__end_cap(), __x.__end_cap()); - __swap_alloc(__alloc(), __x.__alloc()); + __swap_allocator(__alloc(), __x.__alloc()); } template Index: include/__tree =================================================================== --- include/__tree +++ include/__tree @@ -926,9 +926,12 @@ void swap(__tree& __t) _NOEXCEPT_( - __is_nothrow_swappable::value && - (!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value)); + __is_nothrow_swappable::value +#if _LIBCPP_STD_VER <= 11 + && (!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) +#endif + ); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS @@ -1096,25 +1099,6 @@ _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {} - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y) - _NOEXCEPT_( - !__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value) - {__swap_alloc(__x, __y, integral_constant());} - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value) - { - using _VSTD::swap; - swap(__x, __y); - } - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type) - _NOEXCEPT - {} - __node_pointer __detach(); static __node_pointer __detach(__node_pointer); @@ -1452,15 +1436,18 @@ template void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) - _NOEXCEPT_( - __is_nothrow_swappable::value && - (!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value)) + _NOEXCEPT_( + __is_nothrow_swappable::value +#if _LIBCPP_STD_VER <= 11 + && (!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) +#endif + ) { using _VSTD::swap; swap(__begin_node_, __t.__begin_node_); swap(__pair1_.first(), __t.__pair1_.first()); - __swap_alloc(__node_alloc(), __t.__node_alloc()); + __swap_allocator(__node_alloc(), __t.__node_alloc()); __pair3_.swap(__t.__pair3_); if (size() == 0) __begin_node() = __end_node(); Index: include/deque =================================================================== --- include/deque +++ include/deque @@ -124,8 +124,7 @@ iterator erase(const_iterator p); iterator erase(const_iterator f, const_iterator l); void swap(deque& c) - noexcept(!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value); + noexcept(allocator_traits::is_always_equal::value); // C++17 void clear() noexcept; }; @@ -954,8 +953,12 @@ #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void swap(__deque_base& __c) - _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 protected: void clear() _NOEXCEPT; @@ -991,26 +994,6 @@ _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__deque_base&, false_type) _NOEXCEPT {} - - _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());} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(allocator_type& __x, allocator_type& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable::value) - { - using _VSTD::swap; - swap(__x, __y); - } - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(allocator_type&, allocator_type&, false_type) - _NOEXCEPT - {} }; template @@ -1134,13 +1117,17 @@ template void __deque_base<_Tp, _Allocator>::swap(__deque_base& __c) - _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 { __map_.swap(__c.__map_); _VSTD::swap(__start_, __c.__start_); _VSTD::swap(size(), __c.size()); - __swap_alloc(__alloc(), __c.__alloc()); + __swap_allocator(__alloc(), __c.__alloc()); } template @@ -1342,8 +1329,12 @@ iterator erase(const_iterator __f, const_iterator __l); void swap(deque& __c) +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT; +#else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); +#endif void clear() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY @@ -2277,13 +2268,13 @@ __buf(max(2 * __base::__map_.capacity(), 1), 0, __base::__map_.__alloc()); - typedef __allocator_destructor<_Allocator> _Dp; - unique_ptr __hold( - __alloc_traits::allocate(__a, __base::__block_size), - _Dp(__a, __base::__block_size)); - __buf.push_back(__hold.get()); - __hold.release(); - + typedef __allocator_destructor<_Allocator> _Dp; + unique_ptr __hold( + __alloc_traits::allocate(__a, __base::__block_size), + _Dp(__a, __base::__block_size)); + __buf.push_back(__hold.get()); + __hold.release(); + for (typename __base::__map_pointer __i = __base::__map_.begin(); __i != __base::__map_.end(); ++__i) __buf.push_back(*__i); @@ -2420,12 +2411,12 @@ __base::__map_.size(), __base::__map_.__alloc()); - typedef __allocator_destructor<_Allocator> _Dp; - unique_ptr __hold( - __alloc_traits::allocate(__a, __base::__block_size), - _Dp(__a, __base::__block_size)); - __buf.push_back(__hold.get()); - __hold.release(); + typedef __allocator_destructor<_Allocator> _Dp; + unique_ptr __hold( + __alloc_traits::allocate(__a, __base::__block_size), + _Dp(__a, __base::__block_size)); + __buf.push_back(__hold.get()); + __hold.release(); for (typename __base::__map_pointer __i = __base::__map_.end(); __i != __base::__map_.begin();) @@ -2793,8 +2784,12 @@ inline _LIBCPP_INLINE_VISIBILITY void deque<_Tp, _Allocator>::swap(deque& __c) - _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 { __base::swap(__c); } Index: include/forward_list =================================================================== --- include/forward_list +++ include/forward_list @@ -107,8 +107,7 @@ iterator erase_after(const_iterator first, const_iterator last); void swap(forward_list& x) - noexcept(!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value); + noexcept(allocator_traits::is_always_equal::value); // C++17 void resize(size_type n); void resize(size_type n, const value_type& v); @@ -431,8 +430,12 @@ public: void swap(__forward_list_base& __x) - _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value); +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT; +#else + _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || + __is_nothrow_swappable<__node_allocator>::value); +#endif protected: void clear() _NOEXCEPT; @@ -454,26 +457,6 @@ void __move_assign_alloc(__forward_list_base& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {__alloc() = _VSTD::move(__x.__alloc());} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y) - _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value) - {__swap_alloc(__x, __y, integral_constant());} - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, - false_type) - _NOEXCEPT - {} - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, - true_type) - _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value) - { - using _VSTD::swap; - swap(__x, __y); - } }; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -512,10 +495,15 @@ inline _LIBCPP_INLINE_VISIBILITY void __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x) - _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value) +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT +#else + _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || + __is_nothrow_swappable<__node_allocator>::value) +#endif { - __swap_alloc(__alloc(), __x.__alloc()); + __swap_allocator(__alloc(), __x.__alloc(), + integral_constant()); using _VSTD::swap; swap(__before_begin()->__next_, __x.__before_begin()->__next_); } @@ -703,8 +691,12 @@ _LIBCPP_INLINE_VISIBILITY void swap(forward_list& __x) +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT +#else _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) +#endif {base::swap(__x);} void resize(size_type __n); Index: include/list =================================================================== --- include/list +++ include/list @@ -118,8 +118,7 @@ void resize(size_type sz, const value_type& c); void swap(list&) - noexcept(!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value); + noexcept(allocator_traits::is_always_equal::value); // C++17 void clear() noexcept; void splice(const_iterator position, list& x); @@ -593,8 +592,12 @@ } void swap(__list_imp& __c) - _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value); +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT; +#else + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + __is_nothrow_swappable::value); +#endif _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __list_imp& __c) @@ -611,24 +614,6 @@ private: _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y) - _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value) - {__swap_alloc(__x, __y, integral_constant());} - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value) - { - using _VSTD::swap; - swap(__x, __y); - } - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type) - _NOEXCEPT - {} - - _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __list_imp& __c, true_type) { if (__node_alloc() != __c.__node_alloc()) @@ -728,15 +713,19 @@ template void __list_imp<_Tp, _Alloc>::swap(__list_imp& __c) - _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::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->__node_alloc() == __c.__node_alloc(), "list::swap: Either propagate_on_container_swap must be true" " or the allocators must compare equal"); using _VSTD::swap; - __swap_alloc(__node_alloc(), __c.__node_alloc()); + __swap_allocator(__node_alloc(), __c.__node_alloc()); swap(__sz(), __c.__sz()); swap(__end_, __c.__end_); if (__sz() == 0) @@ -972,8 +961,12 @@ _LIBCPP_INLINE_VISIBILITY void swap(list& __c) +#if _LIBCPP_STD_VER >= 14 + _NOEXCEPT +#else _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) +#endif {base::swap(__c);} _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {base::clear();} Index: include/map =================================================================== --- include/map +++ include/map @@ -159,10 +159,8 @@ void clear() noexcept; void swap(map& m) - noexcept( - __is_nothrow_swappable::value && - (!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value)); + noexcept(allocator_traits::is_always_equal::value && + __is_nothrow_swappable::value); // C++17 // observers: allocator_type get_allocator() const noexcept; @@ -354,10 +352,8 @@ void clear() noexcept; void swap(multimap& m) - noexcept( - __is_nothrow_swappable::value && - (!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value)); + noexcept(allocator_traits::is_always_equal::value && + __is_nothrow_swappable::value); // C++17 // observers: allocator_type get_allocator() const noexcept; @@ -479,6 +475,12 @@ _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _CP& __y) const {return static_cast(*this)(__x, __y.__cc.first);} + void swap(__map_value_compare&__y) + _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value) + { + using _VSTD::swap; + swap(static_cast(*this), static_cast(__y)); + } #if _LIBCPP_STD_VER > 11 template @@ -521,7 +523,13 @@ _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _CP& __y) const {return comp(__x, __y.__cc.first);} - + void swap(__map_value_compare&__y) + _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value) + { + using _VSTD::swap; + swap(comp, __y.comp); + } + #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY @@ -537,6 +545,16 @@ #endif }; +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__map_value_compare<_Key, _CP, _Compare, __b>& __x, + __map_value_compare<_Key, _CP, _Compare, __b>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + template class __map_node_destructor { Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -5543,6 +5543,38 @@ _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_allocator(__a1, __a2, + integral_constant::propagate_on_container_swap::value>()); +} + +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 {} + + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_MEMORY Index: include/string =================================================================== --- include/string +++ include/string @@ -220,8 +220,8 @@ basic_string substr(size_type pos = 0, size_type n = npos) const; void swap(basic_string& str) - noexcept(!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); // C++17 const value_type* c_str() const noexcept; const value_type* data() const noexcept; @@ -1604,8 +1604,12 @@ _LIBCPP_INLINE_VISIBILITY void swap(basic_string& __str) - _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_INLINE_VISIBILITY const value_type* c_str() const _NOEXCEPT {return data();} @@ -1868,24 +1872,6 @@ _NOEXCEPT {} - _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());} - - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(allocator_type& __x, allocator_type& __y, true_type) - _NOEXCEPT_(__is_nothrow_swappable::value) - { - using _VSTD::swap; - swap(__x, __y); - } - _LIBCPP_INLINE_VISIBILITY - static void __swap_alloc(allocator_type&, allocator_type&, false_type) _NOEXCEPT - {} - _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type); @@ -3366,8 +3352,12 @@ inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) - _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 { #if _LIBCPP_DEBUG_LEVEL >= 2 if (!__is_long()) @@ -3377,7 +3367,7 @@ __get_db()->swap(this, &__str); #endif _VSTD::swap(__r_.first(), __str.__r_.first()); - __swap_alloc(__alloc(), __str.__alloc()); + __swap_allocator(__alloc(), __str.__alloc()); } // find Index: include/unordered_map =================================================================== --- include/unordered_map +++ include/unordered_map @@ -401,6 +401,12 @@ _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return static_cast(*this)(__x);} + void swap(__unordered_map_hasher&__y) + _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) + { + using _VSTD::swap; + swap(static_cast(*this), static_cast(__y)); + } }; template @@ -425,8 +431,24 @@ _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return __hash_(__x);} + void swap(__unordered_map_hasher&__y) + _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) + { + using _VSTD::swap; + swap(__hash_, __y.__hash_); + } }; +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __x, + __unordered_map_hasher<_Key, _Cp, _Hash, __b>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + template ::value && !__libcpp_is_final<_Pred>::value > @@ -453,6 +475,12 @@ _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return static_cast(*this)(__x, __y.__cc.first);} + void swap(__unordered_map_equal&__y) + _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) + { + using _VSTD::swap; + swap(static_cast(*this), static_cast(__y)); + } }; template @@ -480,8 +508,24 @@ _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return __pred_(__x, __y.__cc.first);} + void swap(__unordered_map_equal&__y) + _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) + { + using _VSTD::swap; + swap(__pred_, __y.__pred_); + } }; +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__unordered_map_equal<_Key, _Cp, _Pred, __b>& __x, + __unordered_map_equal<_Key, _Cp, _Pred, __b>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + template class __hash_map_node_destructor { Index: include/unordered_set =================================================================== --- include/unordered_set +++ include/unordered_set @@ -120,11 +120,9 @@ void clear() noexcept; void swap(unordered_set&) - noexcept( - (!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value) && - __is_nothrow_swappable::value && - __is_nothrow_swappable::value); + noexcept(allocator_traits::is_always_equal::value && + noexcept(swap(declval(), declval())) && + noexcept(swap(declval(), declval()))); // C++17 hasher hash_function() const; key_equal key_eq() const; @@ -270,11 +268,9 @@ void clear() noexcept; void swap(unordered_multiset&) - noexcept( - (!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value) && - __is_nothrow_swappable::value && - __is_nothrow_swappable::value); + noexcept(allocator_traits::is_always_equal::value && + noexcept(swap(declval(), declval())) && + noexcept(swap(declval(), declval()))); // C++17 hasher hash_function() const; key_equal key_eq() const; Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -119,8 +119,8 @@ void resize(size_type sz, const value_type& c); void swap(vector&) - noexcept(!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value); + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); // C++17 bool __invariants() const; }; @@ -237,8 +237,8 @@ void resize(size_type sz, value_type x); void swap(vector&) - noexcept(!allocator_type::propagate_on_container_swap::value || - __is_nothrow_swappable::value); + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); // C++17 void flip() noexcept; bool __invariants() const; @@ -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/associative/map/map.special/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp +++ test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(map& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -33,6 +37,60 @@ typedef std::true_type propagate_on_container_swap; }; +template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::map, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::map, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::map, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::map, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::map, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp +++ test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(multimap& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -33,6 +37,60 @@ typedef std::true_type propagate_on_container_swap; }; +template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::multimap, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::multimap, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::multimap, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::multimap, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::map, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp +++ test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(multiset& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -33,6 +37,60 @@ typedef std::true_type propagate_on_container_swap; }; +template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::multiset, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::multiset, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::multiset, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::multiset, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::multiset, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp +++ test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(set& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -33,6 +37,60 @@ typedef std::true_type propagate_on_container_swap; }; +template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -56,5 +114,35 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for comp + typedef std::set, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for comp + typedef std::set, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for comp + typedef std::set, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for comp + typedef std::set, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for comp + typedef std::set, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp +++ test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp @@ -12,6 +12,9 @@ // void swap(deque& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value); // This tests a conforming extension @@ -33,6 +36,19 @@ typedef std::true_type propagate_on_container_swap; }; +template +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_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +70,21 @@ { typedef std::deque> C; C c1, c2; +#if TEST_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 } +#if TEST_STD_VER >= 14 + { + typedef std::deque> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp +++ test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp @@ -12,6 +12,9 @@ // void swap(forward_list& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(is_always_equal::value); // This tests a conforming extension @@ -33,6 +36,19 @@ typedef std::true_type propagate_on_container_swap; }; +template +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_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +70,21 @@ { typedef std::forward_list> C; C c1, c2; +#if TEST_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 } +#if TEST_STD_VER >= 14 + { + typedef std::forward_list> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp +++ test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp @@ -12,6 +12,9 @@ // void swap(list& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value); // This tests a conforming extension @@ -33,6 +36,19 @@ typedef std::true_type propagate_on_container_swap; }; +template +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_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +70,21 @@ { typedef std::list> C; C c1, c2; +#if TEST_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 } +#if TEST_STD_VER >= 14 + { + typedef std::list> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } 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 @@ -12,6 +12,10 @@ // void swap(vector& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::propagate_on_container_swap::value || +// allocator_traits::is_always_equal::value); // This tests a conforming extension @@ -32,6 +36,19 @@ typedef std::true_type propagate_on_container_swap; }; +template +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_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -53,7 +70,21 @@ { typedef std::vector> C; C c1, c2; +#if TEST_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 } +#if TEST_STD_VER >= 14 + { + typedef std::vector> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + 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 @@ -12,6 +12,10 @@ // void swap(vector& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::propagate_on_container_swap::value || +// allocator_traits::is_always_equal::value); // This tests a conforming extension @@ -33,6 +37,19 @@ typedef std::true_type propagate_on_container_swap; }; +template +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_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -54,7 +71,21 @@ { typedef std::vector> C; C c1, c2; +#if TEST_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 } +#if TEST_STD_VER >= 14 + { + typedef std::vector> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp +++ test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // // void swap(unordered_map& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable::value) && +// __is_nothrow_swappable::value && +// __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval())) && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -31,6 +39,22 @@ }; template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template struct some_hash { typedef T value_type; @@ -38,9 +62,62 @@ some_hash(const some_hash&); }; +template +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_hash2&, some_hash2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + + int main() { #if __has_feature(cxx_noexcept) + typedef std::pair MapType; { typedef std::unordered_map C; C c1, c2; @@ -48,13 +125,13 @@ } { typedef std::unordered_map, - std::equal_to, test_allocator>> C; + std::equal_to, test_allocator> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } { typedef std::unordered_map, - std::equal_to, other_allocator>> C; + std::equal_to, other_allocator> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } @@ -69,5 +146,54 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_map, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_map, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_map, some_comp2, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_map, some_comp2, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_map, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_map, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_map, some_comp2, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_map, some_comp2, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_map, some_comp2, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif +#endif } Index: test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp +++ test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // // void swap(unordered_multimap& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable::value) && +// __is_nothrow_swappable::value && +// __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// __is_nothrow_swappable::value && +// __is_nothrow_swappable::value); // This tests a conforming extension @@ -31,6 +39,22 @@ }; template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template struct some_hash { typedef T value_type; @@ -38,9 +62,61 @@ some_hash(const some_hash&); }; +template +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_hash2&, some_hash2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) + typedef std::pair MapType; { typedef std::unordered_multimap C; C c1, c2; @@ -48,13 +124,13 @@ } { typedef std::unordered_multimap, - std::equal_to, test_allocator>> C; + std::equal_to, test_allocator> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } { typedef std::unordered_multimap, - std::equal_to, other_allocator>> C; + std::equal_to, other_allocator> C; C c1, c2; static_assert(noexcept(swap(c1, c2)), ""); } @@ -69,5 +145,54 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multimap, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multimap, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multimap, some_comp2, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multimap, some_comp2, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multimap, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multimap, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multimap, some_comp2, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multimap, some_comp2, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multimap, some_comp2, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp +++ test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // // void swap(unordered_multiset& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable::value) && +// __is_nothrow_swappable::value && +// __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval())) && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -31,6 +39,22 @@ }; template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template struct some_hash { typedef T value_type; @@ -38,6 +62,57 @@ some_hash(const some_hash&); }; +template +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_hash2&, some_hash2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -69,5 +144,55 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multiset, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_multiset, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multiset, some_comp2, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_multiset, some_comp2, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multiset, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_multiset, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multiset, some_comp2, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multiset, some_comp2, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_multiset, some_comp2, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp =================================================================== --- test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp +++ test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp @@ -10,8 +10,16 @@ // // void swap(unordered_set& c) -// noexcept(!allocator_type::propagate_on_container_swap::value || -// __is_nothrow_swappable::value); +// noexcept( +// (!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable::value) && +// __is_nothrow_swappable::value && +// __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::is_always_equal::value && +// noexcept(swap(declval(), declval())) && +// noexcept(swap(declval(), declval()))); // This tests a conforming extension @@ -31,6 +39,22 @@ }; template +struct some_comp2 +{ + typedef T value_type; + + some_comp2() {} + some_comp2(const some_comp2&) {} + void deallocate(void*, unsigned) {} + typedef std::true_type propagate_on_container_swap; +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_comp2&, some_comp2&) noexcept {} +#endif + +template struct some_hash { typedef T value_type; @@ -38,6 +62,57 @@ some_hash(const some_hash&); }; +template +struct some_hash2 +{ + typedef T value_type; + some_hash2() {} + some_hash2(const some_hash2&); +}; + +#if TEST_STD_VER >= 14 +template +void swap(some_hash2&, some_hash2&) noexcept {} +#endif + +template +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +template +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_swap; + typedef std::true_type is_always_equal; +}; + +template +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_swap; + typedef std::false_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -69,5 +144,55 @@ C c1, c2; static_assert(!noexcept(swap(c1, c2)), ""); } + +#if TEST_STD_VER >= 14 + { // POCS allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_set, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, throwable swap for comp + typedef std::unordered_set, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_set, some_comp2, some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, throwable swap for hash, nothrow swap for comp + typedef std::unordered_set, some_comp2, some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_set, some_comp , some_alloc > C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, throwable swap for comp + typedef std::unordered_set, some_comp , some_alloc2> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } + { // POCS allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_set, some_comp2, some_alloc > C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + { // always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_set, some_comp2, some_alloc2> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } + + { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp + typedef std::unordered_set, some_comp2, some_alloc3> C; + C c1, c2; + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif } Index: test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp =================================================================== --- test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp +++ test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp @@ -12,6 +12,10 @@ // void swap(basic_string& c) // noexcept(!allocator_type::propagate_on_container_swap::value || // __is_nothrow_swappable::value); +// +// In C++17, the standard says that swap shall have: +// noexcept(allocator_traits::propagate_on_container_swap::value || +// allocator_traits::is_always_equal::value); // This tests a conforming extension @@ -32,6 +36,19 @@ typedef std::true_type propagate_on_container_swap; }; +template +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_swap; + typedef std::true_type is_always_equal; +}; + int main() { #if __has_feature(cxx_noexcept) @@ -48,7 +65,21 @@ { typedef std::basic_string, some_alloc> C; C c1, c2; +#if TEST_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 } +#if TEST_STD_VER >= 14 + { + typedef std::basic_string, some_alloc2> C; + C c1, c2; + // if the allocators are always equal, then the swap can be noexcept + static_assert( noexcept(swap(c1, c2)), ""); + } #endif + +#endif }