Add new clone_from overload to implement move semantics

This commit is contained in:
Ion Gaztañaga
2015-02-26 00:02:24 +01:00
parent b5fd69e628
commit 4f20e7279d
6 changed files with 52 additions and 10 deletions

View File

@@ -945,8 +945,8 @@ class bstree_impl
detail::exception_disposer<bstree_impl, 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, value_traits, AlgoType>(cloner, &this->get_value_traits())
,detail::node_disposer<Disposer, value_traits, AlgoType>(disposer, &this->get_value_traits()));
this->sz_traits().set_size(src.sz_traits().get_size());
@@ -955,6 +955,41 @@ class bstree_impl
}
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: 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).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
//! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
//!
//! <b>Note</b>: This version can modify the source container, useful to implement
//! move semantics.
template <class Cloner, class Disposer>
void clone_from(bstree_impl &src, Cloner cloner, Disposer disposer)
{
this->clear_and_dispose(disposer);
if(!src.empty()){
detail::exception_disposer<bstree_impl, Disposer>
rollback(*this, disposer);
node_algorithms::clone
(src.header_ptr()
,this->header_ptr()
,detail::node_cloner <Cloner, value_traits, AlgoType, false>(cloner, &this->get_value_traits())
,detail::node_disposer<Disposer, value_traits, AlgoType>(disposer, &this->get_value_traits()));
this->sz_traits().set_size(src.sz_traits().get_size());
this->comp() = src.comp();
rollback.release();
}
}
//! <b>Requires</b>: value must be an lvalue
//!
//! <b>Effects</b>: Inserts value into the container before the upper bound.

View File

@@ -1285,7 +1285,7 @@ class bstree_algorithms : public bstree_algorithms_base<NodeTraits>
//! the nodes of the target tree. If "cloner" throws, the cloned target nodes
//! are disposed using <tt>void disposer(const node_ptr &)</tt>.
//!
//! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
//! <b>Complexity</b>: Linear to the number of element of the source tree plus the
//! number of elements of tree target tree when calling this function.
//!
//! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.

View File

@@ -183,7 +183,7 @@ class ebo_functor_holder_impl<T, false>
public:
ebo_functor_holder_impl()
{}
ebo_functor_holder_impl(const T& t)
explicit ebo_functor_holder_impl(const T& t)
: T(t)
{}
template<class Arg1, class Arg2>
@@ -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)
{}

View File

@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
#include <boost/intrusive/detail/assert.hpp>
@@ -30,7 +31,7 @@ namespace boost {
namespace intrusive {
namespace detail {
template<class F, class ValueTraits, algo_types AlgoType>
template<class F, class ValueTraits, algo_types AlgoType, bool IsConst = true>
struct node_cloner
//Use public inheritance to avoid MSVC bugs with closures
: public ebo_functor_holder<F>
@@ -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<IsConst, const_reference, reference>::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<const_node_ptr>::pointer_to(to_clone));
node_ptr n = traits_->to_node_ptr(*base_t::get()(v));

View File

@@ -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 <class Cloner, class Disposer>
void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::clone_from(bstree &src, cloner, Disposer)
template <class Cloner, class Disposer>
void clone_from(rbtree_impl &src, Cloner cloner, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::insert_equal(reference)
iterator insert_equal(reference value);

View File

@@ -50,7 +50,7 @@ struct rbtree_node_cloner
typedef typename NodeTraits::node_ptr node_ptr;
typedef detail::ebo_functor_holder<F> base_t;
rbtree_node_cloner(F f)
explicit rbtree_node_cloner(F f)
: base_t(f)
{}