summaryrefslogtreecommitdiff
path: root/boost/container
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container')
-rw-r--r--boost/container/adaptive_pool.hpp6
-rw-r--r--boost/container/allocator_traits.hpp73
-rw-r--r--boost/container/deque.hpp28
-rw-r--r--boost/container/detail/copy_move_algo.hpp71
-rw-r--r--boost/container/detail/flat_tree.hpp98
-rw-r--r--boost/container/detail/iterator.hpp1
-rw-r--r--boost/container/detail/iterators.hpp12
-rw-r--r--boost/container/detail/mpl.hpp175
-rw-r--r--boost/container/detail/node_alloc_holder.hpp108
-rw-r--r--boost/container/detail/pair.hpp79
-rw-r--r--boost/container/detail/std_fwd.hpp6
-rw-r--r--boost/container/detail/tree.hpp91
-rw-r--r--boost/container/detail/type_traits.hpp1
-rw-r--r--boost/container/list.hpp4
-rw-r--r--boost/container/node_allocator.hpp6
-rw-r--r--boost/container/scoped_allocator.hpp52
-rw-r--r--boost/container/slist.hpp4
-rw-r--r--boost/container/small_vector.hpp12
-rw-r--r--boost/container/stable_vector.hpp81
-rw-r--r--boost/container/string.hpp57
-rw-r--r--boost/container/vector.hpp471
21 files changed, 716 insertions, 720 deletions
diff --git a/boost/container/adaptive_pool.hpp b/boost/container/adaptive_pool.hpp
index 1f6b6667e9..59ba37bc93 100644
--- a/boost/container/adaptive_pool.hpp
+++ b/boost/container/adaptive_pool.hpp
@@ -83,9 +83,9 @@ class adaptive_pool
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
- container_detail::unvoid<T>::type & reference;
- typedef const typename ::boost::container::
- container_detail::unvoid<T>::type & const_reference;
+ container_detail::unvoid_ref<T>::type reference;
+ typedef typename ::boost::container::
+ container_detail::unvoid_ref<const T>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp
index cdaf2eacf0..2c7900ea72 100644
--- a/boost/container/allocator_traits.hpp
+++ b/boost/container/allocator_traits.hpp
@@ -96,6 +96,10 @@ template<class T>
struct is_std_allocator< std::allocator<T> >
{ static const bool value = true; };
+template<class Allocator>
+struct is_not_std_allocator
+{ static const bool value = !is_std_allocator<Allocator>::value; };
+
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(const_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
@@ -195,11 +199,11 @@ struct allocator_traits
const_pointer;
//reference
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
- reference, typename container_detail::unvoid<value_type>::type&)
+ reference, typename container_detail::unvoid_ref<value_type>::type)
reference;
//const_reference
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
- const_reference, const typename container_detail::unvoid<value_type>::type&)
+ const_reference, typename container_detail::unvoid_ref<const value_type>::type)
const_reference;
//void_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator,
@@ -340,7 +344,12 @@ struct allocator_traits
template <class T, class ...Args>
static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
{
- container_detail::bool_<container_detail::is_std_allocator<Allocator>::value> flag;
+ static const bool value = ::boost::move_detail::and_
+ < container_detail::is_not_std_allocator<Allocator>
+ , boost::container::container_detail::has_member_function_callable_with_construct
+ < Allocator, T*, Args... >
+ >::value;
+ container_detail::bool_<value> flag;
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
}
#endif
@@ -391,25 +400,11 @@ struct allocator_traits
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class ...Args>
- static void priv_construct(container_detail::false_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
- {
- const bool value = boost::container::container_detail::
- has_member_function_callable_with_construct
- < Allocator, T*, Args... >::value;
- container_detail::bool_<value> flag;
- (priv_construct_dispatch_next)(flag, a, p, ::boost::forward<Args>(args)...);
- }
-
- template<class T, class ...Args>
static void priv_construct(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
- { (priv_construct_dispatch_next)(container_detail::false_type(), a, p, ::boost::forward<Args>(args)...); }
-
- template<class T, class ...Args>
- static void priv_construct_dispatch_next(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
{ a.construct( p, ::boost::forward<Args>(args)...); }
template<class T, class ...Args>
- static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
+ static void priv_construct(container_detail::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
public:
@@ -418,54 +413,38 @@ struct allocator_traits
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
- container_detail::bool_<container_detail::is_std_allocator<Allocator>::value> flag;\
+ static const bool value = ::boost::move_detail::and_ \
+ < container_detail::is_not_std_allocator<Allocator> \
+ , boost::container::container_detail::has_member_function_callable_with_construct \
+ < Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_FWD_T##N > \
+ >::value; \
+ container_detail::bool_<value> flag;\
(priv_construct)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
//
- BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL)
+ BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL)
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL
private:
-
- //////////////////
+ /////////////////////////////////
// priv_construct
- //////////////////
+ /////////////////////////////////
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL(N) \
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
- static void priv_construct(container_detail::false_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
- {\
- const bool value = boost::container::container_detail::has_member_function_callable_with_construct\
- < Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_FWD_T##N>::value;\
- container_detail::bool_<value> flag;\
- (priv_construct_dispatch_next)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
- }\
- \
- template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
static void priv_construct(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
- { (priv_construct_dispatch_next)(container_detail::false_type(), a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
- //
- BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL)
- #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL
-
- /////////////////////////////////
- // priv_construct_dispatch_next
- /////////////////////////////////
- #define BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_DISPATCH_NEXT_IMPL(N) \
- template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
- static void priv_construct_dispatch_next(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ a.construct( p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); }\
\
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
- static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ static void priv_construct(container_detail::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ ::new((void*)p, boost_container_new_t()) T(BOOST_MOVE_FWD##N); }\
//
- BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_DISPATCH_NEXT_IMPL)
- #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_DISPATCH_NEXT_IMPL
+ BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL)
+ #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T>
- static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
+ static void priv_construct(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
{ ::new((void*)p) T; }
static bool priv_storage_is_unpropagable(container_detail::true_type, const Allocator &a, pointer p)
diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp
index eb372a430a..bdfecc1212 100644
--- a/boost/container/deque.hpp
+++ b/boost/container/deque.hpp
@@ -835,9 +835,10 @@ class deque : protected deque_base<Allocator>
template <class InIt>
void assign(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InIt, size_type>::value
- && container_detail::is_input_iterator<InIt>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<InIt, size_type>
+ , container_detail::is_not_input_iterator<InIt>
>::type * = 0
#endif
)
@@ -857,9 +858,10 @@ class deque : protected deque_base<Allocator>
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
void assign(FwdIt first, FwdIt last
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<FwdIt, size_type>::value
- && !container_detail::is_input_iterator<FwdIt>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<FwdIt, size_type>
+ , container_detail::is_input_iterator<FwdIt>
>::type * = 0
)
{
@@ -1509,9 +1511,10 @@ class deque : protected deque_base<Allocator>
template <class InIt>
iterator insert(const_iterator pos, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InIt, size_type>::value
- && container_detail::is_input_iterator<InIt>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<InIt, size_type>
+ , container_detail::is_not_input_iterator<InIt>
>::type * = 0
#endif
)
@@ -1545,9 +1548,10 @@ class deque : protected deque_base<Allocator>
template <class FwdIt>
iterator insert(const_iterator p, FwdIt first, FwdIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<FwdIt, size_type>::value
- && !container_detail::is_input_iterator<FwdIt>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<FwdIt, size_type>
+ , container_detail::is_input_iterator<FwdIt>
>::type * = 0
#endif
)
diff --git a/boost/container/detail/copy_move_algo.hpp b/boost/container/detail/copy_move_algo.hpp
index 79cbde80a9..23fa730838 100644
--- a/boost/container/detail/copy_move_algo.hpp
+++ b/boost/container/detail/copy_move_algo.hpp
@@ -123,48 +123,49 @@ struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, D
template <typename I, typename O>
struct are_contiguous_and_same
-{
- static const bool is_same_io =
- is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type
- , typename ::boost::container::iterator_traits<O>::value_type
- >::value;
- static const bool value = is_same_io &&
- are_elements_contiguous<I>::value &&
- are_elements_contiguous<O>::value;
-};
+ : boost::move_detail::and_
+ < are_elements_contiguous<I>
+ , are_elements_contiguous<O>
+ , is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type
+ , typename ::boost::container::iterator_traits<O>::value_type
+ >
+ >
+{};
template <typename I, typename O>
struct is_memtransfer_copy_assignable
-{
- static const bool value = are_contiguous_and_same<I, O>::value &&
- container_detail::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >::value;
-};
+ : boost::move_detail::and_
+ < are_contiguous_and_same<I, O>
+ , container_detail::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >
+ >
+{};
template <typename I, typename O>
struct is_memtransfer_copy_constructible
-{
- static const bool value = are_contiguous_and_same<I, O>::value &&
- container_detail::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >::value;
-};
+ : boost::move_detail::and_
+ < are_contiguous_and_same<I, O>
+ , container_detail::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >
+ >
+{};
template <typename I, typename O, typename R>
struct enable_if_memtransfer_copy_constructible
- : enable_if_c<container_detail::is_memtransfer_copy_constructible<I, O>::value, R>
+ : enable_if<container_detail::is_memtransfer_copy_constructible<I, O>, R>
{};
template <typename I, typename O, typename R>
struct disable_if_memtransfer_copy_constructible
- : enable_if_c<!container_detail::is_memtransfer_copy_constructible<I, O>::value, R>
+ : disable_if<container_detail::is_memtransfer_copy_constructible<I, O>, R>
{};
template <typename I, typename O, typename R>
struct enable_if_memtransfer_copy_assignable
- : enable_if_c<container_detail::is_memtransfer_copy_assignable<I, O>::value, R>
+ : enable_if<container_detail::is_memtransfer_copy_assignable<I, O>, R>
{};
template <typename I, typename O, typename R>
struct disable_if_memtransfer_copy_assignable
- : enable_if_c<!container_detail::is_memtransfer_copy_assignable<I, O>::value, R>
+ : disable_if<container_detail::is_memtransfer_copy_assignable<I, O>, R>
{};
template
@@ -174,8 +175,10 @@ inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
- boost::container::iterator_advance(r, n);
+ if(n){
+ std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(r, n);
+ }
return r;
}
@@ -185,8 +188,10 @@ template
F memmove_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
- boost::container::iterator_advance(r, n);
+ if(n){
+ std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(r, n);
+ }
return r;
}
@@ -195,9 +200,11 @@ template
typename F> // F models ForwardIterator
I memmove_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
- typedef typename boost::container::iterator_traits<I>::value_type value_type;
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
- boost::container::iterator_advance(f, n);
+ if(n){
+ typedef typename boost::container::iterator_traits<I>::value_type value_type;
+ std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(f, n);
+ }
return f;
}
@@ -207,9 +214,11 @@ template
I memmove_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
- boost::container::iterator_advance(f, n);
- boost::container::iterator_advance(r, n);
+ if(n){
+ std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(f, n);
+ boost::container::iterator_advance(r, n);
+ }
return f;
}
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index a94043c6bd..f27421125f 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -470,20 +470,22 @@ class flat_tree
template <class BidirIt>
void insert_equal(ordered_range_t, BidirIt first, BidirIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_input_iterator<BidirIt>::value &&
- !container_detail::is_forward_iterator<BidirIt>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_input_iterator<BidirIt>
+ , container_detail::is_forward_iterator<BidirIt>
>::type * = 0
#endif
)
- { this->priv_insert_ordered_range(false, first, last); }
+ { this->m_data.m_vect.merge(first, last); }
template <class InIt>
void insert_unique(ordered_unique_range_t, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < container_detail::is_input_iterator<InIt>::value ||
- container_detail::is_forward_iterator<InIt>::value
+ , typename container_detail::enable_if_or
+ < void
+ , container_detail::is_input_iterator<InIt>
+ , container_detail::is_forward_iterator<InIt>
>::type * = 0
#endif
)
@@ -504,7 +506,7 @@ class flat_tree
>::type * = 0
#endif
)
- { this->priv_insert_ordered_range(true, first, last); }
+ { this->m_data.m_vect.merge_unique(first, last, value_compare()); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -855,8 +857,8 @@ class flat_tree
}
template <class RanIt>
- RanIt priv_upper_bound(RanIt first, const RanIt last,
- const key_type & key) const
+ RanIt priv_upper_bound
+ (RanIt first, const RanIt last,const key_type & key) const
{
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
@@ -904,9 +906,9 @@ class flat_tree
//Middle is equal to key
last = first;
last += len;
+ RanIt const first_ret = this->priv_lower_bound(first, middle, key);
return std::pair<RanIt, RanIt>
- ( this->priv_lower_bound(first, middle, key)
- , this->priv_upper_bound(++middle, last, key));
+ ( first_ret, this->priv_upper_bound(++middle, last, key));
}
}
return std::pair<RanIt, RanIt>(first, first);
@@ -939,81 +941,11 @@ class flat_tree
for ( ; first != last; ++first){
//If ordered, then try hint version
//to achieve constant-time complexity per insertion
+ //in some cases
pos = this->insert_equal(pos, *first);
++pos;
}
}
-
- template <class BidirIt>
- void priv_insert_ordered_range(const bool unique_values, BidirIt first, BidirIt last)
- {
- size_type len = static_cast<size_type>(boost::container::iterator_distance(first, last));
- //Prereserve all memory so that iterators are not invalidated
- this->reserve(this->size()+len);
- //Auxiliary data for insertion positions.
- const size_type BurstSize = len;
- const ::boost::movelib::unique_ptr<size_type[]> positions =
- ::boost::movelib::make_unique_definit<size_type[]>(BurstSize);
-
- const const_iterator b(this->cbegin());
- const const_iterator ce(this->cend());
- const_iterator pos(b);
- const value_compare &val_cmp = this->m_data;
- //Loop in burst sizes
- bool back_insert = false;
- while(len && !back_insert){
- const size_type burst = len < BurstSize ? len : BurstSize;
- size_type unique_burst = 0u;
- size_type checked = 0;
- for(; checked != burst; ++checked){
- //Get the insertion position for each key, use iterator_traits<BidirIt>::value_type
- //because it can be different from container::value_type
- //(e.g. conversion between std::pair<T1, T2> -> boost::container::pair<T1, T2>
- const typename boost::container::iterator_traits<BidirIt>::value_type & val = *first;
- pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
- //Check if already present
- if (pos != ce){
- ++first;
- --len;
- positions[checked] = (unique_values && !val_cmp(val, *pos)) ?
- size_type(-1) : (++unique_burst, static_cast<size_type>(pos - b));
- }
- else{ //this element and the remaining should be back inserted
- back_insert = true;
- break;
- }
- }
- if(unique_burst){
- //Insert all in a single step in the precalculated positions
- this->m_data.m_vect.insert_ordered_at(unique_burst, positions.get() + checked, first);
- //Next search position updated, iterator still valid because we've preserved the vector
- pos += unique_burst;
- }
- }
- //The remaining range should be back inserted
- if(unique_values){
- while(len--){
- BidirIt next(first);
- ++next;
- //Use iterator_traits<BidirIt>::value_type
- //because it can be different from container::value_type
- //(e.g. conversion between std::pair<T1, T2> -> boost::container::pair<T1, T2>
- const typename boost::container::iterator_traits<BidirIt>::value_type & val = *first;
- if (next == last || val_cmp(val, *next)){
- const bool room = this->m_data.m_vect.stable_emplace_back(*first);
- (void)room;
- BOOST_ASSERT(room);
- }
- first = next;
- }
- BOOST_ASSERT(first == last);
- }
- else{
- BOOST_ASSERT(size_type(boost::container::iterator_distance(first, last)) == len);
- if(len)
- this->m_data.m_vect.insert(this->m_data.m_vect.cend(), len, first, last);
- }
- }
};
} //namespace container_detail {
diff --git a/boost/container/detail/iterator.hpp b/boost/container/detail/iterator.hpp
index ceb224f3ad..8538acc161 100644
--- a/boost/container/detail/iterator.hpp
+++ b/boost/container/detail/iterator.hpp
@@ -32,6 +32,7 @@ using ::boost::intrusive::iterator_advance;
using ::boost::intrusive::iterator;
using ::boost::intrusive::iterator_enable_if_tag;
using ::boost::intrusive::iterator_disable_if_tag;
+using ::boost::intrusive::iterator_arrow_result;
} //namespace container {
} //namespace boost {
diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp
index 1f80d3e122..e8cfcf97a4 100644
--- a/boost/container/detail/iterators.hpp
+++ b/boost/container/detail/iterators.hpp
@@ -651,11 +651,13 @@ namespace container_detail {
template<class T>
struct has_iterator_category
{
+ struct two { char _[2]; };
+
template <typename X>
static char test(int, typename X::iterator_category*);
template <typename X>
- static int test(int, ...);
+ static two test(int, ...);
static const bool value = (1 == sizeof(test<T>(0, 0)));
};
@@ -673,6 +675,12 @@ struct is_input_iterator<T, false>
static const bool value = false;
};
+template<class T>
+struct is_not_input_iterator
+{
+ static const bool value = !is_input_iterator<T>::value;
+};
+
template<class T, bool = has_iterator_category<T>::value >
struct is_forward_iterator
{
@@ -796,7 +804,7 @@ class iterator_from_iiterator
{ return !(l == r); }
reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
- { return (*this->m_iit).get_data(); }
+ { return this->m_iit->get_data(); }
pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
{ return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
diff --git a/boost/container/detail/mpl.hpp b/boost/container/detail/mpl.hpp
index 74b618f8c6..e1684ea0b1 100644
--- a/boost/container/detail/mpl.hpp
+++ b/boost/container/detail/mpl.hpp
@@ -23,6 +23,8 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
#include <cstddef>
@@ -30,110 +32,35 @@ namespace boost {
namespace container {
namespace container_detail {
-template <class T, T val>
-struct integral_constant
-{
- static const T value = val;
- typedef integral_constant<T,val> type;
-};
-
-template< bool C_ >
-struct bool_ : integral_constant<bool, C_>
-{
- static const bool value = C_;
- operator bool() const { return bool_::value; }
-};
-
-template< unsigned V_ >
-struct unsigned_ : integral_constant<unsigned, V_>
-{
- static const unsigned value = V_;
- operator unsigned() const { return unsigned_::value; }
-};
-
-typedef bool_<true> true_;
-typedef bool_<false> false_;
-
-typedef true_ true_type;
-typedef false_ false_type;
-
-typedef char yes_type;
-struct no_type
-{
- char padding[8];
-};
-
-template <bool B, class T = void>
-struct enable_if_c {
- typedef T type;
-};
-
-template <class T>
-struct enable_if_c<false, T> {};
-
-template <class Cond, class T = void>
-struct enable_if : public enable_if_c<Cond::value, T> {};
-
-template <class Cond, class T = void>
-struct disable_if : public enable_if_c<!Cond::value, T> {};
-
-template <bool B, class T = void>
-struct disable_if_c : public enable_if_c<!B, T> {};
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-
-template <class T, class U>
-struct is_convertible
-{
- static const bool value = __is_convertible_to(T, U);
-};
-
-#else
-
-template <class T, class U>
-class is_convertible
-{
- typedef char true_t;
- class false_t { char dummy[2]; };
- //use any_conversion as first parameter since in MSVC
- //overaligned types can't go through ellipsis
- static false_t dispatch(...);
- static true_t dispatch(U);
- static T &trigger();
- public:
- static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
-};
-
-#endif
-
-template<
- bool C
- , typename T1
- , typename T2
- >
-struct if_c
-{
- typedef T1 type;
-};
-
-template<
- typename T1
- , typename T2
- >
-struct if_c<false,T1,T2>
-{
- typedef T2 type;
-};
-
-template<
- typename T1
- , typename T2
- , typename T3
- >
-struct if_
-{
- typedef typename if_c<0 != T1::value, T2, T3>::type type;
-};
+using boost::move_detail::integral_constant;
+using boost::move_detail::true_type;
+using boost::move_detail::false_type;
+using boost::move_detail::enable_if_c;
+using boost::move_detail::enable_if;
+using boost::move_detail::enable_if_convertible;
+using boost::move_detail::disable_if_c;
+using boost::move_detail::disable_if;
+using boost::move_detail::disable_if_convertible;
+using boost::move_detail::is_convertible;
+using boost::move_detail::if_c;
+using boost::move_detail::if_;
+using boost::move_detail::identity;
+using boost::move_detail::bool_;
+using boost::move_detail::true_;
+using boost::move_detail::false_;
+using boost::move_detail::yes_type;
+using boost::move_detail::no_type;
+using boost::move_detail::bool_;
+using boost::move_detail::true_;
+using boost::move_detail::false_;
+using boost::move_detail::unvoid_ref;
+using boost::move_detail::and_;
+using boost::move_detail::or_;
+using boost::move_detail::not_;
+using boost::move_detail::enable_if_and;
+using boost::move_detail::disable_if_and;
+using boost::move_detail::enable_if_or;
+using boost::move_detail::disable_if_or;
template <class Pair>
@@ -150,46 +77,6 @@ struct select1st
{ return x; }
};
-// identity is an extension: it is not part of the standard.
-template <class T>
-struct identity
-{
- typedef T argument_type;
- typedef T result_type;
-
- typedef T type;
- const T& operator()(const T& x) const
- { return x; }
-};
-
-template<std::size_t S>
-struct ls_zeros
-{
- static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
-};
-
-template<>
-struct ls_zeros<0>
-{
- static const std::size_t value = 0;
-};
-
-template<>
-struct ls_zeros<1>
-{
- static const std::size_t value = 0;
-};
-
-template <std::size_t OrigSize, std::size_t RoundTo>
-struct ct_rounded_size
-{
- static const std::size_t value = ((OrigSize-1)/RoundTo+1)*RoundTo;
-};
-
-template <typename T> struct unvoid { typedef T type; };
-template <> struct unvoid<void> { struct type { }; };
-template <> struct unvoid<const void> { struct type { }; };
-
} //namespace container_detail {
} //namespace container {
} //namespace boost {
diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp
index 98c8e62baa..3b632a677d 100644
--- a/boost/container/detail/node_alloc_holder.hpp
+++ b/boost/container/detail/node_alloc_holder.hpp
@@ -173,87 +173,25 @@ struct node_alloc_holder
}
#else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- NodePtr create_node()
- {
- NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- (this->node_alloc(), container_detail::addressof(p->m_data));
- node_deallocator.release();
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
- return (p);
- }
-
- template<BOOST_MOVE_CLASS1>
- NodePtr create_node(BOOST_MOVE_UREF1)
- {
- NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- (this->node_alloc(), container_detail::addressof(p->m_data)
- , BOOST_MOVE_FWD1);
- node_deallocator.release();
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
- return (p);
- }
- template<BOOST_MOVE_CLASS2>
- NodePtr create_node(BOOST_MOVE_UREF2)
- {
- NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- (this->node_alloc(), container_detail::addressof(p->m_data)
- , BOOST_MOVE_FWD2);
- node_deallocator.release();
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
- return (p);
- }
-
- template<BOOST_MOVE_CLASS3>
- NodePtr create_node(BOOST_MOVE_UREF3)
- {
- NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- (this->node_alloc(), container_detail::addressof(p->m_data)
- , BOOST_MOVE_FWD3);
- node_deallocator.release();
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
- return (p);
- }
-
- template<BOOST_MOVE_CLASS4>
- NodePtr create_node(BOOST_MOVE_UREF4)
- {
- NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- (this->node_alloc(), container_detail::addressof(p->m_data)
- , BOOST_MOVE_FWD4);
- node_deallocator.release();
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
- return (p);
- }
-
- template<BOOST_MOVE_CLASS5>
- NodePtr create_node(BOOST_MOVE_UREF5)
- {
- NodePtr p = this->allocate_one();
- Deallocator node_deallocator(p, this->node_alloc());
- allocator_traits<NodeAlloc>::construct
- (this->node_alloc(), container_detail::addressof(p->m_data)
- , BOOST_MOVE_FWD5);
- node_deallocator.release();
- typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
- return (p);
- }
+ #define BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ NodePtr create_node(BOOST_MOVE_UREF##N)\
+ {\
+ NodePtr p = this->allocate_one();\
+ Deallocator node_deallocator(p, this->node_alloc());\
+ allocator_traits<NodeAlloc>::construct\
+ ( this->node_alloc()\
+ , container_detail::addressof(p->m_data)\
+ BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ node_deallocator.release();\
+ typedef typename Node::hook_type hook_type;\
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
+ return (p);\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL)
+ #undef BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -375,7 +313,7 @@ struct node_alloc_holder
{}
NodePtr operator()(const Node &other) const
- { return m_holder.create_node(other.get_data()); }
+ { return m_holder.create_node(other.m_data); }
node_alloc_holder &m_holder;
};
@@ -387,7 +325,9 @@ struct node_alloc_holder
{}
NodePtr operator()(Node &other)
- { return m_holder.create_node(::boost::move(other.get_data())); }
+ { //Use m_data instead of get_data to allow moving const key in [multi]map
+ return m_holder.create_node(::boost::move(other.m_data));
+ }
node_alloc_holder &m_holder;
};
@@ -413,12 +353,12 @@ struct node_alloc_holder
template<class ConvertibleToAlloc>
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
- , m_icont(typename ICont::value_compare(c))
+ , m_icont(typename ICont::key_compare(c))
{}
explicit members_holder(const value_compare &c)
: NodeAlloc()
- , m_icont(typename ICont::value_compare(c))
+ , m_icont(typename ICont::key_compare(c))
{}
//The intrusive container
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 6d31d3b796..35e8846caa 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -33,6 +33,46 @@
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/utility_core.hpp>
+/*
+namespace boost{
+
+template<class T1, class T2>
+inline rv< std::pair<T1, T2> > &move(std::pair<T1, T2> &r)
+{
+ return reinterpret_cast< rv< std::pair<T1, T2> > &>(r);
+}
+
+template<class T1, class T2>
+inline rv< std::pair<T1, T2> > &move(rv< std::pair<T1, T2> > &r)
+{
+ return r;
+}
+
+template <class T>
+inline typename ::boost::move_detail::enable_if_and
+ < T &
+ , boost::container::container_detail::is_std_pair<T>
+ , ::boost::move_detail::is_rv<T>
+ >::type
+ forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+{
+ return const_cast<T&>(x);
+}
+
+template <class T>
+inline typename ::boost::move_detail::enable_if_and
+ < const T &
+ , boost::container::container_detail::is_std_pair<T>
+ , ::boost::move_detail::is_not_rv<T>
+ >::type
+ forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+{
+ return x;
+}
+
+} //namespace boost {
+*/
+
namespace boost {
namespace container {
namespace container_detail {
@@ -58,6 +98,24 @@ struct is_pair< std::pair<T1, T2> >
static const bool value = true;
};
+template <class T>
+struct is_not_pair
+{
+ static const bool value = !is_pair<T>::value;
+};
+
+template <class T>
+struct is_std_pair
+{
+ static const bool value = false;
+};
+
+template <class T1, class T2>
+struct is_std_pair< std::pair<T1, T2> >
+{
+ static const bool value = true;
+};
+
struct pair_nat;
struct piecewise_construct_t { };
@@ -182,10 +240,11 @@ struct pair
}
template <class D, class S>
- typename ::boost::container::container_detail::enable_if_c
- < !(::boost::container::container_detail::is_same<T1, D>::value &&
- ::boost::container::container_detail::is_same<T2, S>::value)
- , pair &>::type
+ typename ::boost::container::container_detail::disable_if_or
+ < pair &
+ , ::boost::container::container_detail::is_same<T1, D>
+ , ::boost::container::container_detail::is_same<T2, S>
+ >::type
operator=(const pair<D, S>&p)
{
first = p.first;
@@ -194,18 +253,18 @@ struct pair
}
template <class D, class S>
- typename ::boost::container::container_detail::enable_if_c
- < !(::boost::container::container_detail::is_same<T1, D>::value &&
- ::boost::container::container_detail::is_same<T2, S>::value)
- , pair &>::type
+ typename ::boost::container::container_detail::disable_if_or
+ < pair &
+ , ::boost::container::container_detail::is_same<T1, D>
+ , ::boost::container::container_detail::is_same<T2, S>
+ >::type
operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
{
first = ::boost::move(p.first);
second = ::boost::move(p.second);
return *this;
}
-
- //std::pair copy assignment
+//std::pair copy assignment
pair& operator=(const std::pair<T1, T2> &p)
{
first = p.first;
diff --git a/boost/container/detail/std_fwd.hpp b/boost/container/detail/std_fwd.hpp
index a2931c134b..1277df071f 100644
--- a/boost/container/detail/std_fwd.hpp
+++ b/boost/container/detail/std_fwd.hpp
@@ -23,10 +23,12 @@
// Standard predeclarations
//////////////////////////////////////////////////////////////////////////////
-#if defined(__clang__) && defined(_LIBCPP_VERSION)
+#if defined(_LIBCPP_VERSION)
#define BOOST_CONTAINER_CLANG_INLINE_STD_NS
#pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #if defined(__clang__)
+ #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #endif
#define BOOST_CONTAINER_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD
#define BOOST_CONTAINER_STD_NS_END _LIBCPP_END_NAMESPACE_STD
#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION) //GCC >= 4.6
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index 0f90b5a4e2..c90202973a 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -43,6 +43,7 @@
#include <boost/intrusive/sgtree.hpp>
// intrusive/detail
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+#include <boost/intrusive/detail/tree_value_compare.hpp> //tree_value_compare
// move
#include <boost/move/utility_core.hpp>
// move/detail
@@ -52,57 +53,15 @@
// other
#include <boost/core/no_exceptions_support.hpp>
-namespace boost {
-namespace container {
-namespace container_detail {
-template<class Key, class T, class Compare, class KeyOfValue>
-struct tree_value_compare
- : public Compare
-{
- typedef T value_type;
- typedef Compare key_compare;
- typedef KeyOfValue key_of_value;
- typedef Key key_type;
- explicit tree_value_compare(const key_compare &kcomp)
- : Compare(kcomp)
- {}
-
- tree_value_compare()
- : Compare()
- {}
+#include <boost/container/detail/std_fwd.hpp>
- const key_compare &key_comp() const
- { return static_cast<const key_compare &>(*this); }
-
- key_compare &key_comp()
- { return static_cast<key_compare &>(*this); }
-
- template<class U>
- struct is_key
- {
- static const bool value = is_same<const U, const key_type>::value;
- };
-
- template<class U>
- typename enable_if_c<is_key<U>::value, const key_type &>::type
- key_forward(const U &key) const
- { return key; }
-
- template<class U>
- typename enable_if_c<!is_key<U>::value, const key_type &>::type
- key_forward(const U &key) const
- { return KeyOfValue()(key); }
-
- template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2) const
- { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
+namespace boost {
+namespace container {
+namespace container_detail {
- template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2)
- { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
-};
+using boost::intrusive::tree_value_compare;
template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct intrusive_tree_hook;
@@ -156,7 +115,7 @@ struct tree_internal_data_type
template<class T1, class T2>
struct tree_internal_data_type< std::pair<T1, T2> >
{
- typedef pair<T1, T2> type;
+ typedef pair<typename boost::move_detail::remove_const<T1>::type, T2> type;
};
//The node to be store in the tree
@@ -549,9 +508,10 @@ class tree
tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < container_detail::is_input_iterator<InputIterator>::value
- || container_detail::is_same<alloc_version, version_1>::value
+ , typename container_detail::enable_if_or
+ < void
+ , container_detail::is_same<alloc_version, version_1>
+ , container_detail::is_input_iterator<InputIterator>
>::type * = 0
#endif
)
@@ -577,9 +537,10 @@ class tree
tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !(container_detail::is_input_iterator<InputIterator>::value
- || container_detail::is_same<alloc_version, version_1>::value)
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_same<alloc_version, version_1>
+ , container_detail::is_input_iterator<InputIterator>
>::type * = 0
#endif
)
@@ -606,10 +567,11 @@ class tree
tree( ordered_range_t, InputIterator first, InputIterator last
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < container_detail::is_input_iterator<InputIterator>::value
- || container_detail::is_same<alloc_version, version_1>::value
- >::type * = 0
+ , typename container_detail::enable_if_or
+ < void
+ , container_detail::is_same<alloc_version, version_1>
+ , container_detail::is_input_iterator<InputIterator>
+ >::type * = 0
#endif
)
: AllocHolder(value_compare(comp), a)
@@ -623,10 +585,11 @@ class tree
tree( ordered_range_t, InputIterator first, InputIterator last
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !(container_detail::is_input_iterator<InputIterator>::value
- || container_detail::is_same<alloc_version, version_1>::value)
- >::type * = 0
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_same<alloc_version, version_1>
+ , container_detail::is_input_iterator<InputIterator>
+ >::type * = 0
#endif
)
: AllocHolder(value_compare(comp), a)
@@ -663,7 +626,7 @@ class tree
}
else{
this->icont().clone_from
- (x.icont(), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc()));
+ (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc()));
}
}
@@ -730,7 +693,7 @@ class tree
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
- (x.icont()
+ (::boost::move(x.icont())
, RecyclingCloner<AllocHolder, true>(*this, other_tree)
, Destroyer(this->node_alloc()));
diff --git a/boost/container/detail/type_traits.hpp b/boost/container/detail/type_traits.hpp
index 1ae2426863..e02709ac6e 100644
--- a/boost/container/detail/type_traits.hpp
+++ b/boost/container/detail/type_traits.hpp
@@ -31,6 +31,7 @@ namespace container {
namespace container_detail {
using ::boost::move_detail::is_same;
+using ::boost::move_detail::is_different;
using ::boost::move_detail::is_pointer;
using ::boost::move_detail::add_reference;
using ::boost::move_detail::add_const;
diff --git a/boost/container/list.hpp b/boost/container/list.hpp
index 54da6df518..5135eaecee 100644
--- a/boost/container/list.hpp
+++ b/boost/container/list.hpp
@@ -417,9 +417,7 @@ class list
template <class InpIt>
void assign(InpIt first, InpIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InpIt, size_type>::value
- >::type * = 0
+ , typename container_detail::disable_if_convertible<InpIt, size_type>::type * = 0
#endif
)
{
diff --git a/boost/container/node_allocator.hpp b/boost/container/node_allocator.hpp
index afd6f98a8d..c3d809078f 100644
--- a/boost/container/node_allocator.hpp
+++ b/boost/container/node_allocator.hpp
@@ -74,9 +74,9 @@ class node_allocator
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
- container_detail::unvoid<T>::type & reference;
- typedef const typename ::boost::container::
- container_detail::unvoid<T>::type & const_reference;
+ container_detail::unvoid_ref<T>::type reference;
+ typedef typename ::boost::container::
+ container_detail::unvoid_ref<const T>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
diff --git a/boost/container/scoped_allocator.hpp b/boost/container/scoped_allocator.hpp
index 55514aae21..0724f948fb 100644
--- a/boost/container/scoped_allocator.hpp
+++ b/boost/container/scoped_allocator.hpp
@@ -1129,7 +1129,7 @@ class scoped_allocator_adaptor
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
void
#else
- typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type
+ typename container_detail::enable_if<container_detail::is_not_pair<T> >::type
#endif
construct(T* p, BOOST_FWD_REF(Args)...args)
{
@@ -1146,7 +1146,7 @@ class scoped_allocator_adaptor
//overload selection problems when the first parameter is a pair.
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \
template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
- typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type\
+ typename container_detail::enable_if< container_detail::is_not_pair<T> >::type\
construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
{\
container_detail::dispatch_uses_allocator\
@@ -1188,12 +1188,12 @@ class scoped_allocator_adaptor
template <class T1, class T2, class U, class V>
void construct( std::pair<T1, T2>* p
, BOOST_RV_REF_BEG std::pair<U, V> BOOST_RV_REF_END x)
- { this->construct_pair(p, x); }
+ { this->construct_pair(p, ::boost::move(x)); }
template <class T1, class T2, class U, class V>
void construct( container_detail::pair<T1, T2>* p
, BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
- { this->construct_pair(p, x); }
+ { this->construct_pair(p, ::boost::move(x)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
@@ -1246,6 +1246,39 @@ class scoped_allocator_adaptor
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
+template<bool ZeroInner>
+struct scoped_allocator_operator_equal
+{
+ //Optimize equal outer allocator types with
+ //allocator_traits::equal which uses is_always_equal
+ template<class IA>
+ static bool equal_outer(const IA &l, const IA &r)
+ { return allocator_traits<IA>::equal(l, r); }
+
+ //Otherwise compare it normally
+ template<class IA1, class IA2>
+ static bool equal_outer(const IA1 &l, const IA2 &r)
+ { return l == r; }
+
+ //Otherwise compare it normally
+ template<class IA>
+ static bool equal_inner(const IA &l, const IA &r)
+ { return allocator_traits<IA>::equal(l, r); }
+};
+
+template<>
+struct scoped_allocator_operator_equal<true>
+ : scoped_allocator_operator_equal<false>
+{
+ //when inner allocator count is zero,
+ //inner_allocator_type is the same as outer_allocator_type
+ //so both types can be different in operator==
+ template<class IA1, class IA2>
+ static bool equal_inner(const IA1 &, const IA2 &)
+ { return true; }
+};
+
+
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
@@ -1255,14 +1288,9 @@ inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_S
#else
const bool has_zero_inner = boost::container::container_detail::is_same<P0, void>::value;
#endif
- typedef typename scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>
- ::outer_allocator_type outer_allocator_type;
- typedef typename scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>
- ::inner_allocator_type inner_allocator_type;
-
- return allocator_traits<outer_allocator_type>::equal(a.outer_allocator(), b.outer_allocator())
- && (has_zero_inner ||
- allocator_traits<inner_allocator_type>::equal(a.inner_allocator(), b.inner_allocator()));
+ typedef scoped_allocator_operator_equal<has_zero_inner> equal_t;
+ return equal_t::equal_outer(a.outer_allocator(), b.outer_allocator()) &&
+ equal_t::equal_inner(a.inner_allocator(), b.inner_allocator());
}
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
diff --git a/boost/container/slist.hpp b/boost/container/slist.hpp
index b0901ef086..2b53df132f 100644
--- a/boost/container/slist.hpp
+++ b/boost/container/slist.hpp
@@ -442,9 +442,7 @@ class slist
template <class InpIt>
void assign(InpIt first, InpIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InpIt, size_type>::value
- >::type * = 0
+ , typename container_detail::disable_if_convertible<InpIt, size_type>::type * = 0
#endif
)
{
diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp
index 7ef0c238a3..a9f7522205 100644
--- a/boost/container/small_vector.hpp
+++ b/boost/container/small_vector.hpp
@@ -60,7 +60,7 @@ class small_vector_base;
//! for documentation purposes.
//!
//! This allocator inherits from a standard-conforming allocator
-//! and forwards member functiond to the standard allocator except
+//! and forwards member functions to the standard allocator except
//! when internal storage is being used as memory source.
//!
//! This allocator is a "partially_propagable" allocator and
@@ -68,7 +68,7 @@ class small_vector_base;
//!
//! A partially propagable allocator means that not all storage
//! allocatod by an instance of `small_vector_allocator` can be
-//! deallocated by another instance of this type, even is both
+//! deallocated by another instance of this type, even if both
//! instances compare equal or an instance is propagated to another
//! one using the copy/move constructor or assignment. The storage that
//! can never be propagated is identified by `storage_is_unpropagable(p)`.
@@ -311,8 +311,12 @@ class small_vector_base
: public vector<T, small_vector_allocator<SecondaryAllocator> >
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ public:
+ //Make it public as it will be inherited by small_vector and container
+ //must have this public member
typedef typename allocator_traits<SecondaryAllocator>::pointer pointer;
+ private:
BOOST_COPYABLE_AND_MOVABLE(small_vector_base)
friend class small_vector_allocator<SecondaryAllocator>;
@@ -428,8 +432,8 @@ struct small_vector_storage_definer
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-//! small_vector a vector-like container optimized for the case when it contains few elements.
-//! It contains some preallocated elements in-place, which allows it to avoid the use of dynamic storage allocation
+//! small_vector is a vector-like container optimized for the case when it contains few elements.
+//! It contains some preallocated elements in-place, which can avoid the use of dynamic storage allocation
//! when the actual number of elements is below that preallocated threshold.
//!
//! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent
diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp
index 76c9e9f07b..6aca69bde6 100644
--- a/boost/container/stable_vector.hpp
+++ b/boost/container/stable_vector.hpp
@@ -349,7 +349,7 @@ class stable_vector_iterator
return tmp;
}
- friend difference_type operator-(const stable_vector_iterator& left, const stable_vector_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
+ friend difference_type operator-(const stable_vector_iterator &left, const stable_vector_iterator &right) BOOST_NOEXCEPT_OR_NOTHROW
{ return left.m_pn->up - right.m_pn->up; }
//Comparison operators
@@ -493,7 +493,7 @@ class stable_vector
, false> iterator_impl;
typedef stable_vector_iterator
< typename allocator_traits<Allocator>::pointer
- , false> const_iterator_impl;
+ , true> const_iterator_impl;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -687,7 +687,7 @@ class stable_vector
: internal_data(l), index(l)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
- insert(cend(), il.begin(), il.end())
+ insert(cend(), il.begin(), il.end());
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -804,6 +804,7 @@ class stable_vector
//Resources can be transferred if both allocators are
//going to be equal after this function (either propagated or already equal)
if(propagate_alloc || allocators_equal){
+ STABLE_VECTOR_CHECK_INVARIANT
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
@@ -850,13 +851,12 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
template<typename InputIterator>
- void assign(InputIterator first,InputIterator last
- #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InputIterator, size_type>::value
- >::type * = 0
- #endif
- )
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typename container_detail::disable_if_convertible<InputIterator, size_type>::type
+ #else
+ void
+ #endif
+ assign(InputIterator first,InputIterator last)
{
STABLE_VECTOR_CHECK_INVARIANT;
iterator first1 = this->begin();
@@ -1112,13 +1112,12 @@ class stable_vector
{
const size_type index_size = this->index.size();
BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
- const size_type bucket_extra_capacity = this->index.capacity()- index_size;
const size_type node_extra_capacity = this->internal_data.pool_size;
- const size_type extra_capacity = (bucket_extra_capacity < node_extra_capacity)
- ? bucket_extra_capacity : node_extra_capacity;
+ //Pool count must be less than index capacity, as index is a vector
+ BOOST_ASSERT(node_extra_capacity <= (this->index.capacity()- index_size));
const size_type index_offset =
- (ExtraPointers + extra_capacity) & (size_type(0u) - size_type(index_size != 0));
- return index_size - index_offset;
+ (node_extra_capacity - ExtraPointers) & (size_type(0u) - size_type(index_size != 0));
+ return index_size + index_offset;
}
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -1294,11 +1293,10 @@ class stable_vector
return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
}
- //! <b>Requires</b>: size() >= n.
+ //! <b>Requires</b>: begin() <= p <= end().
//!
- //! <b>Effects</b>: Returns an iterator to the nth element
- //! from the beginning of the container. Returns end()
- //! if n == size().
+ //! <b>Effects</b>: Returns the index of the element pointed by p
+ //! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
@@ -1517,14 +1515,16 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to distance [first, last).
template <class InputIterator>
- iterator insert(const_iterator p, InputIterator first, InputIterator last
- #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InputIterator, size_type>::value
- && container_detail::is_input_iterator<InputIterator>::value
- >::type * = 0
- #endif
- )
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typename container_detail::disable_if_or
+ < iterator
+ , container_detail::is_convertible<InputIterator, size_type>
+ , container_detail::is_not_input_iterator<InputIterator>
+ >::type
+ #else
+ iterator
+ #endif
+ insert(const_iterator p, InputIterator first, InputIterator last)
{
STABLE_VECTOR_CHECK_INVARIANT;
const size_type pos_n = p - this->cbegin();
@@ -1536,12 +1536,12 @@ class stable_vector
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
- iterator insert(const_iterator p, FwdIt first, FwdIt last
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<FwdIt, size_type>::value
- && !container_detail::is_input_iterator<FwdIt>::value
- >::type * = 0
- )
+ typename container_detail::disable_if_or
+ < iterator
+ , container_detail::is_convertible<FwdIt, size_type>
+ , container_detail::is_input_iterator<FwdIt>
+ >::type
+ insert(const_iterator p, FwdIt first, FwdIt last)
{
const size_type num_new = static_cast<size_type>(boost::container::iterator_distance(first, last));
const size_type idx = static_cast<size_type>(p - this->cbegin());
@@ -1786,7 +1786,7 @@ class stable_vector
template <class U>
void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
{
- if(this->priv_capacity_bigger_than_size()){
+ if(BOOST_LIKELY(this->priv_capacity_bigger_than_size())){
//Enough memory in the pool and in the index
const node_ptr p = this->priv_get_from_pool();
BOOST_ASSERT(!!p);
@@ -1961,8 +1961,19 @@ class stable_vector
{
index_type & index_ref = const_cast<index_type&>(this->index);
- if(index.empty())
+ const size_type index_size = this->index.size();
+ if(!index_size)
return !this->capacity() && !this->size();
+
+ if(index_size < ExtraPointers)
+ return false;
+
+ const size_type bucket_extra_capacity = this->index.capacity()- index_size;
+ const size_type node_extra_capacity = this->internal_data.pool_size;
+ if(bucket_extra_capacity < node_extra_capacity){
+ return false;
+ }
+
if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
return false;
}
diff --git a/boost/container/string.hpp b/boost/container/string.hpp
index e5ec287cf8..7399223904 100644
--- a/boost/container/string.hpp
+++ b/boost/container/string.hpp
@@ -111,8 +111,7 @@ class basic_string_base
~basic_string_base()
{
if(!this->is_short()){
- this->deallocate_block();
- this->is_short(true);
+ this->deallocate(this->priv_long_addr(), this->priv_long_storage());
}
}
@@ -131,15 +130,14 @@ class basic_string_base
long_t(const long_t &other)
{
- this->is_short = other.is_short;
+ this->is_short = false;
length = other.length;
storage = other.storage;
start = other.start;
}
- long_t &operator =(const long_t &other)
+ long_t &operator= (const long_t &other)
{
- this->is_short = other.is_short;
length = other.length;
storage = other.storage;
start = other.start;
@@ -165,8 +163,7 @@ class basic_string_base
static const size_type MinInternalBufferChars = 8;
static const size_type AlignmentOfValueType =
alignment_of<value_type>::value;
- static const size_type ShortDataOffset =
- container_detail::ct_rounded_size<sizeof(short_header), AlignmentOfValueType>::value;
+ static const size_type ShortDataOffset = ((sizeof(short_header)-1)/AlignmentOfValueType+1)*AlignmentOfValueType;
static const size_type ZeroCostInternalBufferChars =
(sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
static const size_type UnalignedFinalInternalBufferChars =
@@ -421,21 +418,19 @@ class basic_string_base
}
else{
short_t short_backup(this->members_.m_repr.short_repr());
- long_t long_backup (other.members_.m_repr.long_repr());
+ this->members_.m_repr.short_repr().~short_t();
+ ::new(&this->members_.m_repr.long_repr()) long_t(other.members_.m_repr.long_repr());
other.members_.m_repr.long_repr().~long_t();
- ::new(&this->members_.m_repr.long_repr()) long_t;
- this->members_.m_repr.long_repr() = long_backup;
- other.members_.m_repr.short_repr() = short_backup;
+ ::new(&other.members_.m_repr.short_repr()) short_t(short_backup);
}
}
else{
if(other.is_short()){
short_t short_backup(other.members_.m_repr.short_repr());
- long_t long_backup (this->members_.m_repr.long_repr());
+ other.members_.m_repr.short_repr().~short_t();
+ ::new(&other.members_.m_repr.long_repr()) long_t(this->members_.m_repr.long_repr());
this->members_.m_repr.long_repr().~long_t();
- ::new(&other.members_.m_repr.long_repr()) long_t;
- other.members_.m_repr.long_repr() = long_backup;
- this->members_.m_repr.short_repr() = short_backup;
+ ::new(&this->members_.m_repr.short_repr()) short_t(short_backup);
}
else{
boost::adl_move_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
@@ -1289,9 +1284,7 @@ class basic_string
template <class InputIter>
basic_string& assign(InputIter first, InputIter last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InputIter, size_type>::value
- >::type * = 0
+ , typename container_detail::disable_if_convertible<InputIter, size_type>::type * = 0
#endif
)
{
@@ -1438,9 +1431,10 @@ class basic_string
template <class InputIter>
iterator insert(const_iterator p, InputIter first, InputIter last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InputIter, size_type>::value
- && container_detail::is_input_iterator<InputIter>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<InputIter, size_type>
+ , container_detail::is_not_input_iterator<InputIter>
>::type * = 0
#endif
)
@@ -1455,9 +1449,10 @@ class basic_string
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class ForwardIter>
iterator insert(const_iterator p, ForwardIter first, ForwardIter last
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<ForwardIter, size_type>::value
- && !container_detail::is_input_iterator<ForwardIter>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<ForwardIter, size_type>
+ , container_detail::is_input_iterator<ForwardIter>
>::type * = 0
)
{
@@ -1829,9 +1824,10 @@ class basic_string
template <class InputIter>
basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InputIter, size_type>::value
- && container_detail::is_input_iterator<InputIter>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<InputIter, size_type>
+ , container_detail::is_input_iterator<InputIter>
>::type * = 0
#endif
)
@@ -1850,9 +1846,10 @@ class basic_string
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class ForwardIter>
basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<ForwardIter, size_type>::value
- && !container_detail::is_input_iterator<ForwardIter>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<ForwardIter, size_type>
+ , container_detail::is_not_input_iterator<ForwardIter>
>::type * = 0
)
{
diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp
index 1b6d963934..1cf44c8e27 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -57,6 +57,7 @@
// other
#include <boost/core/no_exceptions_support.hpp>
#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
//std
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -179,6 +180,70 @@ class vec_iterator
{ return l.m_ptr >= r.m_ptr; }
};
+template<class BiDirPosConstIt, class BiDirValueIt>
+struct vector_insert_ordered_cursor
+{
+ typedef typename iterator_traits<BiDirPosConstIt>::value_type size_type;
+ typedef typename iterator_traits<BiDirValueIt>::reference reference;
+
+ vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
+ : last_position_it(posit), last_value_it(valueit)
+ {}
+
+ void operator --()
+ {
+ --last_value_it;
+ --last_position_it;
+ while(this->get_pos() == size_type(-1)){
+ --last_value_it;
+ --last_position_it;
+ }
+ }
+
+ size_type get_pos() const
+ { return *last_position_it; }
+
+ reference get_val()
+ { return *last_value_it; }
+
+ BiDirPosConstIt last_position_it;
+ BiDirValueIt last_value_it;
+};
+
+template<class T, class SizeType, class BiDirValueIt, class Comp>
+struct vector_merge_cursor
+{
+ typedef SizeType size_type;
+ typedef typename iterator_traits<BiDirValueIt>::reference reference;
+
+ vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp cmp)
+ : m_pbeg(pbeg), m_pcur(--plast), m_valueit(valueit), m_cmp(cmp)
+ {}
+
+ void operator --()
+ {
+ --m_valueit;
+ const T &t = *m_valueit;
+ while((m_pcur + 1) != m_pbeg){
+ if(!m_cmp(t, *m_pcur)){
+ break;
+ }
+ --m_pcur;
+ }
+ }
+
+ size_type get_pos() const
+ { return static_cast<size_type>((m_pcur + 1) - m_pbeg); }
+
+ reference get_val()
+ { return *m_valueit; }
+
+ T *const m_pbeg;
+ T *m_pcur;
+ BiDirValueIt m_valueit;
+ Comp m_cmp;
+};
+
} //namespace container_detail {
template<class Pointer, bool IsConst>
@@ -640,6 +705,13 @@ class vector
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ struct value_less
+ {
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
+ bool operator()(const value_type &a, const value_type &b) const
+ { return a < b; }
+ };
+
typedef typename container_detail::version<Allocator>::type alloc_version;
typedef boost::container::container_detail::vector_alloc_holder<Allocator> alloc_holder_t;
alloc_holder_t m_holder;
@@ -1043,10 +1115,11 @@ class vector
//!
//! <b>Note</b>: Non-standard extension to support static_vector
template<class OtherAllocator>
- typename container_detail::enable_if_c
- < container_detail::is_version<OtherAllocator, 0>::value &&
- !container_detail::is_same<OtherAllocator, allocator_type>::value
- , vector& >::type
+ typename container_detail::enable_if_and
+ < vector&
+ , container_detail::is_version<OtherAllocator, 0>
+ , container_detail::is_different<OtherAllocator, allocator_type>
+ >::type
operator=(BOOST_RV_REF_BEG vector<value_type, OtherAllocator> BOOST_RV_REF_END x)
{
this->priv_move_assign(boost::move(x));
@@ -1064,10 +1137,11 @@ class vector
//!
//! <b>Note</b>: Non-standard extension to support static_vector
template<class OtherAllocator>
- typename container_detail::enable_if_c
- < container_detail::is_version<OtherAllocator, 0>::value &&
- !container_detail::is_same<OtherAllocator, allocator_type>::value
- , vector& >::type
+ typename container_detail::enable_if_and
+ < vector&
+ , container_detail::is_version<OtherAllocator, 0>
+ , container_detail::is_different<OtherAllocator, allocator_type>
+ >::type
operator=(const vector<value_type, OtherAllocator> &x)
{
this->priv_copy_assign(x);
@@ -1084,11 +1158,15 @@ class vector
//! <b>Complexity</b>: Linear to n.
template <class InIt>
void assign(InIt first, InIt last
- BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
- < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value &&
- ( container_detail::is_input_iterator<InIt>::value ||
- container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value )
- >::type * = 0) )
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_or
+ < void
+ BOOST_MOVE_I container_detail::is_convertible<InIt BOOST_MOVE_I size_type>
+ BOOST_MOVE_I container_detail::and_
+ < container_detail::is_different<alloc_version BOOST_MOVE_I version_0>
+ BOOST_MOVE_I container_detail::is_not_input_iterator<InIt>
+ >
+ >::type * = 0)
+ )
{
//Overwrite all elements we can from [first, last)
iterator cur = this->begin();
@@ -1129,10 +1207,11 @@ class vector
//! <b>Complexity</b>: Linear to n.
template <class FwdIt>
void assign(FwdIt first, FwdIt last
- BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
- < !container_detail::is_convertible<FwdIt BOOST_MOVE_I size_type>::value &&
- ( !container_detail::is_input_iterator<FwdIt>::value &&
- !container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value )
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_or
+ < void
+ BOOST_MOVE_I container_detail::is_same<alloc_version BOOST_MOVE_I version_0>
+ BOOST_MOVE_I container_detail::is_convertible<FwdIt BOOST_MOVE_I size_type>
+ BOOST_MOVE_I container_detail::is_input_iterator<FwdIt>
>::type * = 0)
)
{
@@ -1791,10 +1870,13 @@ class vector
//! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
template <class InIt>
iterator insert(const_iterator pos, InIt first, InIt last
- BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
- < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
- && container_detail::is_input_iterator<InIt>::value
- >::type * = 0)
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<InIt, size_type>
+ , container_detail::is_not_input_iterator<InIt>
+ >::type * = 0
+ #endif
)
{
const size_type n_pos = pos - this->cbegin();
@@ -1809,9 +1891,10 @@ class vector
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert(const_iterator pos, FwdIt first, FwdIt last
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<FwdIt, size_type>::value
- && !container_detail::is_input_iterator<FwdIt>::value
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_convertible<FwdIt, size_type>
+ , container_detail::is_input_iterator<FwdIt>
>::type * = 0
)
{
@@ -1902,7 +1985,7 @@ class vector
T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first));
T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last));
T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
- this->priv_destroy_last_n(old_end_ptr - ptr, last_ptr == old_end_ptr);
+ this->priv_destroy_last_n(old_end_ptr - ptr);
}
return iterator(vector_iterator_get_ptr(first));
}
@@ -1931,9 +2014,11 @@ class vector
//! <b>Note</b>: Non-standard extension to support static_vector
template<class OtherAllocator>
void swap(vector<T, OtherAllocator> & x
- , typename container_detail::enable_if_c
- < container_detail::is_version<OtherAllocator, 0>::value &&
- !container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0
+ , typename container_detail::enable_if_and
+ < void
+ , container_detail::is_version<OtherAllocator, 0>
+ , container_detail::is_different<OtherAllocator, allocator_type>
+ >::type * = 0
)
{ this->m_holder.deep_swap(x.m_holder); }
@@ -2017,12 +2102,36 @@ class vector
template<class BiDirPosConstIt, class BiDirValueIt>
void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
{
+ typedef container_detail::vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
+ return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
+ }
+
+ template<class BidirIt>
+ void merge(BidirIt first, BidirIt last)
+ { this->merge(first, last, value_less()); }
+
+ template<class BidirIt, class Compare>
+ void merge(BidirIt first, BidirIt last, Compare comp)
+ { this->priv_merge(container_detail::false_type(), first, last, comp); }
+
+ template<class BidirIt>
+ void merge_unique(BidirIt first, BidirIt last)
+ { this->priv_merge(container_detail::true_type(), first, last, value_less()); }
+
+ template<class BidirIt, class Compare>
+ void merge_unique(BidirIt first, BidirIt last, Compare comp)
+ { this->priv_merge(container_detail::true_type(), first, last, comp); }
+
+ private:
+ template<class PositionValue>
+ void priv_insert_ordered_at(const size_type element_count, PositionValue position_value)
+ {
const size_type old_size_pos = this->size();
this->reserve(old_size_pos + element_count);
T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
size_type insertions_left = element_count;
- size_type next_pos = old_size_pos;
- size_type hole_size = element_count;
+ size_type prev_pos = old_size_pos;
+ size_type old_hole_size = element_count;
//Exception rollback. If any copy throws before the hole is filled, values
//already inserted/copied at the end of the buffer will be destroyed.
@@ -2031,52 +2140,197 @@ class vector
//Loop for each insertion backwards, first moving the elements after the insertion point,
//then inserting the element.
while(insertions_left){
- size_type pos = static_cast<size_type>(*(--last_position_it));
- while(pos == size_type(-1)){
- --last_value_it;
- pos = static_cast<size_type>(*(--last_position_it));
- }
-
- BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos);
+ --position_value;
+ size_type const pos = position_value.get_pos();
+ BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos && pos <= prev_pos);
//If needed shift the range after the insertion point and the previous insertion point.
//Function will take care if the shift crosses the size() boundary, using copy/move
//or uninitialized copy/move if necessary.
- size_type new_hole_size = (pos != next_pos)
- ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
- : hole_size
+ size_type new_hole_size = (pos != prev_pos)
+ ? priv_insert_ordered_at_shift_range(pos, prev_pos, this->size(), insertions_left)
+ : old_hole_size
;
- if(new_hole_size > 0){
+ if(new_hole_size){
//The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
- past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
+ past_hole_values_destroyer.increment_size_backwards(prev_pos - pos);
//Insert the new value in the hole
- allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
- --new_hole_size;
- if(new_hole_size == 0){
+ allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, position_value.get_val());
+ if(--new_hole_size){
+ //The hole was reduced by the new insertion by one
+ past_hole_values_destroyer.increment_size_backwards(size_type(1u));
+ }
+ else{
//Hole was just filled, disable exception rollback and change vector size
past_hole_values_destroyer.release();
this->m_holder.m_size += element_count;
}
- else{
- //The hole was reduced by the new insertion by one
- past_hole_values_destroyer.increment_size_backwards(size_type(1u));
- }
}
else{
- if(hole_size){
+ if(old_hole_size){
//Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
past_hole_values_destroyer.release();
this->m_holder.m_size += element_count;
}
//Insert the new value in the already constructed range
- begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
+ begin_ptr[pos + insertions_left - 1] = position_value.get_val();
}
--insertions_left;
- hole_size = new_hole_size;
- next_pos = pos;
+ old_hole_size = new_hole_size;
+ prev_pos = pos;
}
}
- private:
+ template<class UniqueBool, class BidirIt, class Compare>
+ void priv_merge(UniqueBool, BidirIt first, BidirIt last, Compare comp)
+ {
+ size_type const n = static_cast<size_type>(boost::container::iterator_distance(first, last));
+ if(BOOST_LIKELY(n)){
+ size_type const s = this->size();
+ if(BOOST_LIKELY(s)){
+ size_type const c = this->capacity();
+ size_type const free_c = (c - s);
+ //Use a new buffer if current one is too small for new elements,
+ //or there is no room for position indexes
+ bool new_buffer = false;
+ if(free_c < n){
+ new_buffer = true;
+ }
+ else if(!UniqueBool::value && free_c >= n){
+ typedef container_detail::vector_merge_cursor<T, size_type, BidirIt, Compare> inserter_t;
+ T* const pbeg = container_detail::to_raw_pointer(m_holder.start());
+ return this->priv_insert_ordered_at(n, inserter_t(pbeg, pbeg + s, last, comp));
+ }
+ else if(UniqueBool::value){ //Query for room to store n + 1 indexes (+1 to guarantee potential alignment overhead).
+ //No need to destroy them as they are integral types, which simplifies things a lot.
+ std::size_t const sz_vlt = sizeof(value_type);
+ std::size_t const sz_szt = sizeof(size_type);
+ new_buffer = (c-s-n)*sz_vlt/sz_szt < (n+1);
+ }
+
+ if(new_buffer){
+ size_type const new_size = s + n;
+ size_type new_cap = new_size;
+ pointer p = pointer();
+ p = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
+ this->priv_merge_in_new_buffer(UniqueBool(), first, n, comp, p, new_cap);
+ }
+ else{
+ //Use trailing memory to store position offsets
+ uintptr_t const szt_align_mask = container_detail::alignment_of<size_type>::value - 1;
+ boost::uintptr_t const addr = boost::uintptr_t(container_detail::to_raw_pointer(m_holder.start()) + s + n);
+ //Align memory before casting to address
+ size_type *const paddr = reinterpret_cast<size_type *>((addr + szt_align_mask) & ~szt_align_mask);
+ this->priv_insert_ordered_range(UniqueBool(), n, first, last, paddr, comp);
+ }
+ }
+ else{
+ this->insert(this->cend(), n, first, last);
+ }
+ }
+ }
+
+ template <class UniqueBool, class BidirIt, class Compare>
+ void priv_insert_ordered_range
+ (UniqueBool, size_type const n, BidirIt first, BidirIt const last, size_type positions[], Compare comp)
+ {
+ //Linear: at most N + M -1 comparisons
+ //Log: MlogN
+ //Average
+ //Linear: N + M - 2
+ //Log: MlogN
+ //N+M - 2
+ //N
+ //(N+M)/2 < MlogN
+ //(N/M+1)/2 <= logN
+ //bool const linear = !s || !n || (s <= n) || ((s+n)/n/2 < logN);
+ size_type const s = this->size();
+ size_type remaining = n;
+ T* const pbeg = container_detail::to_raw_pointer(m_holder.start());
+ T* const pend = pbeg + s;
+ T* pcur = pbeg;
+ size_type *position = positions;
+ size_type added_in_middle = 0;
+ if(first != last && pcur != pend){
+ while(1){
+ //maintain stability moving external values only if they are strictly less
+ if(comp(*first, *pcur)) {
+ *position = static_cast<size_type>(pcur - pbeg);
+ BOOST_ASSERT((position == positions) || (*(position-1) == size_type(-1)) || (*(position-1) <= *position));
+ ++position;
+ ++added_in_middle;
+ --remaining;
+ if(++first == last) break;
+ }
+ else if(UniqueBool::value && !comp(*pcur, *first)){
+ *position = size_type(-1);
+ ++position;
+ --remaining;
+ if(++first == last) break;
+ }
+ else{
+ if(++pcur == pend) break;
+ }
+ }
+ }
+ this->insert_ordered_at(added_in_middle, position, first);
+ this->insert(this->cend(), remaining, first, last);
+ }
+
+ template<class UniqueBool, class FwdIt, class Compare>
+ void priv_merge_in_new_buffer
+ (UniqueBool, FwdIt first, size_type n, Compare comp, pointer new_storage, size_type const new_cap)
+ {
+ BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n);
+ allocator_type &a = this->m_holder.alloc();
+ typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
+ typename value_traits::ArrayDestructor new_values_destroyer(new_storage, a, 0u);
+ T* pbeg = container_detail::to_raw_pointer(m_holder.start());
+ size_type const old_size = this->size();
+ T* const pend = pbeg + old_size;
+ T* d_first = container_detail::to_raw_pointer(new_storage);
+ size_type added = n;
+ //Merge in new buffer loop
+ while(1){
+ if(!n) {
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first);
+ break;
+ }
+ else if(pbeg == pend) {
+ ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first);
+ break;
+ }
+ //maintain stability moving external values only if they are strictly less
+ else if(comp(*first, *pbeg)) {
+ allocator_traits_type::construct( this->m_holder.alloc(), d_first, ::boost::move(*first) );
+ new_values_destroyer.increment_size(1u);
+ ++first;
+ --n;
+ ++d_first;
+ }
+ else if(UniqueBool::value && !comp(*pbeg, *first)){
+ ++first;
+ --n;
+ --added;
+ }
+ else{
+ allocator_traits_type::construct( this->m_holder.alloc(), d_first, ::boost::move(*pbeg) );
+ new_values_destroyer.increment_size(1u);
+ ++pbeg;
+ ++d_first;
+ }
+ }
+
+ //Nothrow operations
+ pointer const old_p = this->m_holder.start();
+ size_type const old_cap = this->m_holder.capacity();
+ boost::container::destroy_alloc_n(a, container_detail::to_raw_pointer(old_p), old_size);
+ a.deallocate(old_p, old_cap);
+ this->m_holder.m_size = old_size + added;
+ this->m_holder.start(new_storage);
+ this->m_holder.capacity(new_cap);
+ new_buffer_deallocator.release();
+ new_values_destroyer.release();
+ }
bool room_enough() const
{ return this->m_holder.m_size < this->m_holder.capacity(); }
@@ -2113,9 +2367,11 @@ class vector
template<class OtherAllocator>
void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
- , typename container_detail::enable_if_c
- < !container_detail::is_version<OtherAllocator, 0>::value &&
- container_detail::is_same<OtherAllocator, allocator_type>::value>::type * = 0)
+ , typename container_detail::disable_if_or
+ < void
+ , container_detail::is_version<OtherAllocator, 0>
+ , container_detail::is_different<OtherAllocator, allocator_type>
+ >::type * = 0)
{
//for move constructor, no aliasing (&x != this) is assummed.
BOOST_ASSERT(this != &x);
@@ -2167,10 +2423,12 @@ class vector
}
template<class OtherAllocator>
- void priv_copy_assign(const vector<T, OtherAllocator> &x
- , typename container_detail::enable_if_c
- < !container_detail::is_version<OtherAllocator, 0>::value &&
- container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0)
+ typename container_detail::disable_if_or
+ < void
+ , container_detail::is_version<OtherAllocator, 0>
+ , container_detail::is_different<OtherAllocator, allocator_type>
+ >::type
+ priv_copy_assign(const vector<T, OtherAllocator> &x)
{
allocator_type &this_alloc = this->m_holder.alloc();
const allocator_type &x_alloc = x.m_holder.alloc();
@@ -2274,16 +2532,7 @@ class vector
}
}
- void priv_destroy_last() BOOST_NOEXCEPT_OR_NOTHROW
- {
- if(!value_traits::trivial_dctr){
- value_type* const p = this->back_raw() - 1;
- allocator_traits_type::destroy(this->get_stored_allocator(), p);
- }
- --this->m_holder.m_size;
- }
-
- void priv_destroy_last(const bool moved) BOOST_NOEXCEPT_OR_NOTHROW
+ void priv_destroy_last(const bool moved = false) BOOST_NOEXCEPT_OR_NOTHROW
{
(void)moved;
if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
@@ -2303,17 +2552,6 @@ class vector
this->m_holder.m_size -= n;
}
- void priv_destroy_last_n(const size_type n, const bool moved) BOOST_NOEXCEPT_OR_NOTHROW
- {
- BOOST_ASSERT(n <= this->m_holder.m_size);
- (void)moved;
- if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
- T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n);
- boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
- }
- this->m_holder.m_size -= n;
- }
-
template<class InpIt>
void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
{
@@ -2554,69 +2792,6 @@ class vector
return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
}
- //Absolutely experimental. This function might change, disappear or simply crash!
- template<class BiDirPosConstIt, class BiDirSkipConstIt, class BiDirValueIt>
- void priv_insert_ordered_at( size_type element_count, BiDirPosConstIt last_position_it
- , bool do_skip, BiDirSkipConstIt last_skip_it, BiDirValueIt last_value_it)
- {
- const size_type old_size_pos = this->size();
- this->reserve(old_size_pos + element_count);
- T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
- size_type insertions_left = element_count;
- size_type next_pos = old_size_pos;
- size_type hole_size = element_count;
-
- //Exception rollback. If any copy throws before the hole is filled, values
- //already inserted/copied at the end of the buffer will be destroyed.
- typename value_traits::ArrayDestructor past_hole_values_destroyer
- (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
- //Loop for each insertion backwards, first moving the elements after the insertion point,
- //then inserting the element.
- while(insertions_left){
- if(do_skip){
- size_type n = *(--last_skip_it);
- boost::container::iterator_advance(last_value_it, -difference_type(n));
- }
- const size_type pos = static_cast<size_type>(*(--last_position_it));
- BOOST_ASSERT(pos <= old_size_pos);
- //If needed shift the range after the insertion point and the previous insertion point.
- //Function will take care if the shift crosses the size() boundary, using copy/move
- //or uninitialized copy/move if necessary.
- size_type new_hole_size = (pos != next_pos)
- ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
- : hole_size
- ;
- if(new_hole_size > 0){
- //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
- past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
- //Insert the new value in the hole
- allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
- --new_hole_size;
- if(new_hole_size == 0){
- //Hole was just filled, disable exception rollback and change vector size
- past_hole_values_destroyer.release();
- this->m_holder.m_size += element_count;
- }
- else{
- //The hole was reduced by the new insertion by one
- past_hole_values_destroyer.increment_size_backwards(size_type(1u));
- }
- }
- else{
- if(hole_size){
- //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
- past_hole_values_destroyer.release();
- this->m_holder.m_size += element_count;
- }
- //Insert the new value in the already constructed range
- begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
- }
- --insertions_left;
- hole_size = new_hole_size;
- next_pos = pos;
- }
- }
-
//Takes the range pointed by [first_pos, last_pos) and shifts it to the right
//by 'shift_count'. 'limit_pos' marks the end of constructed elements.
//
@@ -2647,7 +2822,7 @@ class vector
// |_>_>_>_>_>^
//
//
- //New situation in Case B (hole_size > 0):
+ //New situation in Case B (hole_size >= 0):
// range is moved through uninitialized moves
//
// first_pos last_pos limit_pos
@@ -2689,7 +2864,7 @@ class vector
//All uninitialized_moved
::boost::container::uninitialized_move_alloc
(this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
- hole_size = last_pos + shift_count - limit_pos;
+ hole_size = first_pos + shift_count - limit_pos;
}
//Case C:
else{
@@ -2716,7 +2891,7 @@ class vector
void priv_forward_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;
+ if(BOOST_UNLIKELY(!n)) return;
//There is enough memory
T* const old_finish = this->back_raw();
const size_type elems_after = old_finish - pos;