* Improved vector's insertion performance.

*  Changed again experimental multiallocation interface for better performance (still experimental).
*  Added no exception support for those willing to disable exceptions in their compilers.
*  Fixed GCC -Wshadow warnings.
*  Replaced deprecated BOOST_NO_XXXX with newer BOOST_NO_CXX11_XXX macros.


[SVN r81518]
This commit is contained in:
Ion Gaztañaga
2012-11-24 21:08:18 +00:00
parent a75d72d03c
commit bc5c91bb79
28 changed files with 2449 additions and 1892 deletions

View File

@@ -28,7 +28,7 @@
#include <boost/container/detail/memory_util.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <limits> //numeric_limits<>::max()
#include <new> //placement new
#include <memory> //std::allocator

View File

@@ -58,9 +58,11 @@
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_nothrow_copy.hpp>
#include <boost/type_traits/has_nothrow_assign.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/container/detail/advanced_insert_int.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost {
namespace container {
@@ -79,8 +81,7 @@ struct deque_value_traits
typedef T value_type;
typedef Allocator allocator_type;
static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
static const bool trivial_dctr_after_move = false;
//::boost::has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
static const bool trivial_copy = has_trivial_copy<value_type>::value;
static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
static const bool trivial_assign = has_trivial_assign<value_type>::value;
@@ -304,7 +305,7 @@ class deque_base
{
this->m_node = new_node;
this->m_first = *new_node;
this->m_last = this->m_first + difference_type(this->s_buffer_size());
this->m_last = this->m_first + this->s_buffer_size();
}
friend const_iterator operator+(difference_type n, const const_iterator& x)
@@ -565,9 +566,6 @@ class deque : protected deque_base<T, Allocator>
typedef typename Base::ptr_alloc_ptr index_pointer;
static size_type s_buffer_size()
{ return Base::s_buffer_size(); }
typedef container_detail::advanced_insert_aux_int<iterator> advanced_insert_aux_int_t;
typedef repeat_iterator<T, difference_type> r_iterator;
typedef boost::move_iterator<r_iterator> move_it;
typedef allocator_traits<Allocator> allocator_traits_type;
/// @endcond
@@ -590,10 +588,10 @@ class deque : protected deque_base<T, Allocator>
//! <b>Effects</b>: Constructs a deque taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
explicit deque(const allocator_type& a)
explicit deque(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT
: Base(a)
{}
@@ -607,8 +605,8 @@ class deque : protected deque_base<T, Allocator>
explicit deque(size_type n)
: Base(n, allocator_type())
{
container_detail::default_construct_aux_proxy<Allocator, iterator> proxy(this->alloc(), n);
proxy.uninitialized_copy_remaining_to(this->begin());
container_detail::insert_default_constructed_n_proxy<Allocator, iterator> proxy(this->alloc());
proxy.uninitialized_copy_n_and_update(this->begin(), n);
//deque_base will deallocate in case of exception...
}
@@ -717,7 +715,7 @@ class deque : protected deque_base<T, Allocator>
//! <b>Complexity</b>: Linear to the number of elements.
~deque() BOOST_CONTAINER_NOEXCEPT
{
priv_destroy_range(this->members_.m_start, this->members_.m_finish);
this->priv_destroy_range(this->members_.m_start, this->members_.m_finish);
}
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -1020,7 +1018,7 @@ class deque : protected deque_base<T, Allocator>
this->priv_erase_last_n(len - new_size);
else{
const size_type n = new_size - this->size();
container_detail::default_construct_aux_proxy<Allocator, iterator> proxy(this->alloc(), n);
container_detail::insert_default_constructed_n_proxy<Allocator, iterator> proxy(this->alloc());
priv_insert_back_aux_impl(n, proxy);
}
}
@@ -1176,9 +1174,8 @@ class deque : protected deque_base<T, Allocator>
this->priv_push_front_simple_commit();
}
else{
typedef container_detail::advanced_insert_aux_non_movable_emplace<Allocator, iterator, Args...> type;
type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
this->priv_insert_front_aux_impl(1, proxy);
typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type;
this->priv_insert_front_aux_impl(1, type(this->alloc(), boost::forward<Args>(args)...));
}
}
@@ -1199,9 +1196,8 @@ class deque : protected deque_base<T, Allocator>
this->priv_push_back_simple_commit();
}
else{
typedef container_detail::advanced_insert_aux_non_movable_emplace<Allocator, iterator, Args...> type;
type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
this->priv_insert_back_aux_impl(1, proxy);
typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type;
this->priv_insert_back_aux_impl(1, type(this->alloc(), boost::forward<Args>(args)...));
}
}
@@ -1226,9 +1222,8 @@ class deque : protected deque_base<T, Allocator>
return (this->end()-1);
}
else{
typedef container_detail::advanced_insert_aux_emplace<Allocator, iterator, Args...> type;
type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
return this->priv_insert_aux_impl(p, 1, proxy);
typedef container_detail::insert_emplace_proxy<Allocator, iterator, Args...> type;
return this->priv_insert_aux_impl(p, 1, type(this->alloc(), boost::forward<Args>(args)...));
}
}
@@ -1247,9 +1242,8 @@ class deque : protected deque_base<T, Allocator>
priv_push_front_simple_commit(); \
} \
else{ \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT \
(advanced_insert_aux_non_movable_emplace, n), arg) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
priv_insert_front_aux_impl(1, proxy); \
} \
@@ -1266,9 +1260,8 @@ class deque : protected deque_base<T, Allocator>
priv_push_back_simple_commit(); \
} \
else{ \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT( \
advanced_insert_aux_non_movable_emplace, n), arg) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
priv_insert_back_aux_impl(1, proxy); \
} \
@@ -1287,8 +1280,8 @@ class deque : protected deque_base<T, Allocator>
return (this->end()-1); \
} \
else{ \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
return this->priv_insert_aux_impl(p, 1, proxy); \
} \
@@ -1424,7 +1417,7 @@ class deque : protected deque_base<T, Allocator>
#endif
)
{
container_detail::advanced_insert_aux_proxy<Allocator, FwdIt, iterator> proxy(this->alloc(), first, last);
container_detail::insert_range_proxy<Allocator, FwdIt, iterator> proxy(this->alloc(), first);
return priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
#endif
@@ -1477,8 +1470,8 @@ class deque : protected deque_base<T, Allocator>
{
const_iterator next = pos;
++next;
difference_type index = pos - this->members_.m_start;
if (size_type(index) < (this->size() >> 1)) {
size_type index = pos - this->members_.m_start;
if (index < (this->size()/2)) {
boost::move_backward(begin(), iterator(pos), iterator(next));
pop_front();
}
@@ -1504,9 +1497,9 @@ class deque : protected deque_base<T, Allocator>
return this->members_.m_finish;
}
else {
difference_type n = last - first;
difference_type elems_before = first - this->members_.m_start;
if (elems_before < static_cast<difference_type>(this->size() - n) - elems_before) {
const size_type n = static_cast<size_type>(last - first);
const size_type elems_before = static_cast<size_type>(first - this->members_.m_start);
if (elems_before < (this->size() - n) - elems_before) {
boost::move_backward(begin(), iterator(first), iterator(last));
iterator new_start = this->members_.m_start + n;
if(!Base::traits_t::trivial_dctr_after_move)
@@ -1584,81 +1577,49 @@ class deque : protected deque_base<T, Allocator>
void priv_range_check(size_type n) const
{ if (n >= this->size()) BOOST_RETHROW std::out_of_range("deque"); }
iterator priv_insert(const_iterator position, const value_type &x)
template <class U>
iterator priv_insert(const_iterator position, BOOST_FWD_REF(U) x)
{
if (position == cbegin()){
this->push_front(x);
this->push_front(::boost::forward<U>(x));
return begin();
}
else if (position == cend()){
this->push_back(x);
return (end()-1);
this->push_back(::boost::forward<U>(x));
return --end();
}
else {
return this->insert(position, size_type(1), x);
return priv_insert_aux_impl
(position, (size_type)1, container_detail::get_insert_value_proxy<iterator>(this->alloc(), ::boost::forward<U>(x)));
}
}
iterator priv_insert(const_iterator position, BOOST_RV_REF(value_type) mx)
{
if (position == cbegin()) {
this->push_front(boost::move(mx));
return begin();
}
else if (position == cend()) {
this->push_back(boost::move(mx));
return(end()-1);
}
else {
return this->insert(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
}
}
void priv_push_front(const value_type &t)
template <class U>
void priv_push_front(BOOST_FWD_REF(U) x)
{
if(this->priv_push_front_simple_available()){
allocator_traits_type::construct
( this->alloc(), this->priv_push_front_simple_pos(), t);
( this->alloc(), this->priv_push_front_simple_pos(), ::boost::forward<U>(x));
this->priv_push_front_simple_commit();
}
else{
this->insert(cbegin(), size_type(1), t);
priv_insert_aux_impl
(this->cbegin(), (size_type)1, container_detail::get_insert_value_proxy<iterator>(this->alloc(), ::boost::forward<U>(x)));
}
}
void priv_push_front(BOOST_RV_REF(value_type) t)
{
if(this->priv_push_front_simple_available()){
allocator_traits_type::construct
( this->alloc(), this->priv_push_front_simple_pos(), boost::move(t));
this->priv_push_front_simple_commit();
}
else{
this->insert(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
}
void priv_push_back(const value_type &t)
template <class U>
void priv_push_back(BOOST_FWD_REF(U) x)
{
if(this->priv_push_back_simple_available()){
allocator_traits_type::construct
( this->alloc(), this->priv_push_back_simple_pos(), t);
( this->alloc(), this->priv_push_back_simple_pos(), ::boost::forward<U>(x));
this->priv_push_back_simple_commit();
}
else{
this->insert(cend(), size_type(1), t);
}
}
void priv_push_back(BOOST_RV_REF(T) t)
{
if(this->priv_push_back_simple_available()){
allocator_traits_type::construct
( this->alloc(), this->priv_push_back_simple_pos(), boost::move(t));
this->priv_push_back_simple_commit();
}
else{
this->insert(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
priv_insert_aux_impl
(this->cend(), (size_type)1, container_detail::get_insert_value_proxy<iterator>(this->alloc(), ::boost::forward<U>(x)));
container_detail::insert_copy_proxy<Allocator, iterator> proxy(this->alloc(), x);
}
}
@@ -1710,7 +1671,8 @@ class deque : protected deque_base<T, Allocator>
}
}
iterator priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
template<class InsertProxy>
iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy interf)
{
iterator pos(p);
const size_type pos_n = p - this->cbegin();
@@ -1719,58 +1681,85 @@ class deque : protected deque_base<T, Allocator>
pos = this->begin();
}
const difference_type elemsbefore = pos - this->members_.m_start;
size_type length = this->size();
if (elemsbefore < static_cast<difference_type>(length / 2)) {
iterator new_start = this->priv_reserve_elements_at_front(n);
iterator old_start = this->members_.m_start;
pos = this->members_.m_start + elemsbefore;
if (elemsbefore >= difference_type(n)) {
iterator start_n = this->members_.m_start + difference_type(n);
::boost::container::uninitialized_move_alloc
(this->alloc(), this->members_.m_start, start_n, new_start);
const size_type elemsbefore = static_cast<size_type>(pos - this->members_.m_start);
const size_type length = this->size();
if (elemsbefore < length / 2) {
const iterator new_start = this->priv_reserve_elements_at_front(n);
const iterator old_start = this->members_.m_start;
if(!elemsbefore){
interf.uninitialized_copy_n_and_update(new_start, n);
this->members_.m_start = new_start;
boost::move(start_n, pos, old_start);
interf.copy_remaining_to(pos - difference_type(n));
}
else {
difference_type mid_count = (difference_type(n) - elemsbefore);
iterator mid_start = old_start - mid_count;
interf.uninitialized_copy_some_and_update(mid_start, mid_count, true);
this->members_.m_start = mid_start;
::boost::container::uninitialized_move_alloc
(this->alloc(), old_start, pos, new_start);
this->members_.m_start = new_start;
interf.copy_remaining_to(old_start);
else{
pos = this->members_.m_start + elemsbefore;
if (elemsbefore >= n) {
const iterator start_n = this->members_.m_start + n;
::boost::container::uninitialized_move_alloc
(this->alloc(), this->members_.m_start, start_n, new_start);
this->members_.m_start = new_start;
boost::move(start_n, pos, old_start);
interf.copy_n_and_update(pos - n, n);
}
else {
const size_type mid_count = n - elemsbefore;
const iterator mid_start = old_start - mid_count;
interf.uninitialized_copy_n_and_update(mid_start, mid_count);
this->members_.m_start = mid_start;
::boost::container::uninitialized_move_alloc
(this->alloc(), old_start, pos, new_start);
this->members_.m_start = new_start;
interf.copy_n_and_update(old_start, elemsbefore);
}
}
}
else {
iterator new_finish = this->priv_reserve_elements_at_back(n);
iterator old_finish = this->members_.m_finish;
const difference_type elemsafter =
difference_type(length) - elemsbefore;
pos = this->members_.m_finish - elemsafter;
if (elemsafter >= difference_type(n)) {
iterator finish_n = this->members_.m_finish - difference_type(n);
::boost::container::uninitialized_move_alloc
(this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish);
const iterator new_finish = this->priv_reserve_elements_at_back(n);
const iterator old_finish = this->members_.m_finish;
const size_type elemsafter = length - elemsbefore;
if(!elemsafter){
interf.uninitialized_copy_n_and_update(old_finish, n);
this->members_.m_finish = new_finish;
boost::move_backward(pos, finish_n, old_finish);
interf.copy_remaining_to(pos);
}
else {
interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
this->members_.m_finish += n-elemsafter;
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, this->members_.m_finish);
this->members_.m_finish = new_finish;
interf.copy_remaining_to(pos);
else{
pos = this->members_.m_finish - elemsafter;
if (elemsafter >= n) {
iterator finish_n = this->members_.m_finish - difference_type(n);
::boost::container::uninitialized_move_alloc
(this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish);
this->members_.m_finish = new_finish;
boost::move_backward(pos, finish_n, old_finish);
interf.copy_n_and_update(pos, n);
}
else {
const size_type raw_gap = n - elemsafter;
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, this->members_.m_finish + raw_gap);
BOOST_TRY{
interf.uninitialized_copy_n_and_update(old_finish, raw_gap);
}
BOOST_CATCH(...){
this->priv_destroy_range(this->members_.m_finish, this->members_.m_finish + (old_finish - pos));
BOOST_RETHROW
}
BOOST_CATCH_END
this->members_.m_finish = new_finish;
interf.copy_n_and_update(pos, elemsafter);
/*
interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
this->members_.m_finish += n-elemsafter;
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, this->members_.m_finish);
this->members_.m_finish = new_finish;
interf.copy_remaining_to(pos);
*/
}
}
}
return this->begin() + pos_n;
}
iterator priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
template <class InsertProxy>
iterator priv_insert_back_aux_impl(size_type n, InsertProxy interf)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1778,19 +1767,20 @@ class deque : protected deque_base<T, Allocator>
iterator new_finish = this->priv_reserve_elements_at_back(n);
iterator old_finish = this->members_.m_finish;
interf.uninitialized_copy_some_and_update(old_finish, n, true);
interf.uninitialized_copy_n_and_update(old_finish, n);
this->members_.m_finish = new_finish;
return iterator(this->members_.m_finish - n);
}
iterator priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
template <class InsertProxy>
iterator priv_insert_front_aux_impl(size_type n, InsertProxy interf)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
}
iterator new_start = this->priv_reserve_elements_at_front(n);
interf.uninitialized_copy_some_and_update(new_start, difference_type(n), true);
interf.uninitialized_copy_n_and_update(new_start, n);
this->members_.m_start = new_start;
return new_start;
}
@@ -2015,15 +2005,14 @@ inline void swap(deque<T, Allocator>& x, deque<T, Allocator>& y)
/// @cond
namespace boost {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator> >
{
enum { value = has_trivial_destructor<Allocator>::value };
};
*/
: public ::boost::has_trivial_destructor_after_move<Allocator>
{};
}
/// @endcond

View File

@@ -21,16 +21,28 @@
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
#include <boost/assert.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace adaptive_pool_flag {
static const unsigned int none = 0u;
static const unsigned int align_only = 1u << 0u;
static const unsigned int size_ordered = 1u << 1u;
static const unsigned int address_ordered = 1u << 2u;
} //namespace adaptive_pool_flag{
namespace container_detail {
template<class size_type>
@@ -42,42 +54,160 @@ struct hdr_offset_holder_t
size_type hdr_offset;
};
template<class SizeType, unsigned int Flags>
struct less_func;
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::none>
{
static bool less(SizeType, SizeType, const void *, const void *)
{ return true; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::size_ordered>
{
static bool less(SizeType ls, SizeType rs, const void *, const void *)
{ return ls < rs; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::address_ordered>
{
static bool less(SizeType, SizeType, const void *la, const void *ra)
{ return &la < &ra; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered>
{
static bool less(SizeType ls, SizeType rs, const void *la, const void *ra)
{ return (ls < rs) || ((ls == rs) && (la < ra)); }
};
template<class VoidPointer, class SizeType, bool ordered>
struct block_container_traits
{
typedef typename bi::make_set_base_hook
< bi::void_pointer<VoidPointer>
, bi::optimize_size<true>
, bi::link_mode<bi::normal_link> >::type hook_t;
template<class T>
struct container
{
typedef typename bi::make_multiset
<T, bi::base_hook<hook_t>, bi::size_type<SizeType> >::type type;
};
template<class Container>
static void reinsert_was_used(Container &container, typename Container::reference v, bool)
{
typedef typename Container::const_iterator const_block_iterator;
const const_block_iterator this_block
(Container::s_iterator_to(const_cast<typename Container::const_reference>(v)));
const_block_iterator next_block(this_block);
if(++next_block != container.cend()){
if(this_block->free_nodes.size() > next_block->free_nodes.size()){
container.erase(this_block);
container.insert(v);
}
}
}
template<class Container>
static void insert_was_empty(Container &container, typename Container::value_type &v, bool)
{
container.insert(v);
}
template<class Container>
static void erase_first(Container &container)
{
container.erase(container.cbegin());
}
template<class Container>
static void erase_last(Container &container)
{
container.erase(--container.cend());
}
};
template<class VoidPointer, class SizeType>
struct block_container_traits<VoidPointer, SizeType, false>
{
typedef typename bi::make_list_base_hook
< bi::void_pointer<VoidPointer>
, bi::link_mode<bi::normal_link> >::type hook_t;
template<class T>
struct container
{
typedef typename bi::make_list
<T, bi::base_hook<hook_t>, bi::size_type<SizeType>, bi::constant_time_size<false> >::type type;
};
template<class Container>
static void reinsert_was_used(Container &container, typename Container::value_type &v, bool is_full)
{
if(is_full){
container.erase(Container::s_iterator_to(v));
container.push_back(v);
}
}
template<class Container>
static void insert_was_empty(Container &container, typename Container::value_type &v, bool is_full)
{
if(is_full){
container.push_back(v);
}
else{
container.push_front(v);
}
}
template<class Container>
static void erase_first(Container &container)
{
container.pop_front();
}
template<class Container>
static void erase_last(Container &container)
{
container.pop_back();
}
};
template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
struct adaptive_pool_types
{
typedef VoidPointer void_pointer;
typedef typename bi::make_set_base_hook
< bi::void_pointer<void_pointer>
, bi::optimize_size<true>
, bi::constant_time_size<false>
, bi::link_mode<bi::normal_link> >::type multiset_hook_t;
static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0;
typedef block_container_traits<VoidPointer, SizeType, ordered> block_container_traits_t;
typedef typename block_container_traits_t::hook_t hook_t;
typedef hdr_offset_holder_t<SizeType> hdr_offset_holder;
static const unsigned int order_flags = Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered);
typedef MultiallocationChain free_nodes_t;
struct block_info_t
:
public hdr_offset_holder,
public multiset_hook_t
: public hdr_offset_holder,
public hook_t
{
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
//An intrusive list of free node from this block
free_nodes_t free_nodes;
friend bool operator <(const block_info_t &l, const block_info_t &r)
{
// { return l.free_nodes.size() < r.free_nodes.size(); }
//Let's order blocks first by free nodes and then by address
//so that highest address fully free blocks are deallocated.
//This improves returning memory to the OS (trimming).
const bool is_less = l.free_nodes.size() < r.free_nodes.size();
const bool is_equal = l.free_nodes.size() == r.free_nodes.size();
return is_less || (is_equal && (&l < &r));
return less_func<SizeType, order_flags>::
less(l.free_nodes.size(), r.free_nodes.size(), &l , &r);
}
friend bool operator ==(const block_info_t &l, const block_info_t &r)
{ return &l == &r; }
};
typedef typename bi::make_multiset
<block_info_t, bi::base_hook<multiset_hook_t> >::type block_multiset_t;
typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
};
template<class size_type>
@@ -113,9 +243,9 @@ inline void calculate_num_subblocks
, size_type &num_subblocks, size_type &real_num_node, size_type overhead_percent
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
{
const size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
size_type elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
size_type possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
++possible_num_subblock;
}
@@ -135,7 +265,7 @@ inline void calculate_num_subblocks
real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
}
template<class SegmentManagerBase, bool AlignOnly = false>
template<class SegmentManagerBase, unsigned int Flags>
class private_adaptive_node_pool_impl
{
//Non-copyable
@@ -147,27 +277,42 @@ class private_adaptive_node_pool_impl
typedef typename SegmentManagerBase::void_pointer void_pointer;
static const typename SegmentManagerBase::
size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
//Flags
//align_only
static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
typedef bool_<AlignOnly> IsAlignOnly;
typedef true_ AlignOnlyTrue;
typedef false_ AlignOnlyFalse;
//size_ordered
static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0;
typedef bool_<SizeOrdered> IsSizeOrdered;
typedef true_ SizeOrderedTrue;
typedef false_ SizeOrderedFalse;
//address_ordered
static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0;
typedef bool_<AddressOrdered> IsAddressOrdered;
typedef true_ AddressOrderedTrue;
typedef false_ AddressOrderedFalse;
public:
typedef typename node_slist<void_pointer>::node_t node_t;
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
typedef typename SegmentManagerBase::size_type size_type;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
typedef typename SegmentManagerBase::size_type size_type;
private:
typedef typename adaptive_pool_types<void_pointer, size_type>::block_info_t block_info_t;
typedef typename adaptive_pool_types<void_pointer, size_type>::block_multiset_t block_multiset_t;
typedef typename block_multiset_t::iterator block_iterator;
typedef typename adaptive_pool_types<void_pointer, size_type>::hdr_offset_holder hdr_offset_holder;
typedef adaptive_pool_types
<multiallocation_chain, void_pointer, size_type, Flags> adaptive_pool_types_t;
typedef typename adaptive_pool_types_t::free_nodes_t free_nodes_t;
typedef typename adaptive_pool_types_t::block_info_t block_info_t;
typedef typename adaptive_pool_types_t::block_container_t block_container_t;
typedef typename adaptive_pool_types_t::block_container_traits_t block_container_traits_t;
typedef typename block_container_t::iterator block_iterator;
typedef typename block_container_t::const_iterator const_block_iterator;
typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder;
static const size_type MaxAlign = alignment_of<node_t>::value;
static const size_type MaxAlign = alignment_of<void_pointer>::value;
static const size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
static const size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
public:
//!Segment manager typedef
typedef SegmentManagerBase segment_manager_base_type;
@@ -181,7 +326,7 @@ class private_adaptive_node_pool_impl
, unsigned char overhead_percent
)
: m_max_free_blocks(max_free_blocks)
, m_real_node_size(lcm(node_size, size_type(alignment_of<node_t>::value)))
, m_real_node_size(lcm(node_size, size_type(alignment_of<void_pointer>::value)))
//Round the size to a power of two value.
//This is the total memory size (including payload) that we want to
//allocate from the general-purpose allocator
@@ -195,7 +340,7 @@ class private_adaptive_node_pool_impl
, m_real_num_node(AlignOnly ? (m_real_block_alignment - PayloadPerAllocation - HdrSize)/m_real_node_size : 0)
//General purpose allocator
, mp_segment_mngr_base(segment_mngr_base)
, m_block_multiset()
, m_block_container()
, m_totally_free_blocks(0)
{
if(!AlignOnly){
@@ -214,7 +359,7 @@ class private_adaptive_node_pool_impl
//!Destructor. Deallocates all allocated blocks. Never throws
~private_adaptive_node_pool_impl()
{ priv_clear(); }
{ this->priv_clear(); }
size_type get_real_num_node() const
{ return m_real_num_node; }
@@ -226,84 +371,157 @@ class private_adaptive_node_pool_impl
//!Allocates array of count elements. Can throw
void *allocate_node()
{
priv_invariants();
this->priv_invariants();
//If there are no free nodes we allocate a new block
if (m_block_multiset.empty()){
priv_alloc_block(1);
if(!m_block_container.empty()){
//We take the first free node the multiset can't be empty
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
BOOST_ASSERT(!free_nodes.empty());
const size_type free_nodes_count = free_nodes.size();
void *first_node = container_detail::to_raw_pointer(free_nodes.pop_front());
if(free_nodes.empty()){
block_container_traits_t::erase_first(m_block_container);
}
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == m_real_num_node);
this->priv_invariants();
return first_node;
}
else{
multiallocation_chain chain;
this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
return container_detail::to_raw_pointer(chain.pop_front());
}
//We take the first free node the multiset can't be empty
return priv_take_first_node();
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
multiallocation_chain chain;
chain.push_front(void_pointer(pElem));
this->priv_reinsert_nodes_in_block(chain, 1);
//Update free block count<
if(m_totally_free_blocks > m_max_free_blocks){
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
priv_invariants();
this->priv_invariants();
block_info_t &block_info = *this->priv_block_from_node(pElem);
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
//We put the node at the beginning of the free node list
block_info.free_nodes.push_back(void_pointer(pElem));
//The loop reinserts all blocks except the last one
this->priv_reinsert_block(block_info, block_info.free_nodes.size() == 1);
this->priv_deallocate_free_blocks(m_max_free_blocks);
this->priv_invariants();
}
//!Allocates n nodes.
//!Can throw
multiallocation_chain allocate_nodes(const size_type n)
void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
multiallocation_chain chain;
size_type i = 0;
try{
priv_invariants();
BOOST_TRY{
this->priv_invariants();
while(i != n){
//If there are no free nodes we allocate all needed blocks
if (m_block_multiset.empty()){
priv_alloc_block(((n - i) - 1)/m_real_num_node + 1);
if (m_block_container.empty()){
this->priv_append_from_new_blocks(n - i, chain, IsAlignOnly());
BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
BOOST_ASSERT(chain.size() == n);
break;
}
free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
const size_type free_nodes_count_before = free_nodes.size();
if(free_nodes_count_before == m_real_num_node){
--m_totally_free_blocks;
}
const size_type num_elems = ((n-i) < free_nodes_count_before) ? (n-i) : free_nodes_count_before;
for(size_type j = 0; j != num_elems; ++j){
void *new_node = &free_nodes.front();
free_nodes.pop_front();
chain.push_back(new_node);
}
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == m_real_num_node);
const size_type num_left = n-i;
const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
typedef typename free_nodes_t::iterator free_nodes_iterator;
if(free_nodes.empty()){
m_block_multiset.erase(m_block_multiset.begin());
if(num_left < free_nodes_count_before){
const free_nodes_iterator it_bbeg(free_nodes.before_begin());
free_nodes_iterator it_bend(it_bbeg);
for(size_type j = 0; j != num_elems; ++j){
++it_bend;
}
free_nodes_iterator it_end = it_bend; ++it_end;
free_nodes_iterator it_beg = it_bbeg; ++it_beg;
free_nodes.erase_after(it_bbeg, it_end, num_elems);
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
//chain.splice_after(chain.last(), free_nodes, it_bbeg, it_bend, num_elems);
BOOST_ASSERT(!free_nodes.empty());
}
else{
const free_nodes_iterator it_beg(free_nodes.begin()), it_bend(free_nodes.last());
free_nodes.clear();
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
block_container_traits_t::erase_first(m_block_container);
}
i += num_elems;
}
}
catch(...){
this->deallocate_nodes(boost::move(chain));
throw;
BOOST_CATCH(...){
this->deallocate_nodes(chain);
BOOST_RETHROW
}
priv_invariants();
return boost::move(chain);
BOOST_CATCH_END
this->priv_invariants();
}
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain nodes)
void deallocate_nodes(multiallocation_chain &nodes)
{
this->priv_reinsert_nodes_in_block(nodes, nodes.size());
if(m_totally_free_blocks > m_max_free_blocks){
this->priv_invariants();
//To take advantage of node locality, wait until two
//nodes belong to different blocks. Only then reinsert
//the block of the first node in the block tree.
//Cache of the previous block
block_info_t *prev_block_info = 0;
//If block was empty before this call, it's not already
//inserted in the block tree.
bool prev_block_was_empty = false;
typedef typename free_nodes_t::iterator free_nodes_iterator;
{
const free_nodes_iterator itbb(nodes.before_begin()), ite(nodes.end());
free_nodes_iterator itf(nodes.begin()), itbf(itbb);
size_type splice_node_count = size_type(-1);
while(itf != ite){
void *pElem = container_detail::to_raw_pointer(&*itf);
block_info_t &block_info = *this->priv_block_from_node(pElem);
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
++splice_node_count;
//If block change is detected calculate the cached block position in the tree
if(&block_info != prev_block_info){
if(prev_block_info){ //Make sure we skip the initial "dummy" cache
free_nodes_iterator it(itbb); ++it;
nodes.erase_after(itbb, itf, splice_node_count);
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
splice_node_count = 0;
}
//Update cache with new data
prev_block_was_empty = block_info.free_nodes.empty();
prev_block_info = &block_info;
}
itbf = itf;
++itf;
}
}
if(prev_block_info){
//The loop reinserts all blocks except the last one
const free_nodes_iterator itfirst(nodes.begin()), itlast(nodes.last());
const size_type splice_node_count = nodes.size();
nodes.clear();
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
this->priv_invariants();
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
}
void deallocate_free_blocks()
{ this->priv_deallocate_free_blocks(0); }
{ this->priv_deallocate_free_blocks(0); }
size_type num_free_nodes()
{
typedef typename block_multiset_t::const_iterator citerator;
typedef typename block_container_t::const_iterator citerator;
size_type count = 0;
citerator it (m_block_multiset.begin()), itend(m_block_multiset.end());
citerator it (m_block_container.begin()), itend(m_block_container.end());
for(; it != itend; ++it){
count += it->free_nodes.size();
}
@@ -318,7 +536,7 @@ class private_adaptive_node_pool_impl
BOOST_ASSERT(m_real_num_node == other.m_real_num_node);
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
m_block_multiset.swap(other.m_block_multiset);
m_block_container.swap(other.m_block_container);
}
//Deprecated, use deallocate_free_blocks
@@ -326,83 +544,54 @@ class private_adaptive_node_pool_impl
{ this->priv_deallocate_free_blocks(0); }
private:
void priv_deallocate_free_blocks(size_type max_free_blocks)
{ //Trampoline function to ease inlining
if(m_totally_free_blocks > max_free_blocks){
this->priv_deallocate_free_blocks_impl(max_free_blocks);
}
}
void priv_deallocate_free_blocks_impl(size_type max_free_blocks)
{
priv_invariants();
this->priv_invariants();
//Now check if we've reached the free nodes limit
//and check if we have free blocks. If so, deallocate as much
//as we can to stay below the limit
for( block_iterator itend = m_block_multiset.end()
; m_totally_free_blocks > max_free_blocks
; --m_totally_free_blocks
){
BOOST_ASSERT(!m_block_multiset.empty());
block_iterator it = itend;
multiallocation_chain chain;
{
const const_block_iterator itend = m_block_container.cend();
const_block_iterator it = itend;
--it;
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
m_block_multiset.erase_and_dispose(it, block_destroyer(this));
size_type totally_free_blocks = m_totally_free_blocks;
for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it));
--it;
block_container_traits_t::erase_last(m_block_container);
chain.push_front(void_pointer(addr));
}
BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
m_totally_free_blocks = max_free_blocks;
}
this->mp_segment_mngr_base->deallocate_many(chain);
}
void priv_reinsert_nodes_in_block(multiallocation_chain &chain, size_type n)
void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty)
{
block_iterator block_it(m_block_multiset.end());
while(n--){
void *pElem = container_detail::to_raw_pointer(chain.pop_front());
priv_invariants();
block_info_t *block_info = this->priv_block_from_node(pElem);
BOOST_ASSERT(block_info->free_nodes.size() < m_real_num_node);
//We put the node at the beginning of the free node list
node_t * to_deallocate = static_cast<node_t*>(pElem);
block_info->free_nodes.push_front(*to_deallocate);
//Cache the free nodes from the block
const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
const bool is_full = this_block_free_nodes == m_real_num_node;
block_iterator this_block(block_multiset_t::s_iterator_to(*block_info));
block_iterator next_block(this_block);
++next_block;
//Cache the free nodes from the block
size_type this_block_free_nodes = this_block->free_nodes.size();
if(this_block_free_nodes == 1){
m_block_multiset.insert(m_block_multiset.begin(), *block_info);
}
else{
block_iterator next_block(this_block);
++next_block;
if(next_block != block_it){
size_type next_free_nodes = next_block->free_nodes.size();
if(this_block_free_nodes > next_free_nodes){
//Now move the block to the new position
m_block_multiset.erase(this_block);
m_block_multiset.insert(*block_info);
}
}
}
//Update free block count
if(this_block_free_nodes == m_real_num_node){
++m_totally_free_blocks;
}
priv_invariants();
//Update free block count
m_totally_free_blocks += static_cast<size_type>(is_full);
if(prev_block_was_empty){
block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
}
}
node_t *priv_take_first_node()
{
BOOST_ASSERT(m_block_multiset.begin() != m_block_multiset.end());
//We take the first free node the multiset can't be empty
free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
node_t *first_node = &free_nodes.front();
const size_type free_nodes_count = free_nodes.size();
BOOST_ASSERT(0 != free_nodes_count);
free_nodes.pop_front();
if(free_nodes_count == 1){
m_block_multiset.erase(m_block_multiset.begin());
else{
block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
}
else if(free_nodes_count == m_real_num_node){
--m_totally_free_blocks;
}
priv_invariants();
return first_node;
}
class block_destroyer;
@@ -411,33 +600,31 @@ class private_adaptive_node_pool_impl
class block_destroyer
{
public:
block_destroyer(const this_type *impl)
: mp_impl(impl)
block_destroyer(const this_type *impl, multiallocation_chain &chain)
: mp_impl(impl), m_chain(chain)
{}
void operator()(typename block_multiset_t::pointer to_deallocate)
void operator()(typename block_container_t::pointer to_deallocate)
{ return this->do_destroy(to_deallocate, IsAlignOnly()); }
private:
void do_destroy(typename block_multiset_t::pointer to_deallocate, AlignOnlyTrue)
void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
{
size_type free_nodes = to_deallocate->free_nodes.size();
(void)free_nodes;
BOOST_ASSERT(free_nodes == mp_impl->m_real_num_node);
mp_impl->mp_segment_mngr_base->deallocate(to_deallocate);
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
m_chain.push_back(to_deallocate);
}
void do_destroy(typename block_multiset_t::pointer to_deallocate, AlignOnlyFalse)
void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
{
size_type free_nodes = to_deallocate->free_nodes.size();
(void)free_nodes;
BOOST_ASSERT(free_nodes == mp_impl->m_real_num_node);
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
BOOST_ASSERT(0 == to_deallocate->hdr_offset);
hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder);
hdr_offset_holder *hdr_off_holder =
mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
m_chain.push_back(hdr_off_holder);
}
const this_type *mp_impl;
multiallocation_chain &m_chain;
};
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
@@ -446,44 +633,45 @@ class private_adaptive_node_pool_impl
#ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#undef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
{
//We iterate through the block tree to free the memory
block_iterator it(m_block_multiset.begin()),
itend(m_block_multiset.end()), to_deallocate;
if(it != itend){
for(++it; it != itend; ++it){
block_iterator prev(it);
--prev;
size_type sp = prev->free_nodes.size(),
si = it->free_nodes.size();
BOOST_ASSERT(sp <= si);
(void)sp; (void)si;
const const_block_iterator itend(m_block_container.end());
{ //We iterate through the block tree to free the memory
const_block_iterator it(m_block_container.begin());
if(it != itend){
for(++it; it != itend; ++it){
const_block_iterator prev(it);
--prev;
BOOST_ASSERT(*prev < *it);
(void)prev; (void)it;
}
}
}
//Check that the total free nodes are correct
it = m_block_multiset.begin();
itend = m_block_multiset.end();
size_type total_free_nodes = 0;
for(; it != itend; ++it){
total_free_nodes += it->free_nodes.size();
{ //Check that the total free nodes are correct
const_block_iterator it(m_block_container.cbegin());
size_type total_free_nodes = 0;
for(; it != itend; ++it){
total_free_nodes += it->free_nodes.size();
}
BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
}
BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
//Check that the total totally free blocks are correct
it = m_block_multiset.begin();
itend = m_block_multiset.end();
total_free = 0;
for(; it != itend; ++it){
total_free += it->free_nodes.size() == m_real_num_node;
{ //Check that the total totally free blocks are correct
BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
const_block_iterator it = m_block_container.cend();
size_type total_free_blocks = m_totally_free_blocks;
while(total_free_blocks--){
BOOST_ASSERT((--it)->free_nodes.size() == m_real_num_node);
}
}
BOOST_ASSERT(total_free >= m_totally_free_blocks);
if(!AlignOnly){
//Check that header offsets are correct
it = m_block_multiset.begin();
const_block_iterator it = m_block_container.begin();
for(; it != itend; ++it){
hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it);
hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it));
for(size_type i = 0, max = m_num_subblocks; i < max; ++i){
BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(&*it)- reinterpret_cast<char*>(hdr_off_holder)));
const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
BOOST_ASSERT(0 == ((size_type)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
@@ -499,19 +687,21 @@ class private_adaptive_node_pool_impl
void priv_clear()
{
#ifndef NDEBUG
block_iterator it = m_block_multiset.begin();
block_iterator itend = m_block_multiset.end();
size_type num_free_nodes = 0;
block_iterator it = m_block_container.begin();
block_iterator itend = m_block_container.end();
size_type n_free_nodes = 0;
for(; it != itend; ++it){
//Check for memory leak
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
++num_free_nodes;
++n_free_nodes;
}
BOOST_ASSERT(num_free_nodes == m_totally_free_blocks);
BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
#endif
//Check for memory leaks
priv_invariants();
m_block_multiset.clear_and_dispose(block_destroyer(this));
this->priv_invariants();
multiallocation_chain chain;
m_block_container.clear_and_dispose(block_destroyer(this, chain));
this->mp_segment_mngr_base->deallocate_many(chain);
m_totally_free_blocks = 0;
}
@@ -533,93 +723,129 @@ class private_adaptive_node_pool_impl
}
block_info_t *priv_block_from_node(void *node) const
{ return priv_block_from_node(node, IsAlignOnly()); }
{ return this->priv_block_from_node(node, IsAlignOnly()); }
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
{ return this->priv_first_subblock_from_block(block, IsAlignOnly()); }
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyFalse) const
{
hdr_offset_holder *hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
(reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
return hdr_off_holder;
}
//!Allocates a several blocks of nodes. Can throw
void priv_alloc_block(size_type n, AlignOnlyTrue)
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const
{
size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
if(!mem_address) throw std::bad_alloc();
++m_totally_free_blocks;
block_info_t *c_info = new(mem_address)block_info_t();
m_block_multiset.insert(m_block_multiset.end(), *c_info);
mem_address += HdrSize;
//We initialize all Nodes in Node Block to insert
//them in the free Node list
typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
for(size_type i = 0; i < m_real_num_node; ++i){
prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *(node_t*)mem_address);
mem_address += m_real_node_size;
return reinterpret_cast<hdr_offset_holder*>(block);
}
void priv_dispatch_block_chain_or_free
( multiallocation_chain &chain, block_info_t &c_info, size_type num_node
, char *mem_address, size_type total_elements, bool insert_block_if_free)
{
BOOST_ASSERT(chain.size() <= total_elements);
//First add all possible nodes to the chain
const size_type left = total_elements - chain.size();
const size_type max_chain = (num_node < left) ? num_node : left;
mem_address = static_cast<char *>(container_detail::to_raw_pointer
(chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
//Now store remaining nodes in the free list
if(const size_type max_free = num_node - max_chain){
free_nodes_t & free_nodes = c_info.free_nodes;
free_nodes.incorporate_after(free_nodes.last(), void_pointer(mem_address), m_real_node_size, max_free);
if(insert_block_if_free){
m_block_container.push_front(c_info);
}
}
}
void priv_alloc_block(size_type n, AlignOnlyFalse)
//!Allocates a several blocks of nodes. Can throw
void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue)
{
size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
BOOST_ASSERT(m_block_container.empty());
BOOST_ASSERT(min_elements > 0);
const size_type n = (min_elements - 1)/m_real_num_node + 1;
const size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
const size_type total_elements = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
if(!mem_address){
//In case of error, free memory deallocating all nodes (the new ones allocated
//in this function plus previously stored nodes in chain).
this->deallocate_nodes(chain);
throw std::bad_alloc();
}
block_info_t &c_info = *new(mem_address)block_info_t();
mem_address += HdrSize;
if(i != (n-1)){
chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, m_real_num_node);
}
else{
this->priv_dispatch_block_chain_or_free(chain, c_info, m_real_num_node, mem_address, total_elements, true);
}
}
}
void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse)
{
BOOST_ASSERT(m_block_container.empty());
BOOST_ASSERT(min_elements > 0);
const size_type n = (min_elements - 1)/m_real_num_node + 1;
const size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
const size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
const size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
const size_type total_elements = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
if(!mem_address) throw std::bad_alloc();
++m_totally_free_blocks;
if(!mem_address){
//In case of error, free memory deallocating all nodes (the new ones allocated
//in this function plus previously stored nodes in chain).
this->deallocate_nodes(chain);
throw std::bad_alloc();
}
//First initialize header information on the last subblock
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
block_info_t *c_info = new(hdr_addr)block_info_t();
block_info_t &c_info = *new(hdr_addr)block_info_t();
//Some structural checks
BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder*>(c_info)->hdr_offset) ==
static_cast<void*>(c_info));
typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
; subblock < maxsubblock
; ++subblock, mem_address += m_real_block_alignment){
//Initialize header offset mark
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
char *pNode = mem_address + HdrOffsetSize;
for(size_type i = 0; i < elements_per_subblock; ++i){
prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
pNode += m_real_node_size;
BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
static_cast<void*>(&c_info)); (void)c_info;
if(i != (n-1)){
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
; subblock < maxsubblock
; ++subblock, mem_address += m_real_block_alignment){
//Initialize header offset mark
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
chain.incorporate_after
(chain.last(), void_pointer(mem_address + HdrOffsetSize), m_real_node_size, elements_per_subblock);
}
chain.incorporate_after(chain.last(), void_pointer(hdr_addr + HdrSize), m_real_node_size, hdr_subblock_elements);
}
{
char *pNode = hdr_addr + HdrSize;
//We initialize all Nodes in Node Block to insert
//them in the free Node list
for(size_type i = 0; i < hdr_subblock_elements; ++i){
prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
pNode += m_real_node_size;
else{
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
; subblock < maxsubblock
; ++subblock, mem_address += m_real_block_alignment){
//Initialize header offset mark
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
this->priv_dispatch_block_chain_or_free
(chain, c_info, elements_per_subblock, mem_address + HdrOffsetSize, total_elements, false);
}
this->priv_dispatch_block_chain_or_free
(chain, c_info, hdr_subblock_elements, hdr_addr + HdrSize, total_elements, true);
}
//Insert the block after the free node list is full
m_block_multiset.insert(m_block_multiset.end(), *c_info);
}
}
//!Allocates a block of nodes. Can throw std::bad_alloc
void priv_alloc_block(size_type n)
{ return priv_alloc_block(n, IsAlignOnly()); }
private:
typedef typename boost::intrusive::pointer_traits
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
@@ -633,9 +859,9 @@ class private_adaptive_node_pool_impl
//This is the real number of nodes per block
//const
size_type m_real_num_node;
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
block_multiset_t m_block_multiset; //Intrusive block list
size_type m_totally_free_blocks; //Free blocks
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
block_container_t m_block_container; //Intrusive block list
size_type m_totally_free_blocks; //Free blocks
};
} //namespace container_detail {

View File

@@ -20,160 +20,177 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <iterator> //std::iterator_traits
#include <boost/assert.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost { namespace container { namespace container_detail {
//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
template<class Iterator>
struct advanced_insert_aux_int
{
typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
virtual void copy_remaining_to(Iterator p) = 0;
virtual void uninitialized_copy_remaining_to(Iterator p) = 0;
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
virtual ~advanced_insert_aux_int() {}
};
//This class template will adapt each FwIt types to advanced_insert_aux_int
template<class A, class FwdIt, class Iterator>
struct advanced_insert_aux_proxy
: public advanced_insert_aux_int<Iterator>
struct insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
advanced_insert_aux_proxy(A& a, FwdIt first, FwdIt last)
: a_(a), first_(first), last_(last)
insert_range_proxy(A& a, FwdIt first)
: a_(a), first_(first)
{}
virtual ~advanced_insert_aux_proxy()
{}
virtual void copy_remaining_to(Iterator p)
{ ::boost::copy_or_move(this->first_, this->last_, p); }
virtual void uninitialized_copy_remaining_to(Iterator p)
{ ::boost::container::uninitialized_copy_or_move_alloc(this->a_, this->first_, this->last_, p); }
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
void uninitialized_copy_n_and_update(Iterator pos, size_type n)
{
FwdIt mid = this->first_;
std::advance(mid, division_count);
if(first_n){
::boost::container::uninitialized_copy_or_move_alloc(this->a_, this->first_, mid, pos);
this->first_ = mid;
}
else{
::boost::container::uninitialized_copy_or_move_alloc(this->a_, mid, this->last_, pos);
this->last_ = mid;
}
this->first_ = ::boost::container::uninitialized_copy_or_move_alloc_n_source
(this->a_, this->first_, n, pos);
}
virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
void copy_n_and_update(Iterator pos, size_type n)
{
FwdIt mid = this->first_;
std::advance(mid, division_count);
if(first_n){
::boost::copy_or_move(this->first_, mid, pos);
this->first_ = mid;
}
else{
::boost::copy_or_move(mid, this->last_, pos);
this->last_ = mid;
}
this->first_ = ::boost::container::copy_or_move_n_source(this->first_, n, pos);
}
A &a_;
FwdIt first_, last_;
FwdIt first_;
};
//This class template will adapt default construction insertions to advanced_insert_aux_int
template<class A, class Iterator>
struct default_construct_aux_proxy
: public advanced_insert_aux_int<Iterator>
struct insert_n_copies_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
insert_n_copies_proxy(A& a, const value_type &v)
: a_(a), v_(v)
{}
void uninitialized_copy_n_and_update(Iterator p, size_type n)
{ std::uninitialized_fill_n(p, n, v_); }
void copy_n_and_update(Iterator p, size_type n)
{ std::fill_n(p, n, v_); }
A &a_;
const value_type &v_;
};
template<class A, class Iterator>
struct insert_default_constructed_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
default_construct_aux_proxy(A &a, size_type count)
: a_(a), count_(count)
explicit insert_default_constructed_n_proxy(A &a)
: a_(a)
{}
virtual ~default_construct_aux_proxy()
{}
virtual void copy_remaining_to(Iterator)
{ //This should never be called with any count
BOOST_ASSERT(this->count_ == 0);
}
virtual void uninitialized_copy_remaining_to(Iterator p)
{ this->priv_uninitialized_copy(p, this->count_); }
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
void uninitialized_copy_n_and_update(Iterator p, size_type n)
{
size_type new_count;
if(first_n){
new_count = division_count;
}
else{
BOOST_ASSERT(difference_type(this->count_)>= division_count);
new_count = this->count_ - division_count;
}
this->priv_uninitialized_copy(pos, new_count);
}
virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
{
BOOST_ASSERT(this->count_ == 0);
size_type new_count;
if(first_n){
new_count = division_count;
}
else{
BOOST_ASSERT(difference_type(this->count_)>= division_count);
new_count = this->count_ - division_count;
}
//This function should never called with a count different to zero
BOOST_ASSERT(new_count == 0);
(void)new_count;
}
private:
void priv_uninitialized_copy(Iterator p, const size_type n)
{
BOOST_ASSERT(n <= this->count_);
Iterator orig_p = p;
size_type i = 0;
try{
for(; i < n; ++i, ++p){
size_type n_left = n;
BOOST_TRY{
for(; n_left--; ++p){
alloc_traits::construct(this->a_, container_detail::to_raw_pointer(&*p));
}
}
catch(...){
while(i--){
BOOST_CATCH(...){
for(; orig_p != p; ++orig_p){
alloc_traits::destroy(this->a_, container_detail::to_raw_pointer(&*orig_p++));
}
throw;
BOOST_RETHROW
}
this->count_ -= n;
BOOST_CATCH_END
}
void copy_n_and_update(Iterator, size_type)
{
BOOST_ASSERT(false);
}
private:
A &a_;
size_type count_;
};
template<class A, class Iterator>
struct insert_copy_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
insert_copy_proxy(A& a, const value_type &v)
: a_(a), v_(v)
{}
void uninitialized_copy_n_and_update(Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, v_
);
}
void copy_n_and_update(Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
*p =v_;
}
A &a_;
const value_type &v_;
};
template<class A, class Iterator>
struct insert_move_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
insert_move_proxy(A& a, value_type &v)
: a_(a), v_(v)
{}
void uninitialized_copy_n_and_update(Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, ::boost::move(v_)
);
}
void copy_n_and_update(Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
}
A &a_;
value_type &v_;
};
template<class It, class A>
insert_move_proxy<A, It> get_insert_value_proxy(A& a, BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v)
{
return insert_move_proxy<A, It>(a, v);
}
template<class It, class A>
insert_copy_proxy<A, It> get_insert_value_proxy(A& a, const typename std::iterator_traits<It>::value_type &v)
{
return insert_copy_proxy<A, It>(a, v);
}
}}} //namespace boost { namespace container { namespace container_detail {
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
@@ -181,138 +198,74 @@ namespace boost {
namespace container {
namespace container_detail {
//This class template will adapt emplace construction insertions of movable types
//to advanced_insert_aux_int
template<class A, class Iterator, class ...Args>
struct advanced_insert_aux_non_movable_emplace
: public advanced_insert_aux_int<Iterator>
struct insert_non_movable_emplace_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
explicit advanced_insert_aux_non_movable_emplace(A &a, Args&&... args)
: a_(a)
, args_(args...)
, used_(false)
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
explicit insert_non_movable_emplace_proxy(A &a, Args&&... args)
: a_(a), args_(args...)
{}
~advanced_insert_aux_non_movable_emplace()
{}
virtual void copy_remaining_to(Iterator)
//This code can't be called since value_type is not movable or copyable
{ BOOST_ASSERT(false); }
virtual void uninitialized_copy_remaining_to(Iterator p)
{ this->priv_uninitialized_copy_remaining_to(index_tuple_t(), p); }
virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
{ this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
virtual void copy_some_and_update(Iterator, difference_type, bool )
//This code can't be called since value_type is not movable or copyable
{ BOOST_ASSERT(false); }
void uninitialized_copy_n_and_update(Iterator p, size_type n)
{ this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!this->used_){
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, ::boost::forward<Args>(get<IdxPack>(this->args_))...
);
this->used_ = true;
}
}
}
template<int ...IdxPack>
void priv_uninitialized_copy_remaining_to(const index_tuple<IdxPack...>&, Iterator p)
{
if(!this->used_){
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, ::boost::forward<Args>(get<IdxPack>(this->args_))...
);
this->used_ = true;
}
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, ::boost::forward<Args>(get<IdxPack>(this->args_))...
);
}
protected:
A &a_;
tuple<Args&...> args_;
bool used_;
};
//This class template will adapt emplace construction insertions of movable types
//to advanced_insert_aux_int
template<class A, class Iterator, class ...Args>
struct advanced_insert_aux_emplace
: public advanced_insert_aux_non_movable_emplace<A, Iterator, Args...>
struct insert_emplace_proxy
: public insert_non_movable_emplace_proxy<A, Iterator, Args...>
{
typedef advanced_insert_aux_non_movable_emplace<A, Iterator, Args...> base_t;
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename base_t::value_type value_type;
typedef typename base_t::difference_type difference_type;
typedef typename base_t::index_tuple_t index_tuple_t;
typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t;
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename base_t::value_type value_type;
typedef typename base_t::size_type size_type;
typedef typename base_t::index_tuple_t index_tuple_t;
explicit advanced_insert_aux_emplace(A &a, Args&&... args)
explicit insert_emplace_proxy(A &a, Args&&... args)
: base_t(a, ::boost::forward<Args>(args)...)
{}
~advanced_insert_aux_emplace()
{}
//Override only needed functions
virtual void copy_remaining_to(Iterator p)
{ this->priv_copy_remaining_to(index_tuple_t(), p); }
virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
{ this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
void copy_n_and_update(Iterator p, size_type n)
{ this->priv_copy_some_and_update(index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
void priv_copy_remaining_to(const index_tuple<IdxPack...>&, Iterator p)
{
if(!this->used_){
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(this->a_, vp,
::boost::forward<Args>(get<IdxPack>(this->args_))...);
scoped_destructor<A> d(this->a_, vp);
*p = ::boost::move(*vp);
d.release();
this->used_ = true;
}
}
template<int ...IdxPack>
void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!this->used_){
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(this->a_, vp,
::boost::forward<Args>(get<IdxPack>(this->args_))...);
try {
*p = ::boost::move(*vp);
} catch (...) {
alloc_traits::destroy(this->a_, vp);
throw;
}
alloc_traits::destroy(this->a_, vp);
this->used_ = true;
}
BOOST_ASSERT(n ==1); (void)n;
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(this->a_, vp,
::boost::forward<Args>(get<IdxPack>(this->args_))...);
BOOST_TRY{
*p = ::boost::move(*vp);
}
BOOST_CATCH(...){
alloc_traits::destroy(this->a_, vp);
BOOST_RETHROW
}
BOOST_CATCH_END
alloc_traits::destroy(this->a_, vp);
}
};
@@ -327,115 +280,73 @@ namespace boost {
namespace container {
namespace container_detail {
#define BOOST_PP_LOCAL_MACRO(n) \
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \
: public advanced_insert_aux_int<Iterator> \
#define BOOST_PP_LOCAL_MACRO(N) \
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
{ \
typedef boost::container::allocator_traits<A> alloc_traits; \
typedef typename allocator_traits<A>::size_type size_type; \
typedef typename allocator_traits<A>::value_type value_type; \
typedef typename advanced_insert_aux_int<Iterator>::difference_type \
difference_type; \
typedef typename alloc_traits::size_type size_type; \
typedef typename alloc_traits::value_type value_type; \
\
BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \
( A &a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
( A &a BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
: a_(a) \
, used_(false) \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_INIT, _) \
{} \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \
{} \
\
virtual void copy_remaining_to(Iterator) \
{ BOOST_ASSERT(false); } \
\
virtual void uninitialized_copy_remaining_to(Iterator p) \
void uninitialized_copy_n_and_update(Iterator p, size_type n) \
{ \
if(!this->used_){ \
alloc_traits::construct \
( this->a_ \
, container_detail::to_raw_pointer(&*p) \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
); \
this->used_ = true; \
} \
BOOST_ASSERT(n == 1); (void)n; \
alloc_traits::construct \
( this->a_ \
, container_detail::to_raw_pointer(&*p) \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
); \
} \
\
virtual void uninitialized_copy_some_and_update \
(Iterator p, difference_type division_count, bool first_n) \
{ \
BOOST_ASSERT(division_count <=1); \
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
if(!this->used_){ \
alloc_traits::construct \
( this->a_ \
, container_detail::to_raw_pointer(&*p) \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
); \
this->used_ = true; \
} \
} \
} \
\
virtual void copy_some_and_update(Iterator, difference_type, bool) \
void copy_n_and_update(Iterator, size_type) \
{ BOOST_ASSERT(false); } \
\
protected: \
A &a_; \
bool used_; \
BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
}; \
\
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
: BOOST_PP_CAT(BOOST_PP_CAT( \
advanced_insert_aux_non_movable_emplace, n), arg) \
< A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P) > \
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
: BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
< A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \
{ \
typedef BOOST_PP_CAT(BOOST_PP_CAT( \
advanced_insert_aux_non_movable_emplace, n), arg) \
<A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P) > base_t; \
typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
<A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \
typedef typename base_t::value_type value_type; \
typedef typename base_t::difference_type difference_type; \
typedef typename base_t::size_type size_type; \
typedef boost::container::allocator_traits<A> alloc_traits; \
\
BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
( A &a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
: base_t(a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
{} \
BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
( A &a BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
: base_t(a BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
{} \
\
virtual void copy_remaining_to(Iterator p) \
void copy_n_and_update(Iterator p, size_type n) \
{ \
if(!this->used_){ \
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
alloc_traits::construct(this->a_, vp \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
scoped_destructor<A> d(this->a_, vp); \
BOOST_ASSERT(n == 1); (void)n; \
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
alloc_traits::construct(this->a_, vp \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
BOOST_TRY{ \
*p = ::boost::move(*vp); \
d.release(); \
this->used_ = true; \
} \
} \
\
virtual void copy_some_and_update \
(Iterator p, difference_type division_count, bool first_n) \
{ \
BOOST_ASSERT(division_count <=1); \
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
if(!this->used_){ \
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
alloc_traits::construct(this->a_, vp \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
scoped_destructor<A> d(this->a_, vp); \
*p = ::boost::move(*vp); \
d.release(); \
this->used_ = true; \
} \
BOOST_CATCH(...){ \
alloc_traits::destroy(this->a_, vp); \
BOOST_RETHROW \
} \
BOOST_CATCH_END \
alloc_traits::destroy(this->a_, vp); \
} \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()

View File

@@ -0,0 +1,163 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp> //allocator_traits
#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
#include <boost/container/detail/version_type.hpp> //version_type
#include <boost/container/detail/allocation_type.hpp> //allocation_type
#include <boost/container/detail/mpl.hpp> //integral_constant
#include <boost/intrusive/pointer_traits.hpp> //pointer_traits
#include <utility> //pair
#include <stdexcept> //runtime_error
#include <boost/detail/no_exceptions_support.hpp> //BOOST_TRY
namespace boost {
namespace container {
namespace container_detail {
template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
struct allocator_version_traits
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, Version> alloc_version;
typedef typename Allocator::multiallocation_chain multiallocation_chain;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
//Node allocation interface
static pointer allocate_one(Allocator &a)
{ return a.allocate_one(); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate_one(p); }
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
{ return a.allocate_individual(n, m); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{ a.deallocate_individual(holder); }
static std::pair<pointer, bool>
allocation_command(Allocator &a, allocation_type command,
size_type limit_size, size_type preferred_size,
size_type &received_size, const pointer &reuse)
{
return a.allocation_command
(command, limit_size, preferred_size, received_size, reuse);
}
};
template<class Allocator>
struct allocator_version_traits<Allocator, 1>
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, 1> alloc_version;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
typedef typename boost::intrusive::pointer_traits<pointer>::
template rebind_pointer<void>::type void_ptr;
typedef container_detail::basic_multiallocation_chain
<void_ptr> multialloc_cached_counted;
typedef boost::container::container_detail::
transform_multiallocation_chain
< multialloc_cached_counted, value_type> multiallocation_chain;
//Node allocation interface
static pointer allocate_one(Allocator &a)
{ return a.allocate(1); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate(p, 1); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{
while(!holder.empty()){
a.deallocate(holder.pop_front(), 1);
}
}
struct allocate_individual_rollback
{
allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
: mr_a(a), mp_chain(&chain)
{}
~allocate_individual_rollback()
{
if(mp_chain)
allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
}
void release()
{
mp_chain = 0;
}
Allocator &mr_a;
multiallocation_chain * mp_chain;
};
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
{
allocate_individual_rollback rollback(a, m);
while(n--){
m.push_front(a.allocate(1));
}
rollback.release();
}
static std::pair<pointer, bool>
allocation_command(Allocator &a, allocation_type command,
size_type, size_type preferred_size,
size_type &received_size, const pointer &)
{
std::pair<pointer, bool> ret(pointer(), false);
if(!(command & allocate_new)){
if(!(command & nothrow_allocation)){
throw std::runtime_error("version 1 allocator without allocate_new flag");
}
}
else{
received_size = preferred_size;
BOOST_TRY{
ret.first = a.allocate(received_size);
}
BOOST_CATCH(...){
if(!(command & nothrow_allocation)){
BOOST_RETHROW
}
}
BOOST_CATCH_END
}
return ret;
}
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)

View File

@@ -188,13 +188,17 @@ struct scoped_destructor_n
void increment_size_backwards(size_type inc)
{ m_n += inc; m_p -= inc; }
void shrink_forward(size_type inc)
{ m_n -= inc; m_p += inc; }
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
for(size_type i = 0; i < m_n; ++i, ++raw_ptr)
while(m_n--){
AllocTraits::destroy(m_a, raw_ptr);
}
}
private:
@@ -323,7 +327,7 @@ class allocator_destroyer_and_chain_builder
void operator()(const typename A::pointer &p)
{
allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
c_.push_front(p);
c_.push_back(p);
}
};
@@ -348,8 +352,7 @@ class allocator_multialloc_chain_node_deallocator
~allocator_multialloc_chain_node_deallocator()
{
if(!c_.empty())
a_.deallocate_individual(boost::move(c_));
a_.deallocate_individual(c_);
}
};

View File

@@ -25,7 +25,7 @@
#include <utility>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/pair.hpp>
@@ -48,7 +48,7 @@ class flat_tree_value_compare
typedef Value first_argument_type;
typedef Value second_argument_type;
typedef bool return_type;
public:
public:
flat_tree_value_compare()
: Compare()
{}
@@ -65,7 +65,7 @@ class flat_tree_value_compare
const Compare &get_comp() const
{ return *this; }
Compare &get_comp()
{ return *this; }
};
@@ -238,7 +238,7 @@ class flat_tree
flat_tree& operator=(BOOST_RV_REF(flat_tree) mx)
{ m_data = boost::move(mx.m_data); return *this; }
public:
public:
// accessors:
Compare key_comp() const
{ return this->m_data.get_comp(); }
@@ -441,17 +441,17 @@ class flat_tree
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
const const_iterator beg(this->cbegin());
const_iterator pos(beg);
const const_iterator b(this->cbegin());
const_iterator pos(b);
//Loop in burst sizes
while(len){
const size_type burst = len < BurstSize ? len : BurstSize;
const const_iterator cend_(this->cend());
const const_iterator ce(this->cend());
len -= burst;
for(size_type i = 0; i != burst; ++i){
//Get the insertion position for each key
pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, cend_, KeyOfValue()(*first));
positions[i] = static_cast<size_type>(pos - beg);
pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, ce, KeyOfValue()(*first));
positions[i] = static_cast<size_type>(pos - b);
++first;
}
//Insert all in a single step in the precalculated positions
@@ -489,22 +489,22 @@ class flat_tree
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
const const_iterator beg(this->cbegin());
const_iterator pos(beg);
const const_iterator b(this->cbegin());
const_iterator pos(b);
const value_compare &value_comp = this->m_data;
skips[0u] = 0u;
//Loop in burst sizes
while(len){
const size_type burst = len < BurstSize ? len : BurstSize;
size_type unique_burst = 0u;
const const_iterator cend_(this->cend());
const const_iterator ce(this->cend());
while(unique_burst < burst && len > 0){
//Get the insertion position for each key
const value_type & val = *first++;
--len;
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, cend_, KeyOfValue()(val));
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
//Check if already present
if(pos != cend_ && !value_comp(val, *pos)){
if(pos != ce && !value_comp(val, *pos)){
if(unique_burst > 0){
++skips[unique_burst-1];
}
@@ -512,7 +512,7 @@ class flat_tree
}
//If not present, calculate position
positions[unique_burst] = static_cast<size_type>(pos - beg);
positions[unique_burst] = static_cast<size_type>(pos - b);
skips[unique_burst++] = 0u;
}
if(unique_burst){
@@ -692,22 +692,22 @@ class flat_tree
// set operations:
iterator find(const key_type& k)
{
const Compare &key_comp_ = this->m_data.get_comp();
const Compare &key_cmp = this->m_data.get_comp();
iterator i = this->lower_bound(k);
if (i != this->end() && key_comp_(k, KeyOfValue()(*i))){
i = this->end();
if (i != this->end() && key_cmp(k, KeyOfValue()(*i))){
i = this->end();
}
return i;
}
const_iterator find(const key_type& k) const
{
const Compare &key_comp_ = this->m_data.get_comp();
const Compare &key_cmp = this->m_data.get_comp();
const_iterator i = this->lower_bound(k);
if (i != this->end() && key_comp_(k, KeyOfValue()(*i))){
i = this->end();
if (i != this->end() && key_cmp(k, KeyOfValue()(*i))){
i = this->end();
}
return i;
}
@@ -737,11 +737,11 @@ class flat_tree
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
{ return this->priv_equal_range(this->begin(), this->end(), k); }
size_type capacity() const
size_type capacity() const
{ return this->m_data.m_vect.capacity(); }
void reserve(size_type count_)
{ this->m_data.m_vect.reserve(count_); }
void reserve(size_type cnt)
{ this->m_data.m_vect.reserve(cnt); }
private:
struct insert_commit_data
@@ -780,13 +780,13 @@ class flat_tree
}
std::pair<iterator,bool> priv_insert_unique_prepare
(const_iterator beg, const_iterator end_, const value_type& val, insert_commit_data &commit_data)
(const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data)
{
const value_compare &value_comp = this->m_data;
commit_data.position = this->priv_lower_bound(beg, end_, KeyOfValue()(val));
commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
return std::pair<iterator,bool>
( *reinterpret_cast<iterator*>(&commit_data.position)
, commit_data.position == end_ || value_comp(val, *commit_data.position));
, commit_data.position == e || value_comp(val, *commit_data.position));
}
std::pair<iterator,bool> priv_insert_unique_prepare
@@ -854,7 +854,7 @@ class flat_tree
RanIt priv_lower_bound(RanIt first, RanIt last,
const key_type & key) const
{
const Compare &key_comp_ = this->m_data.get_comp();
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
difference_type len = last - first, half;
RanIt middle;
@@ -864,7 +864,7 @@ class flat_tree
middle = first;
middle += half;
if (key_comp_(key_extract(*middle), key)) {
if (key_cmp(key_extract(*middle), key)) {
++middle;
first = middle;
len = len - half - 1;
@@ -879,7 +879,7 @@ class flat_tree
RanIt priv_upper_bound(RanIt first, RanIt last,
const key_type & key) const
{
const Compare &key_comp_ = this->m_data.get_comp();
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
difference_type len = last - first, half;
RanIt middle;
@@ -889,12 +889,12 @@ class flat_tree
middle = first;
middle += half;
if (key_comp_(key, key_extract(*middle))) {
if (key_cmp(key, key_extract(*middle))) {
len = half;
}
else{
first = ++middle;
len = len - half - 1;
len = len - half - 1;
}
}
return first;
@@ -904,7 +904,7 @@ class flat_tree
std::pair<RanIt, RanIt>
priv_equal_range(RanIt first, RanIt last, const key_type& key) const
{
const Compare &key_comp_ = this->m_data.get_comp();
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
difference_type len = last - first, half;
RanIt middle, left, right;
@@ -914,12 +914,12 @@ class flat_tree
middle = first;
middle += half;
if (key_comp_(key_extract(*middle), key)){
if (key_cmp(key_extract(*middle), key)){
first = middle;
++first;
len = len - half - 1;
}
else if (key_comp_(key, key_extract(*middle))){
else if (key_cmp(key, key_extract(*middle))){
len = half;
}
else {
@@ -1033,7 +1033,7 @@ template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<K, V, KOV, C, A> >
{
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {

View File

@@ -20,7 +20,7 @@
#include "config_begin.hpp"
#include <boost/container/detail/workaround.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/type_traits.hpp>

View File

@@ -19,7 +19,7 @@
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
namespace boost {
namespace container {
@@ -50,41 +50,38 @@ class basic_multiallocation_chain
typedef typename boost::intrusive::
pointer_traits<node_ptr> node_ptr_traits;
static node & build_node(const VoidPointer &p)
{
return *::new (static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p)))) node;
}
static node & to_node(const VoidPointer &p)
{ return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
static VoidPointer destroy_node(node &n)
{
VoidPointer retptr = node_ptr_traits::pointer_to(n);
n.~node();
return retptr;
}
static VoidPointer from_node(node &n)
{ return node_ptr_traits::pointer_to(n); }
static node_ptr to_node_ptr(VoidPointer p)
static node_ptr to_node_ptr(const VoidPointer &p)
{ return node_ptr_traits::static_cast_from(p); }
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
public:
typedef VoidPointer void_pointer;
typedef typename slist_impl_t::iterator iterator;
typedef typename slist_impl_t::size_type size_type;
typedef VoidPointer void_pointer;
typedef typename slist_impl_t::iterator iterator;
typedef typename slist_impl_t::size_type size_type;
basic_multiallocation_chain()
: slist_impl_()
{}
basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
: slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
{}
basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
: slist_impl_()
{ slist_impl_.swap(other.slist_impl_); }
: slist_impl_(::boost::move(other.slist_impl_))
{}
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
{
basic_multiallocation_chain tmp(boost::move(other));
this->swap(tmp);
slist_impl_ = ::boost::move(other.slist_impl_);
return *this;
}
@@ -110,43 +107,54 @@ class basic_multiallocation_chain
{ slist_impl_.clear(); }
iterator insert_after(iterator it, void_pointer m)
{ return slist_impl_.insert_after(it, build_node(m)); }
{ return slist_impl_.insert_after(it, to_node(m)); }
void push_front(void_pointer m)
{ return slist_impl_.push_front(build_node(m)); }
void push_front(const void_pointer &m)
{ return slist_impl_.push_front(to_node(m)); }
void push_back(void_pointer m)
{ return slist_impl_.push_back(build_node(m)); }
void push_back(const void_pointer &m)
{ return slist_impl_.push_back(to_node(m)); }
void_pointer pop_front()
{
node & n = slist_impl_.front();
void_pointer ret = destroy_node(n);
void_pointer ret = from_node(n);
slist_impl_.pop_front();
return ret;
}
void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_begin_, iterator before_end)
{ slist_impl_.splice_after(after_this, x.slist_impl_, before_begin_, before_end); }
void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_begin_, iterator before_end, size_type n)
{ slist_impl_.splice_after(after_this, x.slist_impl_, before_begin_, before_end, n); }
void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
{ slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
void splice_after(iterator after_this, basic_multiallocation_chain &x)
{ slist_impl_.splice_after(after_this, x.slist_impl_); }
void incorporate_after(iterator after_this, void_pointer begin_ , iterator before_end)
void erase_after(iterator before_b, iterator e, size_type n)
{ slist_impl_.erase_after(before_b, e, n); }
void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
{
slist_impl_.incorporate_after(after_this, to_node_ptr(begin_), to_node_ptr(before_end));
typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
char_ptr elem = char_pointer_traits::static_cast_from(b);
if(num_units){
char_ptr prev_elem = elem;
elem += unit_bytes;
for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem);
prev_elem = elem;
}
slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
}
return elem;
}
void incorporate_after(iterator after_this, void_pointer begin_, void_pointer before_end, size_type n)
{ slist_impl_.incorporate_after(after_this, to_node_ptr(begin_), to_node_ptr(before_end), n); }
void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
{ slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
void swap(basic_multiallocation_chain &x)
{ slist_impl_.swap(x.slist_impl_); }
static iterator iterator_to(void_pointer p)
static iterator iterator_to(const void_pointer &p)
{ return slist_impl_t::s_iterator_to(to_node(p)); }
std::pair<void_pointer, void_pointer> extract_data()
@@ -170,11 +178,13 @@ struct cast_functor
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
: public MultiallocationChain
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
//transform_multiallocation_chain(const transform_multiallocation_chain &);
//transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
MultiallocationChain holder_;
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::intrusive::pointer_traits
<void_pointer> void_pointer_traits;
@@ -193,39 +203,41 @@ class transform_multiallocation_chain
typedef typename MultiallocationChain::size_type size_type;
transform_multiallocation_chain()
: holder_()
: MultiallocationChain()
{}
transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
: holder_()
{ this->swap(other); }
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
{}
transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
: holder_(boost::move(other))
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
{}
transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
{
transform_multiallocation_chain tmp(boost::move(other));
this->swap(tmp);
return *this;
return static_cast<MultiallocationChain&>
(this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
}
void push_front(pointer mem)
/*
void push_front(const pointer &mem)
{ holder_.push_front(mem); }
void push_back(const pointer &mem)
{ return holder_.push_back(mem); }
void swap(transform_multiallocation_chain &other_chain)
{ holder_.swap(other_chain.holder_); }
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin_, iterator before_end, size_type n)
{ holder_.splice_after(after_this.base(), x.holder_, before_begin_.base(), before_end.base(), n); }
void incorporate_after(iterator after_this, pointer begin_, pointer before_end, size_type n)
{ holder_.incorporate_after(after_this.base(), begin_, before_end, n); }
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
{ holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); }
void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
{ holder_.incorporate_after(after_this.base(), b, before_e, n); }
*/
pointer pop_front()
{ return cast(holder_.pop_front()); }
{ return cast(this->MultiallocationChain::pop_front()); }
/*
bool empty() const
{ return holder_.empty(); }
@@ -246,23 +258,21 @@ class transform_multiallocation_chain
void clear()
{ holder_.clear(); }
*/
iterator insert_after(iterator it, pointer m)
{ return iterator(holder_.insert_after(it.base(), m)); }
{ return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
static iterator iterator_to(pointer p)
static iterator iterator_to(const pointer &p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
std::pair<pointer, pointer> extract_data()
{
std::pair<void_pointer, void_pointer> data(holder_.extract_data());
std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data());
return std::pair<pointer, pointer>(cast(data.first), cast(data.second));
}
MultiallocationChain extract_multiallocation_chain()
{
return MultiallocationChain(boost::move(holder_));
}
/*
MultiallocationChain &extract_multiallocation_chain()
{ return holder_; }*/
};
}}}

View File

@@ -21,7 +21,7 @@
#include <utility>
#include <functional>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/container/detail/version_type.hpp>
@@ -30,6 +30,8 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
@@ -89,6 +91,7 @@ struct node_alloc_holder
typedef typename ICont::const_iterator icont_citerator;
typedef allocator_destroyer<NodeAlloc> Destroyer;
typedef allocator_traits<NodeAlloc> NodeAllocTraits;
typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
private:
BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
@@ -151,22 +154,10 @@ struct node_alloc_holder
{ return allocator_traits_type::max_size(this->node_alloc()); }
NodePtr allocate_one()
{ return this->allocate_one(alloc_version()); }
NodePtr allocate_one(allocator_v1)
{ return this->node_alloc().allocate(1); }
NodePtr allocate_one(allocator_v2)
{ return this->node_alloc().allocate_one(); }
{ return AllocVersionTraits::allocate_one(this->node_alloc()); }
void deallocate_one(const NodePtr &p)
{ return this->deallocate_one(p, alloc_version()); }
void deallocate_one(const NodePtr &p, allocator_v1)
{ this->node_alloc().deallocate(p, 1); }
void deallocate_one(const NodePtr &p, allocator_v2)
{ this->node_alloc().deallocate_one(p); }
{ AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -235,40 +226,51 @@ struct node_alloc_holder
}
template<class FwdIterator, class Inserter>
FwdIterator allocate_many_and_construct
void allocate_many_and_construct
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
/*
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it);
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
return (p);
*/
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
//Try to allocate memory in a single block
multiallocation_chain mem(this->node_alloc().allocate_individual(n));
int constructed = 0;
Node *p = 0;
BOOST_TRY{
for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
p = container_detail::to_raw_pointer(mem.pop_front());
//This can throw
constructed = 0;
boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), beg);
++constructed;
//This does not throw
typedef typename Node::hook_type hook_type;
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
//This can throw in some containers (predicate might throw)
inserter(*p);
}
//Try to allocate memory in a single block
typedef typename multiallocation_chain::iterator multialloc_iterator;
multiallocation_chain mem;
this->node_alloc().allocate_individual(n, mem);
multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
mem.clear();
Node *p = 0;
NodeAlloc &nalloc = this->node_alloc();
BOOST_TRY{
while(n--){
p = container_detail::to_raw_pointer(&*itbeg);
++itbeg;
//This can throw
Deallocator node_deallocator(p, nalloc);
boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg);
++beg;
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
::new(static_cast<hook_type*>(p)) hook_type;
//This can throw in some containers (predicate might throw)
inserter(*p);
}
BOOST_CATCH(...){
if(constructed){
allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(p));
}
this->node_alloc().deallocate_individual(boost::move(mem));
BOOST_RETHROW
}
BOOST_CATCH_END
}
return beg;
BOOST_CATCH(...){
mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
this->node_alloc().deallocate_individual(mem);
BOOST_RETHROW
}
BOOST_CATCH_END
}
void clear(allocator_v1)
@@ -281,7 +283,7 @@ struct node_alloc_holder
this->icont().clear_and_dispose(builder);
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
if(!chain.empty())
this->node_alloc().deallocate_individual(boost::move(chain));
this->node_alloc().deallocate_individual(chain);
}
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1)
@@ -289,8 +291,13 @@ struct node_alloc_holder
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2)
{
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder());
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
NodeAlloc & nalloc = this->node_alloc();
multiallocation_chain chain;
allocator_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
nalloc.deallocate_individual(chain);
return ret_it;
}
template<class Key, class Comparator>

View File

@@ -26,10 +26,12 @@
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <cstddef>
#include <functional> //std::unary_function
namespace boost {
namespace container {
namespace container_detail {
@@ -85,19 +87,19 @@ class private_node_pool_impl
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
void *allocate_node()
{ return priv_alloc_node(); }
{ return this->priv_alloc_node(); }
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
{ priv_dealloc_node(ptr); }
{ this->priv_dealloc_node(ptr); }
//!Allocates a singly linked list of n nodes ending in null pointer.
multiallocation_chain allocate_nodes(const size_type n)
void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
//Preallocate all needed blocks to fulfill the request
size_type cur_nodes = m_freelist.size();
if(cur_nodes < n){
priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
this->priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
}
//We just iterate the needed nodes to get the last we'll erase
@@ -118,20 +120,18 @@ class private_node_pool_impl
//Now take the last erased node and just splice it in the end
//of the intrusive list that will be traversed by the multialloc iterator.
multiallocation_chain chain;
chain.incorporate_after(chain.before_begin(), &*first_node, &*last_node, n);
m_allocated += n;
return boost::move(chain);
}
void deallocate_nodes(multiallocation_chain chain)
void deallocate_nodes(multiallocation_chain &chain)
{
typedef typename multiallocation_chain::iterator iterator;
iterator it(chain.begin()), itend(chain.end());
while(it != itend){
void *pElem = &*it;
++it;
priv_dealloc_node(pElem);
this->priv_dealloc_node(pElem);
}
}
@@ -275,7 +275,7 @@ class private_node_pool_impl
{
//If there are no free nodes we allocate a new block
if (m_freelist.empty())
priv_alloc_block();
this->priv_alloc_block(1);
//We take the first free node
node_t *n = (node_t*)&m_freelist.front();
m_freelist.pop_front();
@@ -295,14 +295,13 @@ class private_node_pool_impl
}
//!Allocates several blocks of nodes. Can throw
void priv_alloc_block(size_type num_blocks = 1)
void priv_alloc_block(size_type num_blocks)
{
if(!num_blocks)
return;
BOOST_ASSERT(num_blocks > 0);
size_type blocksize =
get_rounded_size(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
try{
BOOST_TRY{
for(size_type i = 0; i != num_blocks; ++i){
//We allocate a new NodeBlock and put it as first
//element in the free Node list
@@ -313,15 +312,16 @@ class private_node_pool_impl
//We initialize all Nodes in Node Block to insert
//them in the free Node list
for(size_type i = 0; i < m_nodes_per_block; ++i, pNode += m_real_node_size){
for(size_type j = 0; j < m_nodes_per_block; ++j, pNode += m_real_node_size){
m_freelist.push_front(*new (pNode) node_t);
}
}
}
catch(...){
BOOST_CATCH(...){
//to-do: if possible, an efficient way to deallocate allocated blocks
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
//!Deprecated, use deallocate_free_blocks

View File

@@ -27,7 +27,7 @@
#include <utility> //std::pair
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/type_traits/is_class.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING

View File

@@ -34,7 +34,7 @@ struct node_slist
typedef slist_hook_t node_t;
typedef typename bi::make_slist
<node_t, bi::linear<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
<node_t, bi::linear<true>, bi::cache_last<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
};
template<class T>

View File

@@ -17,6 +17,7 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/move/utility.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//#error "This file is not needed when perfect forwarding is available"
@@ -38,6 +39,7 @@
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/move/utility.hpp>
#define BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS 10
@@ -97,7 +99,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
template<class T>
struct ref_holder<T &>
{
ref_holder(T &t)
explicit ref_holder(T &t)
: t_(t)
{}
T &t_;
@@ -107,7 +109,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
template<class T>
struct ref_holder<const T>
{
ref_holder(const T &t)
explicit ref_holder(const T &t)
: t_(t)
{}
const T &t_;
@@ -117,7 +119,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
template<class T>
struct ref_holder<const T &&>
{
ref_holder(const T &t)
explicit ref_holder(const T &t)
: t_(t)
{}
const T &t_;
@@ -127,7 +129,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
template<class T>
struct ref_holder
{
ref_holder(T &&t)
explicit ref_holder(T &&t)
: t_(t)
{}
T &t_;
@@ -137,10 +139,10 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
template<class T>
struct ref_holder<T &&>
{
ref_holder(T &&t)
: t(t)
explicit ref_holder(T &&t)
: t_(t)
{}
T &t;
T &t_;
T && get() { return ::boost::move(t_); }
};

View File

@@ -15,7 +15,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
@@ -28,6 +28,7 @@
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -247,19 +248,20 @@ class rbtree
{
if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw)
try{
BOOST_TRY{
//This can throw
p->do_assign(other.m_data);
return p;
}
catch(...){
BOOST_CATCH(...){
//If there is an exception destroy the whole source
m_holder.destroy_node(p);
while((p = m_icont.unlink_leftmost_without_rebalance())){
m_holder.destroy_node(p);
}
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
else{
return m_holder.create_node(other.m_data);
@@ -284,19 +286,20 @@ class rbtree
{
if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw)
try{
BOOST_TRY{
//This can throw
p->do_move_assign(const_cast<Node &>(other).m_data);
return p;
}
catch(...){
BOOST_CATCH(...){
//If there is an exception destroy the whole source
m_holder.destroy_node(p);
while((p = m_icont.unlink_leftmost_without_rebalance())){
m_holder.destroy_node(p);
}
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
else{
return m_holder.create_node(other.m_data);
@@ -1121,7 +1124,7 @@ class C, class A>
struct has_trivial_destructor_after_move
<boost::container::container_detail::rbtree<K, V, KOV, C, A> >
{
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {

View File

@@ -21,7 +21,7 @@
#include "config_begin.hpp"
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
namespace boost {
namespace container {

View File

@@ -18,11 +18,14 @@
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_member_pointer.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <algorithm>
#include <iterator>
namespace boost {
namespace container {
@@ -123,16 +126,6 @@ struct ct_rounded_size
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
template<class T>
struct move_const_ref_type
: if_c
// < ::boost::is_fundamental<T>::value || ::boost::is_pointer<T>::value || ::boost::is_member_pointer<T>::value || ::boost::is_enum<T>::value
< !::boost::is_class<T>::value
,const T &
,BOOST_CATCH_CONST_RLVALUE(T)
>
{};
} //namespace container_detail {
//////////////////////////////////////////////////////////////////////////////
@@ -154,13 +147,95 @@ template
typename F> // F models ForwardIterator
F uninitialized_move_alloc(A &a, I f, I l, F r)
{
while (f != l) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
++f; ++r;
F back = r;
BOOST_TRY{
while (f != l) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return r;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move_alloc_n
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
//! for (; n--; ++result, ++first)
//! allocator_traits::construct(a, &*result, boost::move(*first));
//! \endcode
//!
//! <b>Returns</b>: result
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
while (n--) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return r;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move_alloc_n_source
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
//! for (; n--; ++result, ++first)
//! allocator_traits::construct(a, &*result, boost::move(*first));
//! \endcode
//!
//! <b>Returns</b>: first (after incremented)
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
I uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
while (n--) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return f;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc
@@ -180,13 +255,95 @@ template
typename F> // F models ForwardIterator
F uninitialized_copy_alloc(A &a, I f, I l, F r)
{
while (f != l) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
++f; ++r;
F back = r;
BOOST_TRY{
while (f != l) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return r;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc_n
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
//! for (; n--; ++result, ++first)
//! allocator_traits::construct(a, &*result, *first);
//! \endcode
//!
//! <b>Returns</b>: result
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
F uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
while (n--) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return r;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc_n_source
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
//! for (; n--; ++result, ++first)
//! allocator_traits::construct(a, &*result, *first);
//! \endcode
//!
//! <b>Returns</b>: first (after incremented)
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
I uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
while (n--) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return f;
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc
@@ -206,10 +363,20 @@ template
typename T>
void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
{
while (f != l) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*f), t);
++f;
F back = f;
BOOST_TRY{
while (f != l) {
allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*f), t);
++f;
}
}
BOOST_CATCH(...){
for (; back != l; ++back){
allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
//////////////////////////////////////////////////////////////////////////////
@@ -242,6 +409,168 @@ F uninitialized_copy_or_move_alloc
return ::boost::container::uninitialized_copy_alloc(a, f, l, r);
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_or_move_alloc_n
//
//////////////////////////////////////////////////////////////////////////////
template
<typename A
,typename I // I models InputIterator
,typename F> // F models ForwardIterator
F uninitialized_copy_or_move_alloc_n
(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::enable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
return ::boost::container::uninitialized_move_alloc_n(a, f, n, r);
}
template
<typename A
,typename I // I models InputIterator
,typename F> // F models ForwardIterator
F uninitialized_copy_or_move_alloc_n
(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::disable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
return ::boost::container::uninitialized_copy_alloc_n(a, f, n, r);
}
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_or_move_alloc_n_source
//
//////////////////////////////////////////////////////////////////////////////
template
<typename A
,typename I // I models InputIterator
,typename F> // F models ForwardIterator
I uninitialized_copy_or_move_alloc_n_source
(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::enable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
return ::boost::container::uninitialized_move_alloc_n_source(a, f, n, r);
}
template
<typename A
,typename I // I models InputIterator
,typename F> // F models ForwardIterator
I uninitialized_copy_or_move_alloc_n_source
(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::disable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
return ::boost::container::uninitialized_copy_alloc_n_source(a, f, n, r);
}
//////////////////////////////////////////////////////////////////////////////
//
// copy_or_move
//
//////////////////////////////////////////////////////////////////////////////
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline F copy_or_move(I f, I l, F r
,typename boost::container::container_detail::enable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
while (f != l) {
*r = ::boost::move(*f);
++f; ++r;
}
return r;
}
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline F copy_or_move(I f, I l, F r
,typename boost::container::container_detail::disable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
while (f != l) {
*r = *f;
++f; ++r;
}
return r;
}
//////////////////////////////////////////////////////////////////////////////
//
// copy_or_move_n
//
//////////////////////////////////////////////////////////////////////////////
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline F copy_or_move_n(I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::enable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
while (n--) {
*r = ::boost::move(*f);
++f; ++r;
}
return r;
}
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline F copy_or_move_n(I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::disable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
while (n--) {
*r = *f;
++f; ++r;
}
return r;
}
//////////////////////////////////////////////////////////////////////////////
//
// copy_or_move_n_source
//
//////////////////////////////////////////////////////////////////////////////
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline I copy_or_move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::enable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
while (n--) {
*r = ::boost::move(*f);
++f; ++r;
}
return f;
}
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline I copy_or_move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r
,typename boost::container::container_detail::disable_if
< boost::move_detail::is_move_iterator<I> >::type* = 0)
{
while (n--) {
*r = *f;
++f; ++r;
}
return f;
}
} //namespace container {
} //namespace boost {

View File

@@ -18,8 +18,12 @@
#define BOOST_CONTAINER_PERFECT_FORWARDING
#endif
#if defined(BOOST_NO_CXX11_NOEXCEPT)
#define BOOST_CONTAINER_NOEXCEPT
#if defined(BOOST_NO_NOEXCEPT)
#if defined(BOOST_MSVC)
#define BOOST_CONTAINER_NOEXCEPT throw()
#else
#define BOOST_CONTAINER_NOEXCEPT
#endif
#define BOOST_CONTAINER_NOEXCEPT_IF(x)
#else
#define BOOST_CONTAINER_NOEXCEPT noexcept

View File

@@ -27,8 +27,8 @@
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
namespace boost {
namespace container {
@@ -251,7 +251,7 @@ class flat_map
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -261,7 +261,7 @@ class flat_map
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -271,7 +271,7 @@ class flat_map
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//////////////////////////////////////////////
@@ -285,7 +285,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -293,7 +293,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -301,7 +301,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -309,7 +309,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -318,7 +318,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -327,7 +327,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -336,7 +336,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -345,7 +345,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -353,7 +353,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -361,7 +361,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -370,7 +370,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -379,7 +379,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
//////////////////////////////////////////////
@@ -393,7 +393,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -401,7 +401,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -409,7 +409,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.max_size(); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
@@ -418,7 +418,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -428,10 +428,10 @@ class flat_map
//!
//! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
//!
//! <b>Note</b>: If capacity() is less than "count", iterators and references to
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.
void reserve(size_type count_)
{ m_flat_tree.reserve(count_); }
void reserve(size_type cnt)
{ m_flat_tree.reserve(cnt); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
// with previous allocations. The size of the vector is unchanged
@@ -740,7 +740,7 @@ class flat_map
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ m_flat_tree.clear(); }
//////////////////////////////////////////////
@@ -900,15 +900,15 @@ inline void swap(flat_map<Key,T,Compare,Allocator>& x,
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class T, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::flat_map<K, T, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
// Forward declaration of operators < and ==, needed for friend declaration.
@@ -1099,7 +1099,7 @@ class flat_multimap
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -1109,7 +1109,7 @@ class flat_multimap
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -1119,7 +1119,7 @@ class flat_multimap
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//////////////////////////////////////////////
@@ -1133,7 +1133,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -1141,7 +1141,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -1149,7 +1149,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -1157,7 +1157,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -1166,7 +1166,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1175,7 +1175,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -1184,7 +1184,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1193,7 +1193,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -1201,7 +1201,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -1209,7 +1209,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1218,7 +1218,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1227,7 +1227,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
//////////////////////////////////////////////
@@ -1241,7 +1241,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -1249,7 +1249,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -1257,7 +1257,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.max_size(); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
@@ -1266,7 +1266,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -1276,10 +1276,10 @@ class flat_multimap
//!
//! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
//!
//! <b>Note</b>: If capacity() is less than "count", iterators and references to
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.
void reserve(size_type count_)
{ m_flat_tree.reserve(count_); }
void reserve(size_type cnt)
{ m_flat_tree.reserve(cnt); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
// with previous allocations. The size of the vector is unchanged
@@ -1516,7 +1516,7 @@ class flat_multimap
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ m_flat_tree.clear(); }
//////////////////////////////////////////////
@@ -1655,15 +1655,15 @@ inline void swap(flat_multimap<Key,T,Compare,Allocator>& x, flat_multimap<Key,T,
/// @cond
namespace boost {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class T, class C, class Allocator>
struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {
/// @endcond

View File

@@ -25,8 +25,8 @@
#include <boost/container/detail/flat_tree.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
namespace boost {
namespace container {
@@ -197,7 +197,7 @@ class flat_set
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.get_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -207,7 +207,7 @@ class flat_set
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.get_stored_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -217,7 +217,7 @@ class flat_set
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.get_stored_allocator(); }
//////////////////////////////////////////////
@@ -231,7 +231,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.begin(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -239,7 +239,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.begin(); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -247,7 +247,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.end(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -255,7 +255,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.end(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -264,7 +264,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -273,7 +273,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -282,7 +282,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -291,7 +291,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -299,7 +299,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.cbegin(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -307,7 +307,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.cend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -316,7 +316,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.crbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -325,7 +325,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.crend(); }
@@ -340,7 +340,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -348,7 +348,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -356,7 +356,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.max_size(); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
@@ -365,7 +365,7 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -375,10 +375,10 @@ class flat_set
//!
//! <b>Throws</b>: If memory allocation allocation throws or Key's copy constructor throws.
//!
//! <b>Note</b>: If capacity() is less than "count", iterators and references to
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.
void reserve(size_type count_)
{ m_flat_tree.reserve(count_); }
void reserve(size_type cnt)
{ m_flat_tree.reserve(cnt); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
// with previous allocations. The size of the vector is unchanged
@@ -582,7 +582,7 @@ class flat_set
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ m_flat_tree.clear(); }
//////////////////////////////////////////////
@@ -726,15 +726,15 @@ inline void swap(flat_set<Key,Compare,Allocator>& x, flat_set<Key,Compare,Alloca
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::flat_set<Key, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value &&has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value &&has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
// Forward declaration of operators < and ==, needed for friend declaration.
@@ -884,7 +884,7 @@ class flat_multiset
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.get_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -894,7 +894,7 @@ class flat_multiset
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.get_stored_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -904,7 +904,7 @@ class flat_multiset
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.get_stored_allocator(); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the container.
@@ -912,7 +912,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.begin(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -928,7 +928,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -936,7 +936,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.end(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -944,7 +944,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.end(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -952,7 +952,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -961,7 +961,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -970,7 +970,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -979,7 +979,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -988,7 +988,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -997,7 +997,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.rend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1006,7 +1006,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.crend(); }
//////////////////////////////////////////////
@@ -1020,7 +1020,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -1028,7 +1028,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -1036,7 +1036,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.max_size(); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
@@ -1045,7 +1045,7 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -1055,10 +1055,10 @@ class flat_multiset
//!
//! <b>Throws</b>: If memory allocation allocation throws or Key's copy constructor throws.
//!
//! <b>Note</b>: If capacity() is less than "count", iterators and references to
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.
void reserve(size_type count_)
{ m_flat_tree.reserve(count_); }
void reserve(size_type cnt)
{ m_flat_tree.reserve(cnt); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
// with previous allocations. The size of the vector is unchanged
@@ -1244,7 +1244,7 @@ class flat_multiset
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ m_flat_tree.clear(); }
//////////////////////////////////////////////
@@ -1388,15 +1388,15 @@ inline void swap(flat_multiset<Key,Compare,Allocator>& x, flat_multiset<Key,Comp
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
/// @endcond

View File

@@ -18,8 +18,9 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/algorithms.hpp>
@@ -140,9 +141,6 @@ class list_const_iterator
friend bool operator!= (const list_const_iterator& l, const list_const_iterator& r)
{ return l.m_it != r.m_it; }
IIterator &get()
{ return this->m_it; }
const IIterator &get() const
{ return this->m_it; }
};
@@ -187,9 +185,6 @@ class list_iterator
list_iterator operator--(int)
{ IIterator tmp = this->m_it; --*this; return list_iterator(tmp); }
IIterator &get()
{ return this->m_it; }
const IIterator &get() const
{ return this->m_it; }
};
@@ -303,10 +298,10 @@ class list
//! <b>Effects</b>: Constructs a list taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
explicit list(const allocator_type &a)
explicit list(const allocator_type &a) BOOST_CONTAINER_NOEXCEPT
: AllocHolder(a)
{}
@@ -398,7 +393,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements.
~list()
~list() BOOST_CONTAINER_NOEXCEPT
{} //AllocHolder clears the list
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -498,7 +493,7 @@ class list
//! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return allocator_type(this->node_alloc()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -508,7 +503,7 @@ class list
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -518,7 +513,7 @@ class list
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
//////////////////////////////////////////////
@@ -532,7 +527,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -540,7 +535,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the list.
@@ -548,7 +543,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -556,7 +551,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -565,7 +560,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -574,7 +569,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -583,7 +578,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -592,7 +587,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -600,7 +595,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -608,7 +603,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -617,7 +612,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -626,7 +621,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->cbegin()); }
//////////////////////////////////////////////
@@ -640,7 +635,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return !this->size(); }
//! <b>Effects</b>: Returns the number of the elements contained in the list.
@@ -648,7 +643,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return this->icont().size(); }
//! <b>Effects</b>: Returns the largest possible size of the list.
@@ -656,7 +651,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return AllocHolder::max_size(); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -700,7 +695,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference front()
reference front() BOOST_CONTAINER_NOEXCEPT
{ return *this->begin(); }
//! <b>Requires</b>: !empty()
@@ -711,7 +706,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference front() const
const_reference front() const BOOST_CONTAINER_NOEXCEPT
{ return *this->begin(); }
//! <b>Requires</b>: !empty()
@@ -722,7 +717,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference back()
reference back() BOOST_CONTAINER_NOEXCEPT
{ return *(--this->end()); }
//! <b>Requires</b>: !empty()
@@ -733,7 +728,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference back() const
const_reference back() const BOOST_CONTAINER_NOEXCEPT
{ return *(--this->end()); }
//////////////////////////////////////////////
@@ -939,8 +934,10 @@ class list
{
//Optimized allocation and construction
insertion_functor func(this->icont(), p.get());
iterator before_p(p.get());
--before_p;
this->allocate_many_and_construct(first, std::distance(first, last), func);
return iterator(func.inserted_first());
return ++before_p;
}
#endif
@@ -949,7 +946,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Amortized constant time.
void pop_front()
void pop_front() BOOST_CONTAINER_NOEXCEPT
{ this->erase(this->cbegin()); }
//! <b>Effects</b>: Removes the last element from the list.
@@ -957,7 +954,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Amortized constant time.
void pop_back()
void pop_back() BOOST_CONTAINER_NOEXCEPT
{ const_iterator tmp = this->cend(); this->erase(--tmp); }
//! <b>Requires</b>: p must be a valid iterator of *this.
@@ -967,7 +964,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Amortized constant time.
iterator erase(const_iterator p)
iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this.
@@ -977,7 +974,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the distance between first and last.
iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); }
//! <b>Effects</b>: Swaps the contents of *this and x.
@@ -993,7 +990,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the list.
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ AllocHolder::clear(alloc_version()); }
//////////////////////////////////////////////
@@ -1003,13 +1000,12 @@ class list
//////////////////////////////////////////////
//! <b>Requires</b>: p must point to an element contained
//! by the list. x != *this
//! by the list. x != *this. this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers all the elements of list x to this list, before the
//! the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1017,19 +1013,18 @@ class list
//! this list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, list& x) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this != &x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice(p.get(), x.icont());
}
//! <b>Requires</b>: p must point to an element contained
//! by the list. x != *this
//! by the list. x != *this. this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers all the elements of list x to this list, before the
//! the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1040,13 +1035,13 @@ class list
//! <b>Requires</b>: p must point to an element contained
//! by this list. i must point to an element contained in list x.
//! this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//! If p == i or p == ++i, this function is a null operation.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1054,20 +1049,20 @@ class list
//! list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, list &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
//BOOST_ASSERT(this != &x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice(p.get(), x.icont(), i.get());
}
//! <b>Requires</b>: p must point to an element contained
//! by this list. i must point to an element contained in list x.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//! If p == i or p == ++i, this function is a null operation.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1078,12 +1073,12 @@ class list
//! <b>Requires</b>: p must point to an element contained
//! by this list. first and last must point to elements contained in list x.
//! this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear to the number of elements transferred.
//!
@@ -1091,19 +1086,18 @@ class list
//! list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice(p.get(), x.icont(), first.get(), last.get());
}
//! <b>Requires</b>: p must point to an element contained
//! by this list. first and last must point to elements contained in list x.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear to the number of elements transferred.
//!
@@ -1114,13 +1108,12 @@ class list
//! <b>Requires</b>: p must point to an element contained
//! by this list. first and last must point to elements contained in list x.
//! n == std::distance(first, last)
//! n == std::distance(first, last). this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1130,20 +1123,18 @@ class list
//! <b>Note</b>: Non-standard extension
void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n);
}
//! <b>Requires</b>: p must point to an element contained
//! by this list. first and last must point to elements contained in list x.
//! n == std::distance(first, last)
//! n == std::distance(first, last). this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1156,7 +1147,7 @@ class list
//! <b>Effects</b>: Removes all the elements that compare equal to value.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
//!
@@ -1184,9 +1175,9 @@ class list
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that are equal from the list.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
//! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
//!
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
@@ -1198,7 +1189,7 @@ class list
//!
//! <b>Throws</b>: If pred throws.
//!
//! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
//! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
//!
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
@@ -1216,7 +1207,7 @@ class list
//! that is, if an element from *this is equivalent to one from x, then the element
//! from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1230,7 +1221,7 @@ class list
//! that is, if an element from *this is equivalent to one from x, then the element
//! from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1245,22 +1236,18 @@ class list
//! in order into *this. The merge is stable; that is, if an element from *this is
//! equivalent to one from x, then the element from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comp throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
//!
//! <b>Note</b>: Iterators and references to *this are not invalidated.
template <class StrictWeakOrdering>
void merge(list &x, StrictWeakOrdering comp)
void merge(list &x, const StrictWeakOrdering &comp)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().merge(x.icont(),
ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
}
else{
throw std::runtime_error("list::merge called with unequal allocators");
}
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().merge(x.icont(),
ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
}
//! <b>Requires</b>: p must be a comparison function that induces a strict weak
@@ -1271,7 +1258,7 @@ class list
//! in order into *this. The merge is stable; that is, if an element from *this is
//! equivalent to one from x, then the element from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comp throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1284,7 +1271,7 @@ class list
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1296,7 +1283,7 @@ class list
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comp throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1318,7 +1305,7 @@ class list
//! <b>Complexity</b>: This function is linear time.
//!
//! <b>Note</b>: Iterators and references are not invalidated
void reverse()
void reverse() BOOST_CONTAINER_NOEXCEPT
{ this->icont().reverse(); }
/// @cond
@@ -1382,31 +1369,18 @@ class list
class insertion_functor
{
Icont &icont_;
typedef typename Icont::iterator iiterator;
typedef typename Icont::const_iterator iconst_iterator;
const iconst_iterator pos_;
iiterator ret_;
bool first_;
public:
insertion_functor(Icont &icont, typename Icont::const_iterator pos)
: icont_(icont), pos_(pos), ret_(pos.unconst()), first_(true)
: icont_(icont), pos_(pos)
{}
void operator()(Node &n)
{
if(first_){
ret_ = this->icont_.insert(pos_, n);
first_ = false;
}
else{
this->icont_.insert(pos_, n);
}
this->icont_.insert(pos_, n);
}
iiterator inserted_first() const
{ return ret_; }
};
//Functors for member algorithm defaults
@@ -1483,15 +1457,14 @@ inline void swap(list<T, Allocator>& x, list<T, Allocator>& y)
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value;
};
*/
: public ::boost::has_trivial_destructor_after_move<Allocator>
{};
namespace container {
/// @endcond

View File

@@ -30,8 +30,8 @@
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/value_init.hpp>
@@ -229,7 +229,7 @@ class map
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.get_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -239,7 +239,7 @@ class map
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.get_stored_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -249,7 +249,7 @@ class map
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.get_stored_allocator(); }
//////////////////////////////////////////////
@@ -263,7 +263,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.begin(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -271,7 +271,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -279,7 +279,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.end(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -287,7 +287,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -296,7 +296,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -305,7 +305,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -314,7 +314,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -323,7 +323,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -331,7 +331,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.begin(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -339,7 +339,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.end(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -348,7 +348,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -357,7 +357,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rend(); }
//////////////////////////////////////////////
@@ -371,7 +371,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -379,7 +379,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -387,7 +387,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.max_size(); }
//////////////////////////////////////////////
@@ -621,7 +621,7 @@ class map
//! returns end().
//!
//! <b>Complexity</b>: Amortized constant time
iterator erase(const_iterator position)
iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
{ return m_tree.erase(position); }
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
@@ -629,7 +629,7 @@ class map
//! <b>Returns</b>: Returns the number of erased elements.
//!
//! <b>Complexity</b>: log(size()) + count(k)
size_type erase(const key_type& x)
size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT
{ return m_tree.erase(x); }
//! <b>Effects</b>: Erases all the elements in the range [first, last).
@@ -637,7 +637,7 @@ class map
//! <b>Returns</b>: Returns last.
//!
//! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ return m_tree.erase(first, last); }
//! <b>Effects</b>: Swaps the contents of *this and x.
@@ -653,7 +653,7 @@ class map
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ m_tree.clear(); }
//////////////////////////////////////////////
@@ -827,15 +827,15 @@ inline bool operator<(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y);
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class T, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::map<K, T, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
/// @endcond
@@ -951,9 +951,9 @@ class multimap
//!
//! <b>Complexity</b>: Linear in N.
template <class InputIterator>
multimap(ordered_range_t ordered_range_, InputIterator first, InputIterator last, const Compare& comp = Compare(),
multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: m_tree(ordered_range_, first, last, comp, a)
: m_tree(ordered_range, first, last, comp, a)
{}
//! <b>Effects</b>: Copy constructs a multimap.
@@ -1016,7 +1016,7 @@ class multimap
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.get_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -1026,7 +1026,7 @@ class multimap
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.get_stored_allocator(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -1036,7 +1036,7 @@ class multimap
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.get_stored_allocator(); }
//////////////////////////////////////////////
@@ -1050,7 +1050,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.begin(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -1058,7 +1058,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -1066,7 +1066,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.end(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -1074,7 +1074,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -1083,7 +1083,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1092,7 +1092,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -1101,7 +1101,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1110,7 +1110,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -1118,7 +1118,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.begin(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -1126,7 +1126,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.end(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1135,7 +1135,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1144,7 +1144,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.rend(); }
//////////////////////////////////////////////
@@ -1158,7 +1158,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -1166,7 +1166,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -1174,7 +1174,7 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_tree.max_size(); }
//////////////////////////////////////////////
@@ -1317,7 +1317,7 @@ class multimap
//! returns end().
//!
//! <b>Complexity</b>: Amortized constant time
iterator erase(const_iterator position)
iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
{ return m_tree.erase(position); }
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
@@ -1325,7 +1325,7 @@ class multimap
//! <b>Returns</b>: Returns the number of erased elements.
//!
//! <b>Complexity</b>: log(size()) + count(k)
size_type erase(const key_type& x)
size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT
{ return m_tree.erase(x); }
//! <b>Effects</b>: Erases all the elements in the range [first, last).
@@ -1333,7 +1333,7 @@ class multimap
//! <b>Returns</b>: Returns last.
//!
//! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ return m_tree.erase(first, last); }
//! <b>Effects</b>: Swaps the contents of *this and x.
@@ -1349,7 +1349,7 @@ class multimap
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ m_tree.clear(); }
//////////////////////////////////////////////
@@ -1486,15 +1486,15 @@ inline void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Al
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class T, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::multimap<K, T, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
/// @endcond

View File

@@ -30,8 +30,8 @@
#include <boost/container/detail/utilities.hpp>
#include <utility>
#include <boost/container/detail/pair.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost { namespace container {
@@ -1338,52 +1338,56 @@ class scoped_allocator_adaptor
void construct_pair(Pair* p)
{
this->construct(container_detail::addressof(p->first));
try {
BOOST_TRY{
this->construct(container_detail::addressof(p->second));
}
catch (...) {
BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class Pair, class U, class V>
void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{
this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
try {
BOOST_TRY{
this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
}
catch (...) {
BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class Pair, class Pair2>
void construct_pair(Pair* p, const Pair2& pr)
{
this->construct(container_detail::addressof(p->first), pr.first);
try {
BOOST_TRY{
this->construct(container_detail::addressof(p->second), pr.second);
}
catch (...) {
BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class Pair, class Pair2>
void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
{
this->construct(container_detail::addressof(p->first), ::boost::move(pr.first));
try {
BOOST_TRY{
this->construct(container_detail::addressof(p->second), ::boost::move(pr.second));
}
catch (...) {
BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
throw;
BOOST_RETHROW
}
BOOST_CATCH_END
}
//template <class T1, class T2, class... Args1, class... Args2>

View File

@@ -23,11 +23,11 @@
#include <functional>
#include <memory>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/tree.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -646,15 +646,15 @@ inline void swap(set<Key,Compare,Allocator>& x, set<Key,Compare,Allocator>& y)
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
// Forward declaration of operators < and ==, needed for friend declaration.
@@ -757,10 +757,10 @@ class multiset
//!
//! <b>Complexity</b>: Linear in N.
template <class InputIterator>
multiset( ordered_range_t ordered_range_, InputIterator first, InputIterator last
multiset( ordered_range_t, InputIterator first, InputIterator last
, const Compare& comp = Compare()
, const allocator_type& a = allocator_type())
: m_tree(ordered_range_, first, last, comp, a)
: m_tree(ordered_range, first, last, comp, a)
{}
//! <b>Effects</b>: Copy constructs a multiset.
@@ -1259,15 +1259,15 @@ inline void swap(multiset<Key,Compare,Allocator>& x, multiset<Key,Compare,Alloca
/// @cond
} //namespace container {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class C, class Allocator>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, C, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value && has_trivial_destructor<C>::value;
static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
*/
namespace container {
/// @endcond

View File

@@ -19,8 +19,8 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/mpl.hpp>
@@ -140,9 +140,6 @@ class slist_const_iterator
friend bool operator!= (const slist_const_iterator& l, const slist_const_iterator& r)
{ return l.m_it != r.m_it; }
IIterator &get()
{ return this->m_it; }
const IIterator &get() const
{ return this->m_it; }
};
@@ -181,9 +178,6 @@ class slist_iterator
slist_iterator operator++(int)
{ IIterator tmp = this->m_it; ++*this; return slist_iterator(tmp); }
IIterator &get()
{ return this->m_it; }
const IIterator &get() const
{ return this->m_it; }
};
@@ -319,10 +313,10 @@ class slist
//! <b>Effects</b>: Constructs a list taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
explicit slist(const allocator_type& a)
explicit slist(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT
: AllocHolder(a)
{}
@@ -407,7 +401,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements.
~slist()
~slist() BOOST_CONTAINER_NOEXCEPT
{} //AllocHolder clears the slist
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -511,7 +505,7 @@ class slist
//! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return allocator_type(this->node_alloc()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -521,7 +515,7 @@ class slist
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator()
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -531,7 +525,7 @@ class slist
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
//////////////////////////////////////////////
@@ -547,7 +541,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator before_begin()
iterator before_begin() BOOST_CONTAINER_NOEXCEPT
{ return iterator(end()); }
//! <b>Effects</b>: Returns a non-dereferenceable const_iterator
@@ -557,7 +551,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator before_begin() const
const_iterator before_begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbefore_begin(); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the list.
@@ -565,7 +559,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -573,7 +567,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the list.
@@ -581,7 +575,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -589,7 +583,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->cend(); }
//! <b>Effects</b>: Returns a non-dereferenceable const_iterator
@@ -599,7 +593,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbefore_begin() const
const_iterator cbefore_begin() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(end()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -607,7 +601,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -615,7 +609,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().end()); }
//! <b>Returns</b>: The iterator to the element before i in the sequence.
@@ -627,7 +621,7 @@ class slist
//! <b>Complexity</b>: Linear to the number of elements before i.
//!
//! <b>Note</b>: Non-standard extension.
iterator previous(iterator p)
iterator previous(iterator p) BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().previous(p.get())); }
//! <b>Returns</b>: The const_iterator to the element before i in the sequence.
@@ -986,9 +980,9 @@ class slist
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, slist& x)
void splice_after(const_iterator prev_pos, slist& x) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this != &x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice_after(prev_pos.get(), x.icont());
}
@@ -1006,65 +1000,63 @@ class slist
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x)
void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(prev_pos, static_cast<slist&>(x)); }
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
//! i must point to an element contained in list x.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
//! after the element pointed by prev_pos.
//! If prev_pos == prev or prev_pos == ++prev, this function is a null operation.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, slist& x, const_iterator prev)
void splice_after(const_iterator prev_pos, slist& x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice_after(prev_pos.get(), x.icont(), prev.get());
}
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
//! i must point to an element contained in list x.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
//! after the element pointed by prev_pos.
//! If prev_pos == prev or prev_pos == ++prev, this function is a null operation.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x, const_iterator prev)
void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(prev_pos, static_cast<slist&>(x), prev); }
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
//! before_first and before_last must be valid iterators of x.
//! prev_pos must not be contained in [before_first, before_last) range.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
//! from list x to this list, after the element pointed by prev_pos.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear to the number of transferred elements.
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, slist& x,
const_iterator before_first, const_iterator before_last)
const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice_after
(prev_pos.get(), x.icont(), before_first.get(), before_last.get());
@@ -1073,31 +1065,31 @@ class slist
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
//! before_first and before_last must be valid iterators of x.
//! prev_pos must not be contained in [before_first, before_last) range.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
//! from list x to this list, after the element pointed by prev_pos.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear to the number of transferred elements.
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x,
const_iterator before_first, const_iterator before_last)
const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(prev_pos, static_cast<slist&>(x), before_first, before_last); }
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
//! before_first and before_last must be valid iterators of x.
//! prev_pos must not be contained in [before_first, before_last) range.
//! n == std::distance(before_first, before_last)
//! n == std::distance(before_first, before_last).
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
//! from list x to this list, after the element pointed by prev_pos.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1105,9 +1097,8 @@ class slist
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, slist& x,
const_iterator before_first, const_iterator before_last,
size_type n)
size_type n) BOOST_CONTAINER_NOEXCEPT
{
BOOST_ASSERT(*this != x);
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice_after
(prev_pos.get(), x.icont(), before_first.get(), before_last.get(), n);
@@ -1116,13 +1107,13 @@ class slist
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
//! before_first and before_last must be valid iterators of x.
//! prev_pos must not be contained in [before_first, before_last) range.
//! n == std::distance(before_first, before_last)
//! n == std::distance(before_first, before_last).
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
//! from list x to this list, after the element pointed by prev_pos.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
//!
@@ -1130,7 +1121,7 @@ class slist
//! list. Iterators of this list and all the references are not invalidated.
void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x,
const_iterator before_first, const_iterator before_last,
size_type n)
size_type n) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(prev_pos, static_cast<slist&>(x), before_first, before_last, n); }
//! <b>Effects</b>: Removes all the elements that compare equal to value.
@@ -1163,9 +1154,9 @@ class slist
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that are equal from the list.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
//! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
//!
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
@@ -1177,7 +1168,7 @@ class slist
//!
//! <b>Throws</b>: If pred throws.
//!
//! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
//! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
//!
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
@@ -1195,7 +1186,7 @@ class slist
//! that is, if an element from *this is equivalent to one from x, then the element
//! from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1209,7 +1200,7 @@ class slist
//! that is, if an element from *this is equivalent to one from x, then the element
//! from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1224,7 +1215,7 @@ class slist
//! in order into *this. The merge is stable; that is, if an element from *this is
//! equivalent to one from x, then the element from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comp throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1233,13 +1224,9 @@ class slist
template <class StrictWeakOrdering>
void merge(slist& x, StrictWeakOrdering comp)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().merge(x.icont(),
ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
}
else{
throw std::runtime_error("list::merge called with unequal allocators");
}
BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().merge(x.icont(),
ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
}
//! <b>Requires</b>: p must be a comparison function that induces a strict weak
@@ -1250,7 +1237,7 @@ class slist
//! in order into *this. The merge is stable; that is, if an element from *this is
//! equivalent to one from x, then the element from *this will precede the one from x.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comp throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1263,7 +1250,7 @@ class slist
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comparison throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1275,7 +1262,7 @@ class slist
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
//! The sort is stable, that is, the relative order of equivalent elements is preserved.
//!
//! <b>Throws</b>: Nothing.
//! <b>Throws</b>: If comp throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1297,7 +1284,7 @@ class slist
//! <b>Complexity</b>: This function is linear time.
//!
//! <b>Note</b>: Iterators and references are not invalidated
void reverse()
void reverse() BOOST_CONTAINER_NOEXCEPT
{ this->icont().reverse(); }
//////////////////////////////////////////////
@@ -1403,7 +1390,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements before p.
iterator erase(const_iterator p)
iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->erase_after(previous(p))); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this.
@@ -1414,73 +1401,71 @@ class slist
//!
//! <b>Complexity</b>: Linear to the distance between first and last plus
//! linear to the elements before first.
iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->erase_after(previous(first), last)); }
//! <b>Requires</b>: p must point to an element contained
//! by the list. x != *this
//! by the list. x != *this. this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers all the elements of list x to this list, before the
//! the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear in distance(begin(), p), and linear in x.size().
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, slist& x)
void splice(const_iterator p, slist& x) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(this->previous(p), x); }
//! <b>Requires</b>: p must point to an element contained
//! by the list. x != *this
//! by the list. x != *this. this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers all the elements of list x to this list, before the
//! the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear in distance(begin(), p), and linear in x.size().
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, BOOST_RV_REF(slist) x)
void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT
{ this->splice(p, static_cast<slist&>(x)); }
//! <b>Requires</b>: p must point to an element contained
//! by this list. i must point to an element contained in list x.
//! this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//! If p == i or p == ++i, this function is a null operation.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear in distance(begin(), p), and in distance(x.begin(), i).
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, slist& x, const_iterator i)
void splice(const_iterator p, slist& x, const_iterator i) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(this->previous(p), x, this->previous(i)); }
//! <b>Requires</b>: p must point to an element contained
//! by this list. i must point to an element contained in list x.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//! If p == i or p == ++i, this function is a null operation.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear in distance(begin(), p), and in distance(x.begin(), i).
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i)
void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_CONTAINER_NOEXCEPT
{ this->splice(p, static_cast<slist&>(x), i); }
//! <b>Requires</b>: p must point to an element contained
@@ -1488,33 +1473,33 @@ class slist
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//! this' allocator and x's allocator shall compare equal.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear in distance(begin(), p), in distance(x.begin(), first),
//! and in distance(first, last).
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, slist& x, const_iterator first, const_iterator last)
void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ this->splice_after(this->previous(p), x, this->previous(first), this->previous(last)); }
//! <b>Requires</b>: p must point to an element contained
//! by this list. first and last must point to elements contained in list x.
//! this' allocator and x's allocator shall compare equal
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//!
//! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
//! are not equal.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Linear in distance(begin(), p), in distance(x.begin(), first),
//! and in distance(first, last).
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last)
void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ this->splice(p, static_cast<slist&>(x), first, last); }
/// @cond
@@ -1658,15 +1643,14 @@ inline void swap(slist<T,Allocator>& x, slist<T,Allocator>& y)
/// @cond
namespace boost {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::slist<T, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value;
};
*/
: public ::boost::has_trivial_destructor_after_move<Allocator>
{};
namespace container {
/// @endcond

View File

@@ -1,4 +1,4 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
@@ -29,15 +29,16 @@
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/assert.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/allocator_version_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <algorithm> //max
#include <stdexcept>
#include <memory>
@@ -303,7 +304,7 @@ struct index_traits
static const size_type ExtraPointers = 3;
//Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers:
// back() is this->index.back() - ExtraPointers;
// end node index is *(this->index.end() -3)
// end node index is *(this->index.end() - 3)
// Node cache first is *(this->index.end() - 2);
// Node cache last is this->index.back();
@@ -366,89 +367,6 @@ struct index_traits
#endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
};
template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
struct allocator_version_wrapper
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, Version> alloc_version;
typedef typename Allocator::multiallocation_chain multiallocation_chain;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
static pointer allocate_one(Allocator &a)
{ return a.allocate_one(); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate_one(p); }
static multiallocation_chain allocate_individual(Allocator &a, size_type n)
{ return a.allocate_individual(n); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{ a.deallocate_individual(::boost::move(holder)); }
};
template<class Allocator>
struct allocator_version_wrapper<Allocator, 1>
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, 1> alloc_version;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
typedef typename boost::intrusive::pointer_traits<pointer>::
template rebind_pointer<void>::type void_ptr;
typedef container_detail::basic_multiallocation_chain
<void_ptr> multialloc_cached_counted;
typedef boost::container::container_detail::
transform_multiallocation_chain
< multialloc_cached_counted, value_type> multiallocation_chain;
static pointer allocate_one(Allocator &a)
{ return a.allocate(1); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate(p, 1); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{
while(!holder.empty()){
a.deallocate(holder.pop_front(), 1);
}
}
struct allocate_individual_rollback
{
allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
: mr_a(a), mr_chain(chain)
{}
~allocate_individual_rollback()
{
allocator_version_wrapper::deallocate_individual(mr_a, mr_chain);
}
Allocator &mr_a;
multiallocation_chain &mr_chain;
};
static multiallocation_chain allocate_individual(Allocator &a, size_type n)
{
multiallocation_chain m;
multiallocation_chain m_ret;
allocate_individual_rollback rollback(a, m);
while(n--){
m.push_front(a.allocate(1));
}
m.swap(m_ret);
return ::boost::move(m_ret);
}
};
} //namespace stable_vector_detail
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -555,20 +473,21 @@ class stable_vector
template portable_rebind_alloc
<node_type>::type node_allocator_type;
typedef stable_vector_detail::allocator_version_wrapper<node_allocator_type> allocator_version_wrapper_t;
typedef typename allocator_version_wrapper_t::multiallocation_chain multiallocation_chain;
typedef ::boost::container::container_detail::
allocator_version_traits<node_allocator_type> allocator_version_traits_t;
typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain;
node_ptr allocate_one()
{ return allocator_version_wrapper_t::allocate_one(this->priv_node_alloc()); }
{ return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
void deallocate_one(const node_ptr &p)
{ allocator_version_wrapper_t::deallocate_one(this->priv_node_alloc(), p); }
{ allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
multiallocation_chain allocate_individual(typename allocator_traits_type::size_type n)
{ return allocator_version_wrapper_t::allocate_individual(this->priv_node_alloc(), n); }
void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m)
{ allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); }
void deallocate_individual(multiallocation_chain &holder)
{ allocator_version_wrapper_t::deallocate_individual(this->priv_node_alloc(), holder); }
{ allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); }
friend class stable_vector_detail::clear_on_destroy<stable_vector>;
typedef stable_vector_detail::iterator
@@ -633,10 +552,10 @@ class stable_vector
//! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
explicit stable_vector(const allocator_type& al)
explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT
: internal_data(al), index(al)
{
STABLE_VECTOR_CHECK_INVARIANT;
@@ -904,7 +823,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
@@ -912,7 +831,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin()const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
//! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
@@ -920,7 +839,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
@@ -928,7 +847,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -937,7 +856,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -946,7 +865,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -955,7 +874,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -964,7 +883,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend()const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
@@ -972,7 +891,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->begin(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
@@ -980,7 +899,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend()const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return this->end(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -989,7 +908,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -998,7 +917,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend()const
const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT
{ return this->rend(); }
//////////////////////////////////////////////
@@ -1012,7 +931,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return this->index.size() <= ExtraPointers; }
//! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
@@ -1020,7 +939,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{
const size_type index_size = this->index.size();
return index_size ? (index_size - ExtraPointers) : 0;
@@ -1031,7 +950,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return this->index.max_size() - ExtraPointers; }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -1071,7 +990,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{
const size_type index_size = this->index.size();
BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
@@ -1094,7 +1013,7 @@ class stable_vector
if(n > this->max_size())
throw std::bad_alloc();
size_type size_ = this->size();
size_type sz = this->size();
size_type old_capacity = this->capacity();
if(n > old_capacity){
index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
@@ -1106,8 +1025,8 @@ class stable_vector
index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
}
//Now fill pool if data is not enough
if((n - size_) > this->internal_data.pool_size){
this->priv_increase_pool((n - size_) - this->internal_data.pool_size);
if((n - sz) > this->internal_data.pool_size){
this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
}
}
}
@@ -1156,7 +1075,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference front()
reference front() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
@@ -1167,7 +1086,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference front() const
const_reference front() const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const_node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
@@ -1178,7 +1097,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference back()
reference back() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<node_reference>(*this->index[this->size() - ExtraPointers]).value; }
//! <b>Requires</b>: !empty()
@@ -1189,7 +1108,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference back()const
const_reference back() const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const_node_reference>(*this->index[this->size() - ExtraPointers]).value; }
//! <b>Requires</b>: size() > n.
@@ -1200,7 +1119,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n)
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
{ return static_cast<node_reference>(*this->index[n]).value; }
//! <b>Requires</b>: size() > n.
@@ -1211,7 +1130,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n)const
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const_node_reference>(*this->index[n]).value; }
//! <b>Requires</b>: size() > n.
@@ -1400,7 +1319,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InputIterator>
iterator insert(const_iterator position,InputIterator first, InputIterator last
iterator insert(const_iterator position, InputIterator first, InputIterator last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIterator, size_type>::value
@@ -1426,8 +1345,8 @@ class stable_vector
>::type * = 0
)
{
const size_type num_new = (size_type)std::distance(first,last);
const size_type pos = static_cast<size_type>(position - this->cbegin());
const size_type num_new = static_cast<size_type>(std::distance(first, last));
const size_type pos = static_cast<size_type>(position - this->cbegin());
if(num_new){
//Fills the node pool and inserts num_new null pointers in pos.
//If a new buffer was needed fixes up pointers up to pos so
@@ -1463,7 +1382,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant time.
void pop_back()
void pop_back() BOOST_CONTAINER_NOEXCEPT
{ this->erase(--this->cend()); }
//! <b>Effects</b>: Erases the element at position pos.
@@ -1472,15 +1391,15 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to the elements between pos and the
//! last element. Constant if pos is the last element.
iterator erase(const_iterator position)
iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d = position - this->cbegin();
index_iterator it = this->index.begin() + d;
const size_type d = position - this->cbegin();
index_iterator it = this->index.begin() + d;
this->priv_delete_node(position.node_pointer());
it = this->index.erase(it);
index_traits_type::fix_up_pointers_from(this->index, it);
return this->begin()+d;
return iterator(node_ptr_traits::static_cast_from(*it));
}
//! <b>Effects</b>: Erases the elements pointed by [first, last).
@@ -1489,19 +1408,30 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to the distance between first and last
//! plus linear to the elements between pos and the last element.
iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
if(d1 != d2){
index_iterator it1(this->index.begin() + d1), it2(it1 + (d2 - d1));
for(index_iterator it = it1; it != it2; ++it){
this->priv_delete_node(node_ptr_traits::static_cast_from(*it));
const const_iterator cbeg(this->cbegin());
const size_type d1 = static_cast<size_type>(first - cbeg),
d2 = static_cast<size_type>(last - cbeg);
size_type d_dif = d2 - d1;
if(d_dif){
multiallocation_chain holder;
const index_iterator it1(this->index.begin() + d1);
const index_iterator it2(it1 + d_dif);
index_iterator it(it1);
while(d_dif--){
node_base_ptr &nb = *it;
++it;
node_type &n = *node_ptr_traits::static_cast_from(nb);
this->priv_destroy_node(n);
holder.push_back(node_ptr_traits::pointer_to(n));
}
this->priv_put_in_pool(holder);
const index_iterator e = this->index.erase(it1, it2);
index_traits_type::fix_up_pointers_from(this->index, e);
}
return iterator(this->begin() + d1);
return iterator(last.node_pointer());
}
//! <b>Effects</b>: Swaps the contents of *this and x.
@@ -1524,7 +1454,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ this->erase(this->cbegin(),this->cend()); }
/// @cond
@@ -1666,7 +1596,8 @@ class stable_vector
, node_ptr_traits::static_cast_from(pool_first_ref)
, node_ptr_traits::static_cast_from(pool_last_ref)
, internal_data.pool_size);
multiallocation_chain m (this->allocate_individual(n));
multiallocation_chain m;
this->allocate_individual(n, m);
holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
this->internal_data.pool_size += n;
std::pair<node_ptr, node_ptr> data(holder.extract_data());
@@ -1690,11 +1621,25 @@ class stable_vector
pool_last_ref = ret.second;
}
void priv_put_in_pool(multiallocation_chain &ch)
{
node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
node_base_ptr &pool_last_ref = this->index.back();
ch.incorporate_after( ch.before_begin()
, node_ptr_traits::static_cast_from(pool_first_ref)
, node_ptr_traits::static_cast_from(pool_last_ref)
, internal_data.pool_size);
this->internal_data.pool_size = ch.size();
const std::pair<node_ptr, node_ptr> ret(ch.extract_data());
pool_first_ref = ret.first;
pool_last_ref = ret.second;
}
node_ptr priv_get_from_pool()
{
//Precondition: index is not empty
BOOST_ASSERT(!this->index.empty());
node_base_ptr &pool_first_ref = *(this->index.end() - 2);
node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
node_base_ptr &pool_last_ref = this->index.back();
multiallocation_chain holder;
holder.incorporate_after( holder.before_begin()
@@ -1707,9 +1652,9 @@ class stable_vector
pool_first_ref = pool_last_ref = node_ptr();
}
else{
std::pair<node_ptr, node_ptr> data(holder.extract_data());
const std::pair<node_ptr, node_ptr> data(holder.extract_data());
pool_first_ref = data.first;
pool_last_ref = data.second;
pool_last_ref = data.second;
}
return ret;
}
@@ -1720,11 +1665,16 @@ class stable_vector
(static_cast<node_type&>(const_cast<node_base_type&>(this->internal_data.end_node)));
}
void priv_delete_node(const node_ptr &n)
void priv_destroy_node(const node_type &n)
{
allocator_traits<node_allocator_type>::
destroy(this->priv_node_alloc(), container_detail::addressof(n->value));
static_cast<node_base_type*>(container_detail::to_raw_pointer(n))->~node_base_type();
destroy(this->priv_node_alloc(), container_detail::addressof(n.value));
static_cast<const node_base_type*>(&n)->~node_base_type();
}
void priv_delete_node(const node_ptr &n)
{
this->priv_destroy_node(*n);
this->priv_put_in_pool(n);
}
@@ -1776,7 +1726,7 @@ class stable_vector
}
size_type n = this->capacity() - this->size();
node_base_ptr &pool_first_ref = *(index_ref.end() - 2);
node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
node_base_ptr &pool_last_ref = index_ref.back();
multiallocation_chain holder;
holder.incorporate_after( holder.before_begin()
@@ -1886,6 +1836,17 @@ void swap(stable_vector<T,Allocator>& x,stable_vector<T,Allocator>& y)
/// @endcond
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
: public has_trivial_destructor_after_move<Allocator>::value
{};
*/
}}
#include <boost/container/detail/config_end.hpp>

View File

@@ -44,11 +44,13 @@
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/allocation_type.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/move/move.hpp>
#include <boost/move/utility.hpp>
#include <boost/static_assert.hpp>
#include <boost/functional/hash.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <functional>
#include <string>
@@ -81,8 +83,8 @@ namespace container_detail {
// an exception-safe version of basic_string. The constructor allocates,
// but does not initialize, a block of memory. The destructor
// deallocates, but does not destroy elements within, a block of
// memory. The destructor assumes that the memory either is the internal buffer,
// or else points to a block of memory that was allocated using _String_base's
// memory. The destructor assumes that the memory either is the internal buffer,
// or else points to a block of memory that was allocated using string_base's
// allocator and whose size is this->m_storage.
template <class Allocator>
class basic_string_base
@@ -92,7 +94,6 @@ class basic_string_base
typedef allocator_traits<Allocator> allocator_traits_type;
public:
typedef Allocator allocator_type;
//! The stored allocator type
typedef allocator_type stored_allocator_type;
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::value_type value_type;
@@ -284,36 +285,8 @@ class basic_string_base
reuse = pointer();
command &= ~(expand_fwd | expand_bwd);
}
return this->allocation_command
(command, limit_size, preferred_size, received_size, reuse, alloc_version());
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size,
const pointer &reuse,
allocator_v1)
{
(void)limit_size;
(void)reuse;
if(!(command & allocate_new))
return std::pair<pointer, bool>(pointer(), false);
received_size = preferred_size;
return std::make_pair(this->alloc().allocate(received_size), false);
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size,
pointer reuse,
allocator_v2)
{
return this->alloc().allocation_command(command, limit_size, preferred_size,
received_size, reuse);
return container_detail::allocator_version_traits<Allocator>::allocation_command
(this->alloc(), command, limit_size, preferred_size, received_size, reuse);
}
size_type next_capacity(size_type additional_objects) const
@@ -336,11 +309,9 @@ class basic_string_base
void destroy(pointer p, size_type n)
{
for(; n--; ++p){
allocator_traits_type::destroy
( this->alloc()
, container_detail::to_raw_pointer(p)
);
value_type *raw_p = container_detail::to_raw_pointer(p);
for(; n--; ++raw_p){
allocator_traits_type::destroy( this->alloc(), raw_p);
}
}
@@ -569,37 +540,26 @@ class basic_string
/// @endcond
public:
//! The allocator type
typedef Allocator allocator_type;
//! The stored allocator type
typedef allocator_type stored_allocator_type;
//! The type of object, CharT, stored in the string
typedef CharT value_type;
//! The second template parameter Traits
typedef Traits traits_type;
//! Pointer to CharT
typedef typename allocator_traits_type::pointer pointer;
//! Const pointer to CharT
typedef typename allocator_traits_type::const_pointer const_pointer;
//! Reference to CharT
typedef typename allocator_traits_type::reference reference;
//! Const reference to CharT
typedef typename allocator_traits_type::const_reference const_reference;
//! An unsigned integral type
typedef typename allocator_traits_type::size_type size_type;
//! A signed integral type
typedef typename allocator_traits_type::difference_type difference_type;
//! Iterator used to iterate through a string. It's a Random Access Iterator
typedef pointer iterator;
//! Const iterator used to iterate through a string. It's a Random Access Iterator
typedef const_pointer const_iterator;
//! Iterator used to iterate backwards through a string
typedef std::reverse_iterator<iterator> reverse_iterator;
//! Const iterator used to iterate backwards through a string
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
//! The largest possible value of type size_type. That is, size_type(-1).
static const size_type npos;
//////////////////////////////////////////////
//
// types
//
//////////////////////////////////////////////
typedef Traits traits_type;
typedef CharT value_type;
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
typedef Allocator allocator_type;
typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type;
typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<iterator>) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
static const size_type npos = size_type(-1);
/// @cond
private:
@@ -611,6 +571,11 @@ class basic_string
/// @endcond
public: // Constructor, destructor, assignment.
//////////////////////////////////////////////
//
// construct/copy/destroy
//
//////////////////////////////////////////////
/// @cond
struct reserve_t {};
@@ -634,8 +599,8 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
explicit basic_string(const allocator_type& a)
//! <b>Throws</b>: Nothing
explicit basic_string(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT
: base_t(a)
{ this->priv_terminate_string(); }
@@ -653,10 +618,10 @@ class basic_string
//! <b>Effects</b>: Move constructor. Moves s's resources to *this.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
basic_string(BOOST_RV_REF(basic_string) s)
basic_string(BOOST_RV_REF(basic_string) s) BOOST_CONTAINER_NOEXCEPT
: base_t(boost::move((base_t&)s))
{}
@@ -693,7 +658,7 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by a specific number of characters of the s string.
basic_string(const basic_string& s, size_type pos, size_type n = npos,
const allocator_type& a = allocator_type())
const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_terminate_string();
@@ -706,8 +671,7 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by a specific number of characters of the s c-string.
basic_string(const CharT* s, size_type n,
const allocator_type& a = allocator_type())
basic_string(const CharT* s, size_type n, const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_terminate_string();
@@ -716,8 +680,7 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by the null-terminated s c-string.
basic_string(const CharT* s,
const allocator_type& a = allocator_type())
basic_string(const CharT* s, const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_terminate_string();
@@ -726,8 +689,7 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by n copies of c.
basic_string(size_type n, CharT c,
const allocator_type& a = allocator_type())
basic_string(size_type n, CharT c, const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_terminate_string();
@@ -737,8 +699,7 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and a range of iterators.
template <class InputIterator>
basic_string(InputIterator f, InputIterator l,
const allocator_type& a = allocator_type())
basic_string(InputIterator f, InputIterator l, const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_terminate_string();
@@ -750,7 +711,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
~basic_string()
~basic_string() BOOST_CONTAINER_NOEXCEPT
{}
//! <b>Effects</b>: Copy constructs a string.
@@ -784,7 +745,7 @@ class basic_string
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
basic_string& operator=(BOOST_RV_REF(basic_string) x)
basic_string& operator=(BOOST_RV_REF(basic_string) x) BOOST_CONTAINER_NOEXCEPT
{
if (&x != this){
allocator_type &this_alloc = this->alloc();
@@ -815,114 +776,12 @@ class basic_string
basic_string& operator=(CharT c)
{ return this->assign(static_cast<size_type>(1), c); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
{ return this->priv_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
{ return this->priv_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
{ return this->priv_addr(); }
//! <b>Effects</b>: Returns an iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
{ return this->priv_end_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
{ return this->priv_end_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
{ return this->priv_end_addr(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
{ return reverse_iterator(this->priv_end_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
{ return const_reverse_iterator(this->priv_end_addr()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
{ return reverse_iterator(this->priv_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
{ return const_reverse_iterator(this->priv_addr()); }
//! <b>Effects</b>: Returns a copy of the internal allocator.
//!
//! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return this->alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -945,12 +804,134 @@ class basic_string
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return this->alloc(); }
//////////////////////////////////////////////
//
// iterators
//
//////////////////////////////////////////////
//! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return this->priv_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_addr(); }
//! <b>Effects</b>: Returns an iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return this->priv_end_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_end_addr(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->priv_end_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->priv_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_addr(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_end_addr(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->priv_end_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->priv_addr()); }
//////////////////////////////////////////////
//
// capacity
//
//////////////////////////////////////////////
//! <b>Effects</b>: Returns true if the vector contains no elements.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return !this->priv_size(); }
//! <b>Effects</b>: Returns the number of the elements contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_size(); }
//! <b>Effects</b>: Returns the number of the elements contained in the vector.
@@ -958,7 +939,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type length() const
size_type length() const BOOST_CONTAINER_NOEXCEPT
{ return this->size(); }
//! <b>Effects</b>: Returns the largest possible size of the vector.
@@ -966,7 +947,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return base_t::max_size(); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -990,7 +971,16 @@ class basic_string
//!
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type n)
{ resize(n, CharT(0)); }
{ resize(n, CharT()); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
//! effect. Otherwise, it is a request for allocation of additional memory.
@@ -1023,28 +1013,6 @@ class basic_string
}
}
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
{ return this->priv_capacity(); }
//! <b>Effects</b>: Erases all the elements of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the vector.
void clear()
{
if (!this->empty()) {
Traits::assign(*this->priv_addr(), CharT(0));
this->priv_size(0);
}
}
//! <b>Effects</b>: Tries to deallocate the excess of memory created
//! with previous allocations. The size of the string is unchanged
//!
@@ -1076,13 +1044,11 @@ class basic_string
}
}
//! <b>Effects</b>: Returns true if the vector contains no elements.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
{ return !this->priv_size(); }
//////////////////////////////////////////////
//
// element access
//
//////////////////////////////////////////////
//! <b>Requires</b>: size() > n.
//!
@@ -1092,7 +1058,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n)
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
{ return *(this->priv_addr() + n); }
//! <b>Requires</b>: size() > n.
@@ -1103,7 +1069,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n) const
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return *(this->priv_addr() + n); }
//! <b>Requires</b>: size() > n.
@@ -1135,6 +1101,12 @@ class basic_string
return *(this->priv_addr() + n);
}
//////////////////////////////////////////////
//
// modifiers
//
//////////////////////////////////////////////
//! <b>Effects</b>: Calls append(str.data, str.size()).
//!
//! <b>Returns</b>: *this
@@ -1240,7 +1212,7 @@ class basic_string
//! <b>Throws</b>: Nothing
//!
//! <b>Returns</b>: *this
basic_string& assign(BOOST_RV_REF(basic_string) ms)
basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_CONTAINER_NOEXCEPT
{ return this->swap_data(ms), *this; }
//! <b>Requires</b>: pos <= str.size()
@@ -1322,10 +1294,10 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& insert(size_type pos, const basic_string& s)
{
const size_type size_ = this->size();
if (pos > size_)
const size_type sz = this->size();
if (pos > sz)
this->throw_out_of_range();
if (size_ > this->max_size() - s.size())
if (sz > this->max_size() - s.size())
this->throw_length_error();
this->insert(this->priv_addr() + pos, s.begin(), s.end());
return *this;
@@ -1341,12 +1313,12 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n)
{
const size_type size_ = this->size();
const size_type sz = this->size();
const size_type str_size = s.size();
if (pos1 > size_ || pos2 > str_size)
if (pos1 > sz || pos2 > str_size)
this->throw_out_of_range();
size_type len = container_detail::min_value(n, str_size - pos2);
if (size_ > this->max_size() - len)
if (sz > this->max_size() - len)
this->throw_length_error();
const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2;
const CharT *end_ptr = beg_ptr + len;
@@ -1591,7 +1563,7 @@ class basic_string
//!
//! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
//! erased. If no such element exists, end() is returned.
iterator erase(const_iterator p)
iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
{
// The move includes the terminating null.
CharT * const ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p));
@@ -1611,7 +1583,7 @@ class basic_string
//!
//! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
//! the other elements being erased. If no such element exists, end() is returned.
iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{
CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first));
if (first != last) { // The move includes the terminating null.
@@ -1631,13 +1603,26 @@ class basic_string
//! <b>Throws</b>: Nothing
//!
//! <b>Effects</b>: Equivalent to erase(size() - 1, 1).
void pop_back()
void pop_back() BOOST_CONTAINER_NOEXCEPT
{
const size_type old_size = this->priv_size();
Traits::assign(this->priv_addr()[old_size-1], CharT(0));
this->priv_size(old_size-1);;
}
//! <b>Effects</b>: Erases all the elements of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the vector.
void clear() BOOST_CONTAINER_NOEXCEPT
{
if (!this->empty()) {
Traits::assign(*this->priv_addr(), CharT(0));
this->priv_size(0);
}
}
//! <b>Requires</b>: pos1 <= size().
//!
//! <b>Effects</b>: Calls replace(pos1, n1, str.data(), str.size()).
@@ -1890,12 +1875,18 @@ class basic_string
container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
}
//////////////////////////////////////////////
//
// data access
//
//////////////////////////////////////////////
//! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
//!
//! <b>Returns</b>: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()].
//!
//! <b>Complexity</b>: constant time.
const CharT* c_str() const
const CharT* c_str() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::to_raw_pointer(this->priv_addr()); }
//! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
@@ -1903,9 +1894,15 @@ class basic_string
//! <b>Returns</b>: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()].
//!
//! <b>Complexity</b>: constant time.
const CharT* data() const
const CharT* data() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::to_raw_pointer(this->priv_addr()); }
//////////////////////////////////////////////
//
// string operations
//
//////////////////////////////////////////////
//! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
//! of the following conditions obtain: 19 pos <= xpos and xpos + str.size() <= size();
//! 2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
@@ -1949,12 +1946,12 @@ class basic_string
//! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(1,c), pos).
size_type find(CharT c, size_type pos = 0) const
{
const size_type size_ = this->size();
if (pos >= size_)
const size_type sz = this->size();
if (pos >= sz)
return npos;
else {
const pointer addr = this->priv_addr();
pointer finish = addr + size_;
const pointer addr = this->priv_addr();
pointer finish = addr + sz;
const const_iterator result =
std::find_if(addr + pos, finish,
std::bind2nd(Eq_traits<Traits>(), c));
@@ -2039,12 +2036,12 @@ class basic_string
//! <b>Returns</b>: find_first_of(basic_string(s, n), pos).
size_type find_first_of(const CharT* s, size_type pos, size_type n) const
{
const size_type size_ = this->size();
if (pos >= size_)
const size_type sz = this->size();
if (pos >= sz)
return npos;
else {
const pointer addr = this->priv_addr();
pointer finish = addr + size_;
const pointer addr = this->priv_addr();
pointer finish = addr + sz;
const_iterator result = std::find_first_of
(addr + pos, finish, s, s + n, Eq_traits<Traits>());
return result != finish ? result - this->begin() : npos;
@@ -2282,8 +2279,8 @@ class basic_string
//! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
//!
//! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
int compare(size_type pos1, size_type n1,
const basic_string& str, size_type pos2, size_type n2) const {
int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const
{
if (pos1 > this->size() || pos2 > str.size())
this->throw_out_of_range();
const pointer addr = this->priv_addr();
@@ -2309,8 +2306,7 @@ class basic_string
//! <b>Throws</b>: out_of_range if pos1 > size()
//!
//! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
int compare(size_type pos1, size_type n1,
const CharT* s, size_type n2) const
int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
{
if (pos1 > this->size())
this->throw_out_of_range();
@@ -2352,7 +2348,7 @@ class basic_string
const size_type long_size = this->priv_long_size();
const size_type long_storage = this->priv_long_storage();
//We can make this nothrow as chars are always NoThrowCopyables
try{
BOOST_TRY{
const std::pair<pointer, bool> ret = this->allocation_command
(allocate_new, long_size+1, long_size+1, real_cap, long_addr);
//Copy and update
@@ -2364,9 +2360,10 @@ class basic_string
//And release old buffer
this->alloc().deallocate(long_addr, long_storage);
}
catch(...){
BOOST_CATCH(...){
return;
}
BOOST_CATCH_END
}
template<class AllocVersion>
@@ -2481,15 +2478,6 @@ typedef basic_string
,std::allocator<wchar_t> >
wstring;
/// @cond
template <class CharT, class Traits, class Allocator>
const typename basic_string<CharT,Traits,Allocator>::size_type
basic_string<CharT,Traits,Allocator>::npos
= (typename basic_string<CharT,Traits,Allocator>::size_type) -1;
/// @endcond
// ------------------------------------------------------------
// Non-member functions.
@@ -2857,15 +2845,14 @@ inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator>
/// @cond
namespace boost {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class C, class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value;
};
*/
: public ::boost::has_trivial_destructor_after_move<Allocator>
{};
}
/// @endcond

View File

@@ -32,6 +32,7 @@
#include <boost/type_traits/has_nothrow_copy.hpp>
#include <boost/type_traits/has_nothrow_assign.hpp>
#include <boost/type_traits/has_nothrow_constructor.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/allocation_type.hpp>
#include <boost/container/detail/utilities.hpp>
@@ -39,9 +40,10 @@
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/move/move.hpp>
#include <boost/move/move_helpers.hpp>
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -213,8 +215,7 @@ struct vector_value_traits
typedef T value_type;
typedef Allocator allocator_type;
static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
static const bool trivial_dctr_after_move = trivial_dctr;
//::boost::has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
//static const bool trivial_copy = has_trivial_copy<value_type>::value;
//static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
//static const bool trivial_assign = has_trivial_assign<value_type>::value;
@@ -286,42 +287,17 @@ struct vector_alloc_holder
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0)
{
return allocation_command(command, limit_size, preferred_size,
received_size, reuse, alloc_version());
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size,
const pointer &reuse,
allocator_v1)
{
(void)limit_size;
(void)reuse;
if(!(command & allocate_new))
return std::pair<pointer, bool>(pointer(0), false);
received_size = preferred_size;
return std::make_pair(this->alloc().allocate(received_size), false);
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size,
const pointer &reuse,
allocator_v2)
{
return this->alloc().allocation_command
(command, limit_size, preferred_size, received_size, reuse);
return allocator_version_traits<Allocator>::allocation_command
(this->alloc(), command, limit_size, preferred_size, received_size, reuse);
}
size_type next_capacity(size_type additional_objects) const
{
std::size_t num_objects = this->members_.m_size + additional_objects;
std::size_t next_cap = this->members_.m_capacity + this->members_.m_capacity/2;
return num_objects > next_cap ? num_objects : next_cap;/*
return get_next_capacity( allocator_traits_type::max_size(this->alloc())
, this->members_.m_capacity, additional_objects);
, this->members_.m_capacity, additional_objects);*/
}
struct members_holder
@@ -435,7 +411,6 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
/// @cond
private:
BOOST_COPYABLE_AND_MOVABLE(vector)
typedef container_detail::advanced_insert_aux_int<T*> advanced_insert_aux_int_t;
typedef container_detail::vector_value_traits<value_type, Allocator> value_traits;
typedef typename base_t::allocator_v1 allocator_v1;
@@ -443,8 +418,6 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
typedef typename base_t::alloc_version alloc_version;
typedef constant_iterator<T, difference_type> cvalue_iterator;
typedef repeat_iterator<T, difference_type> repeat_it;
typedef boost::move_iterator<repeat_it> repeat_move_it;
/// @endcond
public:
@@ -857,7 +830,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
else{
const size_type n = new_size - this->size();
this->reserve(new_size);
container_detail::default_construct_aux_proxy<Allocator, T*> proxy(this->alloc(), n);
container_detail::insert_default_constructed_n_proxy<Allocator, T*> proxy(this->alloc());
this->priv_forward_range_insert(this->cend().get_ptr(), n, proxy);
}
}
@@ -920,11 +893,10 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//If there is no forward expansion, move objects
else{
//We will reuse insert code, so create a dummy input iterator
T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start));
container_detail::advanced_insert_aux_proxy<Allocator, boost::move_iterator<T*>, T*>
proxy(this->alloc(), ::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
proxy(this->alloc(), ::boost::make_move_iterator((T *)0));
//Backwards (and possibly forward) expansion
if(ret.second){
if(alloc_version::value > 1 && ret.second){
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_bwd;
#endif
@@ -1018,7 +990,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n)
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
{ return this->members_.m_start[n]; }
//! <b>Requires</b>: size() > n.
@@ -1102,9 +1074,9 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
++this->members_.m_size;
}
else{
typedef container_detail::advanced_insert_aux_emplace<Allocator, T*, Args...> type;
type &&proxy = type(this->alloc(), ::boost::forward<Args>(args)...);
this->priv_forward_range_insert(back_pos, 1, proxy);
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
this->priv_forward_range_insert
(back_pos, 1, type(this->alloc(), ::boost::forward<Args>(args)...));
}
}
@@ -1122,11 +1094,9 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
iterator emplace(const_iterator position, Args && ...args)
{
//Just call more general insert(pos, size, value) and return iterator
size_type pos_n = position - cbegin();
typedef container_detail::advanced_insert_aux_emplace<Allocator, T*, Args...> type;
type &&proxy = type(this->alloc(), ::boost::forward<Args>(args)...);
this->priv_forward_range_insert(position.get_ptr(), 1, proxy);
return iterator(this->members_.m_start + pos_n);
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
return this->priv_forward_range_insert
(position.get_ptr(), 1, type(this->alloc(), ::boost::forward<Args>(args)...));
}
#else
@@ -1143,8 +1113,8 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
++this->members_.m_size; \
} \
else{ \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
<Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
this->priv_forward_range_insert(back_pos, 1, proxy); \
} \
@@ -1154,12 +1124,11 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
iterator emplace(const_iterator pos \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
size_type pos_n = pos - cbegin(); \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
<Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
this->priv_forward_range_insert(container_detail::to_raw_pointer(pos.get_ptr()), 1,proxy);\
return iterator(this->members_.m_start + pos_n); \
return this->priv_forward_range_insert \
(container_detail::to_raw_pointer(pos.get_ptr()), 1, proxy); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
@@ -1222,7 +1191,10 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//!
//! <b>Complexity</b>: Linear to n.
iterator insert(const_iterator p, size_type n, const T& x)
{ return this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); }
{
container_detail::insert_n_copies_proxy<Allocator, T*> proxy(this->alloc(), x);
return this->priv_forward_range_insert(p.get_ptr(), n, proxy);
}
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
@@ -1250,7 +1222,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
it = this->emplace(it, *first);
++it;
}
return this->begin() + n_pos;
return iterator(this->members_.m_start + n_pos);
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1262,11 +1234,8 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
>::type * = 0
)
{
const size_type n_pos = pos - this->cbegin();
const size_type n = std::distance(first, last);
container_detail::advanced_insert_aux_proxy<Allocator, FwdIt, T*> proxy(this->alloc(), first, last);
this->priv_forward_range_insert(pos.get_ptr(), n, proxy);
return this->begin() + n_pos;
container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(this->alloc(), first);
return this->priv_forward_range_insert(pos.get_ptr(), std::distance(first, last), proxy);
}
#endif
@@ -1275,7 +1244,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant time.
void pop_back()
void pop_back() BOOST_CONTAINER_NOEXCEPT
{
//Destroy last element
--this->members_.m_size;
@@ -1290,8 +1259,8 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//! last element. Constant if pos is the last element.
iterator erase(const_iterator position)
{
T *pos = container_detail::to_raw_pointer(position.get_ptr());
T *beg = container_detail::to_raw_pointer(this->members_.m_start);
T *const pos = container_detail::to_raw_pointer(position.get_ptr());
T *const beg = container_detail::to_raw_pointer(this->members_.m_start);
::boost::move(pos + 1, beg + this->members_.m_size, pos);
--this->members_.m_size;
//Destroy last element
@@ -1307,14 +1276,14 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//! plus linear to the elements between pos and the last element.
iterator erase(const_iterator first, const_iterator last)
{
if (first != last){ // worth doing, copy down over hole
if (first != last){
T* end_pos = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
T* ptr = container_detail::to_raw_pointer(boost::move
(container_detail::to_raw_pointer(last.get_ptr())
,end_pos
,container_detail::to_raw_pointer(first.get_ptr())
));
size_type destroyed = (end_pos - ptr);
const size_type destroyed = (end_pos - ptr);
this->destroy_n(ptr, destroyed);
this->members_.m_size -= destroyed;
}
@@ -1361,26 +1330,15 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
}
private:
iterator priv_insert(const_iterator position, const T &x)
template<class U>
iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
{
//Just call more general insert(pos, size, value) and return iterator
size_type pos_n = position - cbegin();
this->insert(position, (size_type)1, x);
return iterator(this->members_.m_start + pos_n);
}
iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x)
{
//Just call more general insert(pos, size, value) and return iterator
size_type pos_n = position - cbegin();
this->insert(position
,repeat_move_it(repeat_it(x, 1))
,repeat_move_it(repeat_it()));
return iterator(this->members_.m_start + pos_n);
return this->priv_forward_range_insert
(p.get_ptr(), 1, container_detail::get_insert_value_proxy<T*>(this->alloc(), ::boost::forward<U>(x)));
}
template <class U>
void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
void priv_push_back(BOOST_FWD_REF(U) x)
{
if (this->members_.m_size < this->members_.m_capacity){
//There is more memory, just construct a new object at the end
@@ -1391,7 +1349,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
++this->members_.m_size;
}
else{
this->insert(this->cend(), ::boost::forward<U>(x));
this->priv_insert(this->cend(), ::boost::forward<U>(x));
}
}
@@ -1409,9 +1367,8 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
(allocate_new, this->size(), this->size(), real_cap, this->members_.m_start);
if(real_cap < this->capacity()){
//We will reuse insert code, so create a dummy input iterator
T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start));
container_detail::advanced_insert_aux_proxy<Allocator, boost::move_iterator<T*>, T*>
proxy(this->alloc(), ::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
proxy(this->alloc(), ::boost::make_move_iterator((T *)0));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
@@ -1450,65 +1407,79 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
}
}
void priv_forward_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf)
template <class InsertionProxy>
iterator priv_forward_range_insert
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
{
//Check if we have enough memory or try to expand current memory
size_type remaining = this->members_.m_capacity - this->members_.m_size;
bool same_buffer_start;
std::pair<pointer, bool> ret;
size_type real_cap = this->members_.m_capacity;
const size_type remaining = this->members_.m_capacity - this->members_.m_size;
const size_type n_pos = pos - this->members_.m_start;
T *const raw_pos = container_detail::to_raw_pointer(pos);
//Check if we already have room
if (n <= remaining){
same_buffer_start = true;
}
else{
//There is not enough memory, allocate a new
//buffer or expand the old one.
size_type new_cap = this->next_capacity(n);
ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
this->members_.m_size + n, new_cap, real_cap, this->members_.m_start);
if(alloc_version::value > 1){ //Version 2 allocator, compile time check
bool same_buffer_start = n <= remaining;
if (!same_buffer_start){
size_type real_cap = 0;
//There is not enough memory, allocate a new
//buffer or expand the old one.
std::pair<pointer, bool> ret = (this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
this->members_.m_size + n, this->next_capacity(n), real_cap, this->members_.m_start));
//Check for forward expansion
same_buffer_start = ret.second && this->members_.m_start == ret.first;
if(same_buffer_start){
this->members_.m_capacity = real_cap;
//Buffer reallocated
if(ret.second){
//Forward expansion, delay insertion
if(this->members_.m_start == ret.first){
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_fwd;
#endif
this->members_.m_capacity = real_cap;
//Expand forward
this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
}
//Backwards (and possibly forward) expansion
else{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_bwd;
#endif
this->priv_range_insert_expand_backwards
( container_detail::to_raw_pointer(ret.first)
, real_cap, raw_pos, n, insert_range_proxy);
}
}
//New buffer
else{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
this->priv_range_insert_new_allocation
( container_detail::to_raw_pointer(ret.first)
, real_cap, raw_pos, n, insert_range_proxy);
}
}
else{
//Expand forward
this->priv_range_insert_expand_forward
(raw_pos, n, insert_range_proxy);
}
}
//If we had room or we have expanded forward
if (same_buffer_start){
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_fwd;
#endif
this->priv_range_insert_expand_forward
(container_detail::to_raw_pointer(pos), n, interf);
}
//Backwards (and possibly forward) expansion
else if(ret.second){
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_bwd;
#endif
this->priv_range_insert_expand_backwards
( container_detail::to_raw_pointer(ret.first)
, real_cap
, container_detail::to_raw_pointer(pos)
, n
, interf);
}
//New buffer
else{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
this->priv_range_insert_new_allocation
( container_detail::to_raw_pointer(ret.first)
, real_cap
, container_detail::to_raw_pointer(pos)
, n
, interf);
else{ //Version 1 allocator
if (n <= remaining){
this->priv_range_insert_expand_forward
(raw_pos, n, insert_range_proxy);
}
else{
const size_type new_cap = this->next_capacity(n);
T * new_buf = container_detail::to_raw_pointer(this->alloc().allocate(new_cap));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
#endif
this->priv_range_insert_new_allocation
( new_buf, new_cap, raw_pos, n, insert_range_proxy);
}
}
return iterator(this->members_.m_start + n_pos);
}
//Absolutely experimental. This function might change, disappear or simply crash!
@@ -1660,15 +1631,21 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
}
private:
void priv_range_insert_expand_forward(T* pos, size_type n, advanced_insert_aux_int_t &interf)
template <class InsertionProxy>
void priv_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
{
//n can't be 0, because there is nothing to do in that case
if(!n) return;
//There is enough memory
T* old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
T* const old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
const size_type elems_after = old_finish - pos;
if (elems_after >= n){
if (!elems_after){
//Copy first new elements in pos
insert_range_proxy.uninitialized_copy_n_and_update(pos, n);
this->members_.m_size += n;
}
else if (elems_after >= n){
//New elements can be just copied.
//Move to uninitialized memory last objects
::boost::container::uninitialized_move_alloc
@@ -1677,24 +1654,31 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//Copy previous to last objects to the initialized end
boost::move_backward(pos, old_finish - n, old_finish);
//Insert new objects in the pos
interf.copy_remaining_to(pos);
insert_range_proxy.copy_n_and_update(pos, n);
}
else {
//The new elements don't fit in the [pos, end()) range. Copy
//to the beginning of the unallocated zone the last new elements.
interf.uninitialized_copy_some_and_update(old_finish, elems_after, false);
this->members_.m_size += n - elems_after;
//Copy old [pos, end()) elements to the uninitialized memory
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
this->members_.m_size += elems_after;
//Copy first new elements in pos
interf.copy_remaining_to(pos);
//The new elements don't fit in the [pos, end()) range.
//Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
::boost::container::uninitialized_move_alloc(this->alloc(), pos, old_finish, pos + n);
BOOST_TRY{
//Copy first new elements in pos (gap is still there)
insert_range_proxy.copy_n_and_update(pos, elems_after);
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
insert_range_proxy.uninitialized_copy_n_and_update(old_finish, n - elems_after);
this->members_.m_size += n;
}
BOOST_CATCH(...){
this->destroy_n(pos + n, elems_after);
BOOST_RETHROW
}
BOOST_CATCH_END
}
}
template <class InsertionProxy>
void priv_range_insert_new_allocation
(T* new_start, size_type new_cap, T* pos, size_type n, advanced_insert_aux_int_t &interf)
(T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
{
//n can be zero, if we want to reallocate!
T *new_finish = new_start;
@@ -1712,7 +1696,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
constructed_values_destroyer.increment_size(new_finish - old_finish);
}
//Initialize new objects, starting from previous point
interf.uninitialized_copy_remaining_to(old_finish = new_finish);
insert_range_proxy.uninitialized_copy_n_and_update(old_finish = new_finish, n);
new_finish += n;
constructed_values_destroyer.increment_size(new_finish - old_finish);
//Initialize from the rest of the old buffer,
@@ -1734,19 +1718,21 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
scoped_alloc.release();
}
template <class InsertionProxy>
void priv_range_insert_expand_backwards
(T* new_start, size_type new_capacity,
T* pos, const size_type n, advanced_insert_aux_int_t &interf)
(T* const new_start, const size_type new_capacity,
T* const pos, const size_type n, InsertionProxy insert_range_proxy)
{
//n can be zero to just expand capacity
//Backup old data
T* old_start = container_detail::to_raw_pointer(this->members_.m_start);
T* old_finish = old_start + this->members_.m_size;
size_type old_size = this->members_.m_size;
T* const old_start = container_detail::to_raw_pointer(this->members_.m_start);
T* const old_finish = old_start + this->members_.m_size;
const size_type old_size = this->members_.m_size;
//We can have 8 possibilities:
const size_type elemsbefore = (size_type)(pos - old_start);
const size_type s_before = (size_type)(old_start - new_start);
const size_type elemsbefore = static_cast<size_type>(pos - old_start);
const size_type s_before = static_cast<size_type>(old_start - new_start);
const size_type before_plus_new = elemsbefore + n;
//Update the vector buffer information to a safe state
this->members_.m_start = new_start;
@@ -1757,15 +1743,16 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//all the old objects to fulfill previous vector state
typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size);
//Check if s_before is big enough to hold the beginning of old data + new data
if(difference_type(s_before) >= difference_type(elemsbefore + n)){
if(s_before >= before_plus_new){
//Copy first old values before pos, after that the new objects
::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start);
T *const new_elem_pos = ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start);
this->members_.m_size = elemsbefore;
interf.uninitialized_copy_remaining_to(new_start + elemsbefore);
insert_range_proxy.uninitialized_copy_n_and_update(new_elem_pos, n);
this->members_.m_size += n;
//Check if s_before is so big that even copying the old data + new data
//there is a gap between the new data and the old data
if(s_before >= (old_size + n)){
const size_type new_size = old_size + n;
if(s_before >= new_size){
//Old situation:
// _________________________________________________________
//| raw_mem | old_begin | old_end |
@@ -1778,9 +1765,9 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//
//Now initialize the rest of memory with the last old values
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, new_start + elemsbefore + n);
(this->alloc(), pos, old_finish, new_start + before_plus_new);
//All new elements correctly constructed, avoid new element destruction
this->members_.m_size = old_size + n;
this->members_.m_size = new_size;
//Old values destroyed automatically with "old_values_destroyer"
//when "old_values_destroyer" goes out of scope unless the have trivial
//destructor after move.
@@ -1801,17 +1788,17 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//
//Now initialize the rest of memory with the last old values
//All new elements correctly constructed, avoid new element destruction
size_type raw_gap = s_before - (elemsbefore + n);
const size_type raw_gap = s_before - before_plus_new;
//Now initialize the rest of s_before memory with the
//first of elements after new values
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, pos + raw_gap, new_start + elemsbefore + n);
::boost::container::uninitialized_move_alloc_n
(this->alloc(), pos, raw_gap, new_start + before_plus_new);
//Update size since we have a contiguous buffer
this->members_.m_size = old_size + s_before;
//All new elements correctly constructed, avoid old element destruction
old_values_destroyer.release();
//Now copy remaining last objects in the old buffer begin
T *to_destroy = ::boost::move(pos + raw_gap, old_finish, old_start);
T * const to_destroy = ::boost::move(pos + raw_gap, old_finish, old_start);
//Now destroy redundant elements except if they were moved and
//they have trivial destructor after move
size_type n_destroy = old_finish - to_destroy;
@@ -1840,7 +1827,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//| old_begin + new + old_end | raw_mem |
//|____________________________|____________________|
//
bool do_after = n > s_before;
const bool do_after = n > s_before;
//Now we can have two situations: the raw_mem of the
//beginning divides the old_begin, or the new elements:
@@ -1869,28 +1856,26 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//|___________|_____|_________|_____________________|
//
//Copy the first part of old_begin to raw_mem
T *start_n = old_start + difference_type(s_before);
::boost::container::uninitialized_move_alloc
(this->alloc(), old_start, start_n, new_start);
::boost::container::uninitialized_move_alloc_n
(this->alloc(), old_start, s_before, new_start);
//The buffer is all constructed until old_end,
//release destroyer and update size
old_values_destroyer.release();
this->members_.m_size = old_size + s_before;
//Now copy the second part of old_begin overwriting himself
T* next = ::boost::move(start_n, pos, old_start);
//Now copy the second part of old_begin overwriting itself
T *const next = ::boost::move(old_start + s_before, pos, old_start);
if(do_after){
//Now copy the new_beg elements
interf.copy_some_and_update(next, s_before, true);
insert_range_proxy.copy_n_and_update(next, s_before);
}
else{
//Now copy the all the new elements
interf.copy_remaining_to(next);
T* move_start = next + n;
insert_range_proxy.copy_n_and_update(next, n);
//Now displace old_end elements
T* move_end = ::boost::move(pos, old_finish, move_start);
T* const move_end = ::boost::move(pos, old_finish, next + n);
//Destroy remaining moved elements from old_end except if
//they have trivial destructor after being moved
difference_type n_destroy = s_before - n;
const size_type n_destroy = s_before - n;
if(!value_traits::trivial_dctr_after_move)
this->destroy_n(move_end, n_destroy);
this->members_.m_size -= n_destroy;
@@ -1923,30 +1908,30 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//|___________|_____|_________|__________________________|
//
//First copy whole old_begin and part of new to raw_mem
::boost::container::uninitialized_move_alloc
T * const new_pos = ::boost::container::uninitialized_move_alloc
(this->alloc(), old_start, pos, new_start);
this->members_.m_size = elemsbefore;
const size_type mid_n = difference_type(s_before) - elemsbefore;
interf.uninitialized_copy_some_and_update(new_start + elemsbefore, mid_n, true);
this->members_.m_size = old_size + s_before;
const size_type mid_n = s_before - elemsbefore;
insert_range_proxy.uninitialized_copy_n_and_update(new_pos, mid_n);
//The buffer is all constructed until old_end,
//release destroyer and update size
//release destroyer
this->members_.m_size = old_size + s_before;
old_values_destroyer.release();
if(do_after){
//Copy new_beg part
interf.copy_some_and_update(old_start, s_before - mid_n, true);
insert_range_proxy.copy_n_and_update(old_start, elemsbefore);
}
else{
//Copy all new elements
interf.copy_remaining_to(old_start);
T* move_start = old_start + (n-mid_n);
const size_type rest_new = n - mid_n;
insert_range_proxy.copy_n_and_update(old_start, rest_new);
T* move_start = old_start + rest_new;
//Displace old_end
T* move_end = ::boost::move(pos, old_finish, move_start);
//Destroy remaining moved elements from old_end except if they
//have trivial destructor after being moved
difference_type n_destroy = s_before - n;
size_type n_destroy = s_before - n;
if(!value_traits::trivial_dctr_after_move)
this->destroy_n(move_end, n_destroy);
this->members_.m_size -= n_destroy;
@@ -1954,9 +1939,6 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
}
//This is only executed if two phase construction is needed
//This can be executed without exception handling since we
//have to just copy and append in raw memory and
//old_values_destroyer has been released in phase 1.
if(do_after){
//The raw memory divides the new elements
//
@@ -1975,11 +1957,11 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//| old_begin + new | old_end |raw |
//|_______________________________________|_________|____|
//
const size_type n_after = n - s_before;
const difference_type elemsafter = old_size - elemsbefore;
const size_type n_after = n - s_before;
const size_type elemsafter = old_size - elemsbefore;
//We can have two situations:
if (elemsafter > difference_type(n_after)){
if (elemsafter >= n_after){
//The raw_mem from end will divide displaced old_end
//
//Old situation:
@@ -1993,7 +1975,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//|__________________________|_________|________|_________|
//
//First copy the part of old_end raw_mem
T* finish_n = old_finish - difference_type(n_after);
T* finish_n = old_finish - n_after;
::boost::container::uninitialized_move_alloc
(this->alloc(), finish_n, old_finish, old_finish);
this->members_.m_size += n_after;
@@ -2001,7 +1983,7 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
boost::move_backward(pos, finish_n, old_finish);
//Now overwrite with new_end
//The new_end part is [first + (n - n_after), last)
interf.copy_remaining_to(pos);
insert_range_proxy.copy_n_and_update(pos, n_after);
}
else {
//The raw_mem from end will divide new_end part
@@ -2016,16 +1998,38 @@ class vector : private container_detail::vector_alloc_holder<Allocator>
//| old_begin + new_beg | new_end |old_end | raw_mem |
//|__________________________|_______________|________|_________|
//
const size_type mid_last_dist = n_after - elemsafter;
//First initialize data in raw memory
//Copy to the old_end part to the uninitialized zone leaving a gap.
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, old_finish + mid_last_dist);
BOOST_TRY{
//Copy the first part to the already constructed old_end zone
insert_range_proxy.copy_n_and_update(pos, elemsafter);
//Copy the rest to the uninitialized zone filling the gap
insert_range_proxy.uninitialized_copy_n_and_update(old_finish, mid_last_dist);
this->members_.m_size += n_after;
}
BOOST_CATCH(...){
this->destroy_n(pos, mid_last_dist);
BOOST_RETHROW
}
BOOST_CATCH_END
/*
size_type mid_last_dist = n_after - elemsafter;
//First initialize data in raw memory
//The new_end part is [first + (n - n_after), last)
interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
insert_range_proxy.uninitialized_copy_last_and_update(old_finish, elemsafter);
this->members_.m_size += mid_last_dist;
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, old_finish + mid_last_dist);
this->members_.m_size += n_after - mid_last_dist;
//Now copy the part of new_end over constructed elements
interf.copy_remaining_to(pos);
insert_range_proxy.copy_remaining_to(pos);*/
}
}
}
@@ -2083,17 +2087,14 @@ inline void swap(vector<T, Allocator>& x, vector<T, Allocator>& y)
namespace boost {
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
{
static const bool value = has_trivial_destructor<Allocator>::value;
};
: public ::boost::has_trivial_destructor_after_move<Allocator>
{};
*/
}