From 4f20e7279d0cf3632b8fdfd66db57806ce821314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 26 Feb 2015 00:02:24 +0100 Subject: [PATCH] Add new clone_from overload to implement move semantics --- include/boost/intrusive/bstree.hpp | 39 ++++++++++++++++++- include/boost/intrusive/bstree_algorithms.hpp | 2 +- .../intrusive/detail/ebo_functor_holder.hpp | 4 +- .../intrusive/detail/node_cloner_disposer.hpp | 9 +++-- include/boost/intrusive/rbtree.hpp | 6 ++- include/boost/intrusive/rbtree_algorithms.hpp | 2 +- 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 8659cd4..39c9d3e 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -945,8 +945,8 @@ class bstree_impl detail::exception_disposer rollback(*this, disposer); node_algorithms::clone - (const_node_ptr(src.header_ptr()) - ,node_ptr(this->header_ptr()) + (src.header_ptr() + ,this->header_ptr() ,detail::node_cloner (cloner, &this->get_value_traits()) ,detail::node_disposer(disposer, &this->get_value_traits())); this->sz_traits().set_size(src.sz_traits().get_size()); @@ -955,6 +955,41 @@ class bstree_impl } } + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! Cloner should yield to nodes equivalent to the original nodes. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. Copies the predicate from the source container. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! + //! Note: This version can modify the source container, useful to implement + //! move semantics. + template + void clone_from(bstree_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!src.empty()){ + detail::exception_disposer + rollback(*this, disposer); + node_algorithms::clone + (src.header_ptr() + ,this->header_ptr() + ,detail::node_cloner (cloner, &this->get_value_traits()) + ,detail::node_disposer(disposer, &this->get_value_traits())); + this->sz_traits().set_size(src.sz_traits().get_size()); + this->comp() = src.comp(); + rollback.release(); + } + } + //! Requires: value must be an lvalue //! //! Effects: Inserts value into the container before the upper bound. diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 4e72e5d..f7e915e 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -1285,7 +1285,7 @@ class bstree_algorithms : public bstree_algorithms_base //! the nodes of the target tree. If "cloner" throws, the cloned target nodes //! are disposed using void disposer(const node_ptr &). //! - //! Complexity: Linear to the number of element of the source tree plus the. + //! Complexity: Linear to the number of element of the source tree plus the //! number of elements of tree target tree when calling this function. //! //! Throws: If cloner functor throws. If this happens target nodes are disposed. diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index b2c5908..e8e73ff 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -183,7 +183,7 @@ class ebo_functor_holder_impl public: ebo_functor_holder_impl() {} - ebo_functor_holder_impl(const T& t) + explicit ebo_functor_holder_impl(const T& t) : T(t) {} template @@ -204,7 +204,7 @@ class ebo_functor_holder public: ebo_functor_holder(){} - ebo_functor_holder(const T& t) + explicit ebo_functor_holder(const T& t) : super(t) {} diff --git a/include/boost/intrusive/detail/node_cloner_disposer.hpp b/include/boost/intrusive/detail/node_cloner_disposer.hpp index 48c7c93..65af3e3 100644 --- a/include/boost/intrusive/detail/node_cloner_disposer.hpp +++ b/include/boost/intrusive/detail/node_cloner_disposer.hpp @@ -22,6 +22,7 @@ #endif #include +#include #include #include #include @@ -30,7 +31,7 @@ namespace boost { namespace intrusive { namespace detail { -template +template struct node_cloner //Use public inheritance to avoid MSVC bugs with closures : public ebo_functor_holder @@ -50,6 +51,8 @@ struct node_cloner typedef typename value_traits::reference reference; typedef typename value_traits::const_reference const_reference; + typedef typename if_c::type reference_type; + node_cloner(F f, const ValueTraits *traits) : base_t(f), traits_(traits) {} @@ -57,7 +60,7 @@ struct node_cloner // tree-based containers use this method, which is proxy-reference friendly node_ptr operator()(const node_ptr & p) { - const_reference v = *traits_->to_value_ptr(p); + reference_type v = *traits_->to_value_ptr(p); node_ptr n = traits_->to_node_ptr(*base_t::get()(v)); //Cloned node must be in default mode if the linking mode requires it if(safemode_or_autounlink) @@ -68,7 +71,7 @@ struct node_cloner // hashtables use this method, which is proxy-reference unfriendly node_ptr operator()(const node &to_clone) { - const value_type &v = + reference_type v = *traits_->to_value_ptr (pointer_traits::pointer_to(to_clone)); node_ptr n = traits_->to_node_ptr(*base_t::get()(v)); diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 892390b..4ef50b4 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -213,10 +213,14 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::swap void swap(rbtree_impl& other); - //! @copydoc ::boost::intrusive::bstree::clone_from + //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree &src, cloner, Disposer) template void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::clone_from(bstree &src, cloner, Disposer) + template + void clone_from(rbtree_impl &src, Cloner cloner, Disposer disposer); + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value); diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 7714982..ad9c765 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -50,7 +50,7 @@ struct rbtree_node_cloner typedef typename NodeTraits::node_ptr node_ptr; typedef detail::ebo_functor_holder base_t; - rbtree_node_cloner(F f) + explicit rbtree_node_cloner(F f) : base_t(f) {}