Introducing allocator_traits and pointer_traits changes into several libraries.

[SVN r76106]
This commit is contained in:
Ion Gaztañaga
2011-12-22 20:08:24 +00:00
parent 5247083184
commit 935a534713
41 changed files with 4304 additions and 2448 deletions
+292 -175
View File
@@ -27,15 +27,14 @@
#include <boost/container/container_fwd.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/get_pointer.hpp>
#include <boost/container/allocator/allocator_traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <algorithm>
#include <stdexcept>
@@ -79,7 +78,7 @@ struct smart_ptr_type<T*>
};
template<class Ptr>
inline typename smart_ptr_type<Ptr>::pointer get_pointer(const Ptr &ptr)
inline typename smart_ptr_type<Ptr>::pointer to_raw_pointer(const Ptr &ptr)
{ return smart_ptr_type<Ptr>::get(ptr); }
template <class C>
@@ -126,33 +125,29 @@ template<typename VoidPointer, typename T>
struct node_type
: public node_type_base<VoidPointer>
{
#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
node_type()
: value()
{}
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<class ...Args>
node_type(Args &&...args)
: value(boost::forward<Args>(args)...)
{}
#else //BOOST_CONTAINERS_PERFECT_FORWARDING
#else //BOOST_CONTAINER_PERFECT_FORWARDING
node_type()
: value()
{}
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
node_type(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
: value(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
{} \
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
node_type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
: value(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif//BOOST_CONTAINERS_PERFECT_FORWARDING
#endif//BOOST_CONTAINER_PERFECT_FORWARDING
void set_pointer(VoidPointer p)
{ node_type_base<VoidPointer>::set_pointer(p); }
@@ -163,33 +158,38 @@ struct node_type
template<typename T, typename Reference, typename Pointer>
class iterator
: public std::iterator< std::random_access_iterator_tag
, typename std::iterator_traits<Pointer>::value_type
, typename std::iterator_traits<Pointer>::difference_type
, T
, typename boost::intrusive::
pointer_traits<Pointer>::difference_type
, Pointer
, Reference>
{
typedef typename boost::intrusive::
pointer_traits<Pointer>::template
rebind_pointer<void>::type void_ptr;
typedef typename boost::intrusive::
pointer_traits<Pointer>::template
rebind_pointer<const void>::type const_void_ptr;
typedef node_type<void_ptr, T> node_type_t;
typedef typename boost::intrusive::
pointer_traits<Pointer>::template
rebind_pointer<node_type_t>::type node_type_ptr_t;
typedef typename boost::intrusive::
pointer_traits<Pointer>::template
rebind_pointer<const node_type_t>::type const_node_type_ptr_t;
typedef typename boost::intrusive::
pointer_traits<Pointer>::template
rebind_pointer<void_ptr>::type void_ptr_ptr;
typedef typename boost::pointer_to_other
<Pointer, void>::type void_ptr;
typedef typename boost::pointer_to_other
<Pointer, const void>::type const_void_ptr;
typedef node_type<void_ptr, T> node_type_t;
typedef typename boost::pointer_to_other
<void_ptr, node_type_t>::type node_type_ptr_t;
typedef typename boost::pointer_to_other
<void_ptr, const node_type_t>::type const_node_type_ptr_t;
typedef typename boost::pointer_to_other
<void_ptr, void_ptr>::type void_ptr_ptr;
friend class iterator<T, const T, typename boost::pointer_to_other<Pointer, T>::type>;
friend class iterator<T, const T, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::type>;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef typename std::iterator_traits
<Pointer>::difference_type difference_type;
typedef Pointer pointer;
typedef Reference reference;
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef typename boost::intrusive::
pointer_traits<Pointer>::difference_type difference_type;
typedef Pointer pointer;
typedef Reference reference;
iterator()
{}
@@ -198,27 +198,24 @@ class iterator
: pn(pn)
{}
iterator(const iterator<T, T&, typename boost::pointer_to_other<Pointer, T>::type >& x)
iterator(const iterator<T, T&, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::type>& x)
: pn(x.pn)
{}
private:
static node_type_ptr_t node_ptr_cast(const void_ptr &p)
{
using boost::get_pointer;
return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::get_pointer(p)));
return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::to_raw_pointer(p)));
}
static const_node_type_ptr_t node_ptr_cast(const const_void_ptr &p)
{
using boost::get_pointer;
return const_node_type_ptr_t(static_cast<const node_type_t*>(stable_vector_detail::get_pointer(p)));
return const_node_type_ptr_t(static_cast<const node_type_t*>(stable_vector_detail::to_raw_pointer(p)));
}
static void_ptr_ptr void_ptr_ptr_cast(const void_ptr &p)
{
using boost::get_pointer;
return void_ptr_ptr(static_cast<void_ptr*>(stable_vector_detail::get_pointer(p)));
return void_ptr_ptr(static_cast<void_ptr*>(stable_vector_detail::to_raw_pointer(p)));
}
reference dereference() const
@@ -325,12 +322,15 @@ struct select_multiallocation_chain
template<class A>
struct select_multiallocation_chain<A, 1>
{
typedef typename A::template
rebind<void>::other::pointer void_ptr;
typedef containers_detail::basic_multiallocation_chain
typedef typename boost::intrusive::pointer_traits
<typename allocator_traits<A>::pointer>::
template rebind_pointer<void>::type void_ptr;
typedef container_detail::basic_multiallocation_chain
<void_ptr> multialloc_cached_counted;
typedef boost::container::containers_detail::transform_multiallocation_chain
<multialloc_cached_counted, typename A::value_type> type;
typedef boost::container::container_detail::
transform_multiallocation_chain
< multialloc_cached_counted
, typename allocator_traits<A>::value_type> type;
};
} //namespace stable_vector_detail
@@ -389,59 +389,82 @@ template <class T, class A>
class stable_vector
{
///@cond
typedef typename containers_detail::
move_const_ref_type<T>::type insert_const_ref_type;
typedef typename A::template
rebind<void>::other::pointer void_ptr;
typedef typename boost::pointer_to_other
<void_ptr, const void>::type const_void_ptr;
typedef typename A::template
rebind<void_ptr>::other::pointer void_ptr_ptr;
typedef typename boost::pointer_to_other
<void_ptr, const void_ptr>::type const_void_ptr_ptr;
typedef allocator_traits<A> allocator_traits_type;
typedef typename container_detail::
move_const_ref_type<T>::type insert_const_ref_type;
typedef typename boost::intrusive::pointer_traits
<typename allocator_traits_type::pointer>::
template rebind_pointer<void>::type void_ptr;
typedef typename boost::intrusive::pointer_traits
<void_ptr>::template
rebind_pointer<const void>::type const_void_ptr;
typedef typename boost::intrusive::pointer_traits
<void_ptr>::template
rebind_pointer<void_ptr>::type void_ptr_ptr;
typedef typename boost::intrusive::pointer_traits
<void_ptr>::template
rebind_pointer<const void_ptr>::type const_void_ptr_ptr;
typedef stable_vector_detail::node_type
<void_ptr, T> node_type_t;
typedef typename A::template
rebind<node_type_t>::other::pointer node_type_ptr_t;
typedef typename boost::intrusive::pointer_traits
<void_ptr>::template
rebind_pointer<node_type_t>::type node_type_ptr_t;
typedef stable_vector_detail::node_type_base
<void_ptr> node_type_base_t;
typedef typename A::template
rebind<node_type_base_t>::other::pointer node_type_base_ptr_t;
typedef
::boost::container::vector<void_ptr,
typename A::
template rebind<void_ptr>::other
> impl_type;
typedef typename boost::intrusive::pointer_traits
<void_ptr>::template
rebind_pointer<node_type_base_t>::type node_type_base_ptr_t;
typedef ::boost::container::vector<void_ptr,
typename allocator_traits_type::
template portable_rebind_alloc
<void_ptr>::type> impl_type;
typedef typename impl_type::iterator impl_iterator;
typedef typename impl_type::const_iterator const_impl_iterator;
typedef ::boost::container::containers_detail::
typedef ::boost::container::container_detail::
integral_constant<unsigned, 1> allocator_v1;
typedef ::boost::container::containers_detail::
typedef ::boost::container::container_detail::
integral_constant<unsigned, 2> allocator_v2;
typedef ::boost::container::containers_detail::integral_constant
<unsigned, boost::container::containers_detail::
version<A>::value> alloc_version;
typedef typename A::
template rebind<node_type_t>::other node_allocator_type;
typedef ::boost::container::container_detail::integral_constant
<unsigned, boost::container::container_detail::
version<A>::value> alloc_version;
typedef typename allocator_traits_type::
template portable_rebind_alloc
<node_type_t>::type node_allocator_type;
node_type_ptr_t allocate_one()
{ return this->allocate_one(alloc_version()); }
node_type_ptr_t allocate_one(allocator_v1)
{ return get_al().allocate(1); }
template<class AllocatorVersion>
node_type_ptr_t allocate_one(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{ return node_alloc().allocate(1); }
node_type_ptr_t allocate_one(allocator_v2)
{ return get_al().allocate_one(); }
template<class AllocatorVersion>
node_type_ptr_t allocate_one(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v2>
::value>::type * = 0)
{ return node_alloc().allocate_one(); }
void deallocate_one(node_type_ptr_t p)
{ return this->deallocate_one(p, alloc_version()); }
void deallocate_one(node_type_ptr_t p, allocator_v1)
{ get_al().deallocate(p, 1); }
template<class AllocatorVersion>
void deallocate_one(node_type_ptr_t p, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{ node_alloc().deallocate(p, 1); }
void deallocate_one(node_type_ptr_t p, allocator_v2)
{ get_al().deallocate_one(p); }
template<class AllocatorVersion>
void deallocate_one(node_type_ptr_t p, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v2>
::value>::type * = 0)
{ node_alloc().deallocate_one(p); }
friend class stable_vector_detail::clear_on_destroy<stable_vector>;
///@endcond
@@ -450,10 +473,10 @@ class stable_vector
// types:
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename allocator_traits_type::reference reference;
typedef typename allocator_traits_type::const_reference const_reference;
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::const_pointer const_pointer;
typedef stable_vector_detail::iterator
<T,T&, pointer> iterator;
typedef stable_vector_detail::iterator
@@ -461,9 +484,10 @@ class stable_vector
typedef typename impl_type::size_type size_type;
typedef typename iterator::difference_type difference_type;
typedef T value_type;
typedef A allocator_type;
typedef A allocator_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef node_allocator_type stored_allocator_type;
///@cond
private:
@@ -483,13 +507,24 @@ class stable_vector
///@endcond
public:
//! <b>Effects</b>: Default constructs a stable_vector.
//!
//! <b>Throws</b>: If allocator_type's default constructor throws.
//!
//! <b>Complexity</b>: Constant.
stable_vector()
: internal_data(), impl()
{
STABLE_VECTOR_CHECK_INVARIANT;
}
//! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
explicit stable_vector(const A& al=A())
: internal_data(al),impl(al)
explicit stable_vector(const A& al)
: internal_data(al),impl(al)
{
STABLE_VECTOR_CHECK_INVARIANT;
}
@@ -502,7 +537,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
explicit stable_vector(size_type n)
: internal_data(A()),impl(A())
: internal_data(A()),impl(A())
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->resize(n);
@@ -518,7 +553,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
stable_vector(size_type n, const T& t, const A& al=A())
: internal_data(al),impl(al)
: internal_data(al),impl(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), n, t);
@@ -549,7 +584,10 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to the elements x contains.
stable_vector(const stable_vector& x)
: internal_data(x.get_al()),impl(x.get_al())
: internal_data(allocator_traits<node_allocator_type>::
select_on_container_copy_construction(x.node_alloc()))
, impl(allocator_traits<allocator_type>::
select_on_container_copy_construction(x.impl.get_stored_allocator()))
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), x.begin(), x.end());
@@ -562,9 +600,11 @@ class stable_vector
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
stable_vector(BOOST_RV_REF(stable_vector) x)
: internal_data(x.get_al()),impl(x.get_al())
{ this->swap(x); }
stable_vector(BOOST_RV_REF(stable_vector) x)
: internal_data(boost::move(x.node_alloc())), impl(boost::move(x.impl))
{
this->priv_swap_members(x);
}
//! <b>Effects</b>: Destroys the stable_vector. All stored values are destroyed
//! and used memory is deallocated.
@@ -589,7 +629,17 @@ class stable_vector
stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
{
STABLE_VECTOR_CHECK_INVARIANT;
if (this != &x) {
if (&x != this){
node_allocator_type &this_alloc = this->node_alloc();
const node_allocator_type &x_alloc = x.node_alloc();
container_detail::bool_<allocator_traits_type::
propagate_on_container_copy_assignment::value> flag;
if(flag && this_alloc != x_alloc){
this->clear();
this->shrink_to_fit();
}
container_detail::assign_alloc(this->node_alloc(), x.node_alloc(), flag);
container_detail::assign_alloc(this->impl.get_stored_allocator(), x.impl.get_stored_allocator(), flag);
this->assign(x.begin(), x.end());
}
return *this;
@@ -606,8 +656,25 @@ class stable_vector
stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
{
if (&x != this){
this->swap(x);
x.clear();
node_allocator_type &this_alloc = this->node_alloc();
node_allocator_type &x_alloc = x.node_alloc();
//If allocators are equal we can just swap pointers
if(this_alloc == x_alloc){
//Destroy objects but retain memory
this->clear();
this->impl = boost::move(x.impl);
this->priv_swap_members(x);
//Move allocator if needed
container_detail::bool_<allocator_traits_type::
propagate_on_container_move_assignment::value> flag;
container_detail::move_alloc(this->node_alloc(), x.node_alloc(), flag);
}
//If unequal allocators, then do a one by one move
else{
typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
this->assign( boost::make_move_iterator(x.begin())
, boost::make_move_iterator(x.end()));
}
}
return *this;
}
@@ -641,7 +708,27 @@ class stable_vector
//! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator()const {return get_al();}
allocator_type get_allocator()const {return node_alloc();}
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return node_alloc(); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
@@ -946,7 +1033,8 @@ class stable_vector
void push_back(T &x) { push_back(const_cast<const T &>(x)); }
template<class U>
void push_back(const U &u, typename containers_detail::enable_if_c<containers_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
void push_back(const U &u, typename container_detail::enable_if_c
<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
{ return priv_push_back(u); }
#endif
@@ -982,7 +1070,8 @@ class stable_vector
iterator insert(const_iterator position, T &x) { return this->insert(position, const_cast<const T &>(x)); }
template<class U>
iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c<containers_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c
<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
{ return this->priv_insert(position, u); }
#endif
@@ -1035,7 +1124,7 @@ class stable_vector
boost::mpl::not_<boost::is_integral<InputIterator> >());
}
#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
//! std::forward<Args>(args)... in the end of the stable_vector.
@@ -1046,7 +1135,7 @@ class stable_vector
template<class ...Args>
void emplace_back(Args &&...args)
{
typedef emplace_functor<node_type_t, Args...> EmplaceFunctor;
typedef emplace_functor<Args...> EmplaceFunctor;
typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator;
EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
@@ -1066,7 +1155,7 @@ class stable_vector
{
//Just call more general insert(pos, size, value) and return iterator
size_type pos_n = position - cbegin();
typedef emplace_functor<node_type_t, Args...> EmplaceFunctor;
typedef emplace_functor<Args...> EmplaceFunctor;
typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator;
EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
this->insert(position, EmplaceIterator(ef), EmplaceIterator());
@@ -1075,51 +1164,40 @@ class stable_vector
#else
void emplace_back()
{
typedef emplace_functor<node_type_t> EmplaceFunctor;
typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator;
EmplaceFunctor ef;
this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
}
iterator emplace(const_iterator position)
{
typedef emplace_functor<node_type_t> EmplaceFunctor;
typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator;
EmplaceFunctor ef;
size_type pos_n = position - this->cbegin();
this->insert(position, EmplaceIterator(ef), EmplaceIterator());
return iterator(this->begin() + pos_n);
}
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
<node_type_t, BOOST_PP_ENUM_PARAMS(n, P)> EmplaceFunctor; \
BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
EmplaceFunctor; \
typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator; \
EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator()); \
EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
BOOST_PP_RPAREN_IF(n); \
this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator()); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace(const_iterator pos \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
<node_type_t, BOOST_PP_ENUM_PARAMS(n, P)> EmplaceFunctor; \
BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
EmplaceFunctor; \
typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator; \
EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
BOOST_PP_RPAREN_IF(n); \
size_type pos_n = pos - this->cbegin(); \
this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
return iterator(this->begin() + pos_n); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//! <b>Effects</b>: Erases the element at position pos.
//!
@@ -1157,7 +1235,11 @@ class stable_vector
void swap(stable_vector & x)
{
STABLE_VECTOR_CHECK_INVARIANT;
this->swap_impl(*this,x);
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
//vector's allocator is swapped here
this->impl.swap(x.impl);
this->priv_swap_members(x);
}
//! <b>Effects</b>: Erases all the elements of the stable_vector.
@@ -1181,7 +1263,8 @@ class stable_vector
this->clear_pool();
//If empty completely destroy the index, let's recover default-constructed state
if(this->empty()){
impl_type().swap(this->impl);
this->impl.clear();
this->impl.shrink_to_fit();
this->internal_data.set_end_pointer_to_default_constructed();
}
//Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
@@ -1209,7 +1292,11 @@ class stable_vector
void priv_push_back(const value_type &t)
{ this->insert(end(), t); }
void clear_pool(allocator_v1)
template<class AllocatorVersion>
void clear_pool(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{
if(!impl.empty() && impl.back()){
void_ptr &pool_first_ref = impl.end()[-2];
@@ -1227,15 +1314,18 @@ class stable_vector
}
}
void clear_pool(allocator_v2)
template<class AllocatorVersion>
void clear_pool(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v2>
::value>::type * = 0)
{
if(!impl.empty() && impl.back()){
void_ptr &pool_first_ref = impl.end()[-2];
void_ptr &pool_last_ref = impl.back();
multiallocation_chain holder;
holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
get_al().deallocate_individual(boost::move(holder));
node_alloc().deallocate_individual(boost::move(holder));
pool_first_ref = pool_last_ref = 0;
this->internal_data.pool_size = 0;
}
@@ -1251,7 +1341,11 @@ class stable_vector
this->add_to_pool(n, alloc_version());
}
void add_to_pool(size_type n, allocator_v1)
template<class AllocatorVersion>
void add_to_pool(size_type n, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{
size_type remaining = n;
while(remaining--){
@@ -1259,14 +1353,18 @@ class stable_vector
}
}
void add_to_pool(size_type n, allocator_v2)
template<class AllocatorVersion>
void add_to_pool(size_type n, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v2>
::value>::type * = 0)
{
void_ptr &pool_first_ref = impl.end()[-2];
void_ptr &pool_last_ref = impl.back();
multiallocation_chain holder;
holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<multiallocation_chain>::value == true));
multiallocation_chain m (get_al().allocate_individual(n));
multiallocation_chain m (node_alloc().allocate_individual(n));
holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
this->internal_data.pool_size += n;
std::pair<void_ptr, void_ptr> data(holder.extract_data());
@@ -1375,8 +1473,8 @@ class stable_vector
template<class AllocatorVersion>
iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion,
typename boost::container::containers_detail::enable_if_c
<boost::container::containers_detail::is_same<AllocatorVersion, allocator_v2>
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v2>
::value>::type * = 0)
{
STABLE_VECTOR_CHECK_INVARIANT;
@@ -1385,14 +1483,12 @@ class stable_vector
static node_type_ptr_t node_ptr_cast(const void_ptr &p)
{
using boost::get_pointer;
return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::get_pointer(p)));
return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::to_raw_pointer(p)));
}
static node_type_base_ptr_t node_base_ptr_cast(const void_ptr &p)
{
using boost::get_pointer;
return node_type_base_ptr_t(static_cast<node_type_base_t*>(stable_vector_detail::get_pointer(p)));
return node_type_base_ptr_t(static_cast<node_type_base_t*>(stable_vector_detail::to_raw_pointer(p)));
}
static value_type& value(const void_ptr &p)
@@ -1434,7 +1530,7 @@ class stable_vector
{
node_type_ptr_t p = this->allocate_one();
try{
boost::container::construct_in_place(&*p, it);
boost::container::construct_in_place(this->node_alloc(), &*p, it);
p->set_pointer(up);
}
catch(...){
@@ -1516,7 +1612,7 @@ class stable_vector
template <class FwdIterator>
void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
{
multiallocation_chain mem(get_al().allocate_individual(n));
multiallocation_chain mem(node_alloc().allocate_individual(n));
size_type i = 0;
node_type_ptr_t p = 0;
@@ -1525,7 +1621,7 @@ class stable_vector
p = mem.front();
mem.pop_front();
//This can throw
boost::container::construct_in_place(&*p, first);
boost::container::construct_in_place(this->node_alloc(), &*p, first);
p->set_pointer(void_ptr_ptr(&it[i]));
++first;
it[i] = p;
@@ -1533,8 +1629,8 @@ class stable_vector
}
}
catch(...){
get_al().deallocate_one(p);
get_al().deallocate_many(boost::move(mem));
node_alloc().deallocate_one(p);
node_alloc().deallocate_many(boost::move(mem));
impl_iterator e = impl.erase(it+i, it+n);
this->align_nodes(e, get_last_align());
throw;
@@ -1548,13 +1644,13 @@ class stable_vector
node_type_ptr_t p = 0;
try{
while(first != last){
p = get_from_pool();
p = this->get_from_pool();
if(!p){
insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
break;
}
//This can throw
boost::container::construct_in_place(&*p, first);
boost::container::construct_in_place(this->node_alloc(), &*p, first);
p->set_pointer(void_ptr_ptr(&it[i]));
++first;
it[i]=p;
@@ -1575,16 +1671,6 @@ class stable_vector
this->insert_not_iter(position, first, last);
}
static void swap_impl(stable_vector& x,stable_vector& y)
{
using std::swap;
swap(x.get_al(),y.get_al());
swap(x.impl,y.impl);
swap(x.internal_data.pool_size, y.internal_data.pool_size);
x.readjust_end_node();
y.readjust_end_node();
}
#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
bool invariant()const
{
@@ -1609,9 +1695,12 @@ class stable_vector
return n >= num_pool;
}
class invariant_checker:private boost::noncopyable
class invariant_checker
{
invariant_checker(const invariant_checker &);
invariant_checker & operator=(const invariant_checker &);
const stable_vector* p;
public:
invariant_checker(const stable_vector& v):p(&v){}
~invariant_checker(){BOOST_ASSERT(p->invariant());}
@@ -1619,11 +1708,32 @@ class stable_vector
};
#endif
struct ebo_holder
: node_allocator_type
class ebo_holder
: public node_allocator_type
{
ebo_holder(const allocator_type &a)
: node_allocator_type(a), pool_size(0), end_node()
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
public:
/*
explicit ebo_holder(BOOST_RV_REF(ebo_holder) x)
: node_allocator_type(boost::move(static_cast<node_allocator_type&>(x)))
, pool_size(0)
, end_node()
{}
*/
template<class AllocatorRLValue>
explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
: node_allocator_type(boost::forward<AllocatorRLValue>(a))
, pool_size(0)
, end_node()
{
this->set_end_pointer_to_default_constructed();
}
ebo_holder()
: node_allocator_type()
, pool_size(0)
, end_node()
{
this->set_end_pointer_to_default_constructed();
}
@@ -1637,8 +1747,15 @@ class stable_vector
node_type_base_t end_node;
} internal_data;
node_allocator_type &get_al() { return internal_data; }
const node_allocator_type &get_al() const { return internal_data; }
void priv_swap_members(stable_vector &x)
{
container_detail::do_swap(this->internal_data.pool_size, x.internal_data.pool_size);
this->readjust_end_node();
x.readjust_end_node();
}
node_allocator_type &node_alloc() { return internal_data; }
const node_allocator_type &node_alloc() const { return internal_data; }
impl_type impl;
/// @endcond