From dbafd61d4db515142ea2a38505b48638fcec9907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 19 Jan 2015 00:18:44 +0100 Subject: [PATCH] updated move assignments and swap operations to "N4258: Cleaning-up noexcept in the Library, Rev 3" with some customizations. --- include/boost/container/deque.hpp | 5 +++- include/boost/container/detail/flat_tree.hpp | 9 ++++-- include/boost/container/detail/tree.hpp | 30 +++++++++++-------- .../boost/container/detail/type_traits.hpp | 1 + include/boost/container/flat_map.hpp | 10 +++++-- include/boost/container/flat_set.hpp | 14 ++++++--- include/boost/container/list.hpp | 5 +++- include/boost/container/map.hpp | 18 ++++++++--- include/boost/container/set.hpp | 13 ++++++-- include/boost/container/slist.hpp | 5 +++- include/boost/container/stable_vector.hpp | 5 +++- include/boost/container/string.hpp | 5 +++- include/boost/container/vector.hpp | 8 +++-- 13 files changed, 94 insertions(+), 34 deletions(-) diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index db221f4..dce2720 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -733,7 +733,8 @@ class deque : protected deque_base //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. deque& operator= (BOOST_RV_REF(deque) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { BOOST_ASSERT(this != &x); allocator_type &this_alloc = this->alloc(); @@ -1622,6 +1623,8 @@ class deque : protected deque_base //! //! Complexity: Constant. void swap(deque &x) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { this->swap_members(x); container_detail::bool_ flag; diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index d7ec702..09e678f 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -98,8 +98,9 @@ template class flat_tree { - typedef boost::container::vector vector_t; - typedef Allocator allocator_t; + typedef boost::container::vector vector_t; + typedef Allocator allocator_t; + typedef allocator_traits allocator_traits_type; public: typedef flat_tree_value_compare value_compare; @@ -264,6 +265,8 @@ class flat_tree { m_data = x.m_data; return *this; } flat_tree& operator=(BOOST_RV_REF(flat_tree) x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { m_data = boost::move(x.m_data); return *this; } public: @@ -329,6 +332,8 @@ class flat_tree { return this->m_data.m_vect.max_size(); } void swap(flat_tree& other) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ) { this->m_data.swap(other.m_data); } public: diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index d9e49ca..e7a0940 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -471,16 +471,18 @@ class tree > { typedef tree_value_compare - ValComp; + ValComp; typedef typename container_detail::intrusive_tree_type < Allocator, ValComp, Options::tree_type , Options::optimize_size>::type Icont; typedef container_detail::node_alloc_holder - AllocHolder; + AllocHolder; typedef typename AllocHolder::NodePtr NodePtr; typedef tree < Key, T, KeyOfValue - , Compare, Allocator, Options> ThisType; + , Compare, Allocator, Options> ThisType; typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef boost::container:: + allocator_traits allocator_traits_type; typedef typename AllocHolder::ValAlloc ValAlloc; typedef typename AllocHolder::Node Node; typedef typename Icont::iterator iiterator; @@ -494,22 +496,22 @@ class tree public: typedef Key key_type; - typedef T value_type; - typedef Allocator allocator_type; - typedef Compare key_compare; + typedef T value_type; + typedef Allocator allocator_type; + typedef Compare key_compare; typedef ValComp value_compare; typedef typename boost::container:: - allocator_traits::pointer pointer; + allocator_traits::pointer pointer; typedef typename boost::container:: - allocator_traits::const_pointer const_pointer; + allocator_traits::const_pointer const_pointer; typedef typename boost::container:: - allocator_traits::reference reference; + allocator_traits::reference reference; typedef typename boost::container:: - allocator_traits::const_reference const_reference; + allocator_traits::const_reference const_reference; typedef typename boost::container:: - allocator_traits::size_type size_type; + allocator_traits::size_type size_type; typedef typename boost::container:: - allocator_traits::difference_type difference_type; + allocator_traits::difference_type difference_type; typedef difference_type tree_difference_type; typedef pointer tree_pointer; typedef const_pointer tree_const_pointer; @@ -696,6 +698,8 @@ class tree } tree& operator=(BOOST_RV_REF(tree) x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { BOOST_ASSERT(this != &x); NodeAlloc &this_alloc = this->node_alloc(); @@ -820,6 +824,8 @@ class tree { return AllocHolder::max_size(); } void swap(ThisType& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ) { AllocHolder::swap(x); } public: diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp index 86b640c..55cccd2 100644 --- a/include/boost/container/detail/type_traits.hpp +++ b/include/boost/container/detail/type_traits.hpp @@ -50,6 +50,7 @@ using ::boost::move_detail::is_nothrow_copy_constructible; using ::boost::move_detail::is_nothrow_move_constructible; using ::boost::move_detail::is_nothrow_copy_assignable; using ::boost::move_detail::is_nothrow_move_assignable; +using ::boost::move_detail::is_nothrow_swappable; using ::boost::move_detail::alignment_of; using ::boost::move_detail::aligned_storage; using ::boost::move_detail::nat; diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index d7b2f41..c54ba59 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -330,7 +330,8 @@ class flat_map //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. flat_map& operator=(BOOST_RV_REF(flat_map) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { m_flat_tree = boost::move(x.m_flat_tree); return *this; } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -877,6 +878,8 @@ class flat_map //! //! Complexity: Constant. void swap(flat_map& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ) { m_flat_tree.swap(x.m_flat_tree); } //! Effects: erase(a.begin(),a.end()). @@ -1314,7 +1317,8 @@ class flat_multimap //! //! Complexity: Constant. flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { m_flat_tree = boost::move(x.m_flat_tree); return *this; } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1780,6 +1784,8 @@ class flat_multimap //! //! Complexity: Constant. void swap(flat_multimap& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ) { m_flat_tree.swap(x.m_flat_tree); } //! Effects: erase(a.begin(),a.end()). diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 993b4fa..6004058 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -232,7 +232,8 @@ class flat_set //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. flat_set& operator=(BOOST_RV_REF(flat_set) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { return static_cast(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -619,7 +620,9 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - void swap(flat_set& x); + void swap(flat_set& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ); //! Effects: erase(a.begin(),a.end()). //! @@ -956,7 +959,8 @@ class flat_multiset //! @copydoc ::boost::container::flat_set::operator=(flat_set &&) flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { return static_cast(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1198,7 +1202,9 @@ class flat_multiset iterator erase(const_iterator first, const_iterator last); //! @copydoc ::boost::container::flat_set::swap - void swap(flat_multiset& x); + void swap(flat_multiset& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ); //! @copydoc ::boost::container::flat_set::clear void clear() BOOST_CONTAINER_NOEXCEPT; diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 2d45032..2bd5e94 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -339,7 +339,8 @@ class list //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. list& operator=(BOOST_RV_REF(list) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { BOOST_ASSERT(this != &x); NodeAlloc &this_alloc = this->node_alloc(); @@ -931,6 +932,8 @@ class list //! //! Complexity: Constant. void swap(list& x) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { AllocHolder::swap(x); } //! Effects: Erases all the elements of the list. diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index c44f858..3df1df5 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -99,7 +99,7 @@ class map ////////////////////////////////////////////// typedef Key key_type; - typedef ::boost::container::allocator_traits allocator_traits_type; + typedef ::boost::container::allocator_traits allocator_traits_type; typedef T mapped_type; typedef std::pair value_type; typedef typename boost::container::allocator_traits::pointer pointer; @@ -272,7 +272,9 @@ class map //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. map& operator=(BOOST_RV_REF(map) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) + { return static_cast(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -680,7 +682,9 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - void swap(map& x); + void swap(map& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ) //! Effects: erase(a.begin(),a.end()). //! @@ -894,6 +898,8 @@ class multimap > value_compare_impl; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef ::boost::container::allocator_traits allocator_traits_type; + public: ////////////////////////////////////////////// // @@ -1065,6 +1071,8 @@ class multimap //! //! Complexity: Constant. multimap& operator=(BOOST_RV_REF(multimap) x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { return static_cast(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1281,7 +1289,9 @@ class multimap iterator erase(const_iterator first, const_iterator last); //! @copydoc ::boost::container::set::swap - void swap(flat_multiset& x); + void swap(multiset& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ); //! @copydoc ::boost::container::set::clear void clear() BOOST_CONTAINER_NOEXCEPT; diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index bf77031..8160530 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -224,7 +224,8 @@ class set //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. set& operator=(BOOST_RV_REF(set) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { return static_cast(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -522,7 +523,9 @@ class set //! Throws: Nothing. //! //! Complexity: Constant. - void swap(set& x); + void swap(set& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ); //! Effects: erase(a.begin(),a.end()). //! @@ -835,6 +838,8 @@ class multiset //! @copydoc ::boost::container::set::operator=(set &&) multiset& operator=(BOOST_RV_REF(multiset) x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable::value ) { return static_cast(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1013,7 +1018,9 @@ class multiset iterator erase(const_iterator first, const_iterator last); //! @copydoc ::boost::container::set::swap - void swap(flat_multiset& x); + void swap(multiset& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable::value ); //! @copydoc ::boost::container::set::clear void clear() BOOST_CONTAINER_NOEXCEPT; diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 681adc7..fb24bc9 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -358,7 +358,8 @@ class slist //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. slist& operator= (BOOST_RV_REF(slist) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { BOOST_ASSERT(this != &x); NodeAlloc &this_alloc = this->node_alloc(); @@ -916,6 +917,8 @@ class slist //! //! Complexity: Linear to the number of elements on *this and x. void swap(slist& x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { AllocHolder::swap(x); } //! Effects: Erases all the elements of the list. diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 63812dc..8cda00c 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -751,7 +751,8 @@ class stable_vector //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. stable_vector& operator=(BOOST_RV_REF(stable_vector) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { //for move constructor, no aliasing (&x != this) is assummed. BOOST_ASSERT(this != &x); @@ -1598,6 +1599,8 @@ class stable_vector //! //! Complexity: Constant. void swap(stable_vector & x) + BOOST_CONTAINER_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { STABLE_VECTOR_CHECK_INVARIANT; container_detail::bool_ flag; diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index e58d078..c2edf44 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -751,7 +751,8 @@ class basic_string //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. basic_string& operator=(BOOST_RV_REF(basic_string) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { //for move constructor, no aliasing (&x != this) is assummed. BOOST_ASSERT(this != &x); @@ -1892,6 +1893,8 @@ class basic_string //! //! Throws: Nothing void swap(basic_string& x) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { this->base_t::swap_data(x); container_detail::bool_ flag; diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 3be380c..d207a57 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -896,7 +896,8 @@ class vector //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. vector& operator=(BOOST_RV_REF(vector) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { this->priv_move_assign(boost::move(x)); return *this; @@ -1784,7 +1785,10 @@ class vector //! Throws: Nothing. //! //! Complexity: Constant. - void swap(vector& x) BOOST_CONTAINER_NOEXCEPT_IF((!container_detail::is_version::value)) + void swap(vector& x) + BOOST_CONTAINER_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) && + !container_detail::is_version::value)) { //Just swap internals in case of !version_0. Otherwise, deep swap this->m_holder.swap(x.m_holder);