forked from boostorg/container
Fixes #156: ("Compile error with vector") and remove warnings about precission loss due to integer narrowing
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
[/
|
[/
|
||||||
/ Copyright (c) 2009-2018 Ion Gaztañaga
|
/ Copyright (c) 2009-2020 Ion Gazta<EFBFBD>aga
|
||||||
/
|
/
|
||||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
/ 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)
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -1342,11 +1342,13 @@ use [*Boost.Container]? There are several reasons for that:
|
|||||||
|
|
||||||
* New [classref boost::container::devector devector] container.
|
* New [classref boost::container::devector devector] container.
|
||||||
* Fixed bugs/issues:
|
* Fixed bugs/issues:
|
||||||
|
* [@https://github.com/boostorg/container/issues/156 GitHub #156: ['"Compile error with vector"]].
|
||||||
* [@https://github.com/boostorg/container/pull/157 GitHub #157: ['"Add missing include"]].
|
* [@https://github.com/boostorg/container/pull/157 GitHub #157: ['"Add missing include"]].
|
||||||
* [@https://github.com/boostorg/container/issues/159 GitHub #159: ['"pmr::monotonic_buffer_resource crashes on large single allocations"]].
|
* [@https://github.com/boostorg/container/issues/159 GitHub #159: ['"pmr::monotonic_buffer_resource crashes on large single allocations"]].
|
||||||
* [@https://github.com/boostorg/container/issues/160 GitHub #160: ['"Usage of uses_allocator needs a remove_cvref_t"]].
|
* [@https://github.com/boostorg/container/issues/160 GitHub #160: ['"Usage of uses_allocator needs a remove_cvref_t"]].
|
||||||
* [@https://github.com/boostorg/container/issues/161 GitHub #161: ['"polymorphic_allocator(memory_resource*) non-standard extension causes headache"]].
|
* [@https://github.com/boostorg/container/issues/161 GitHub #161: ['"polymorphic_allocator(memory_resource*) non-standard extension causes headache"]].
|
||||||
* [@https://github.com/boostorg/container/pull/163 GitHub #163: ['"container_rebind for small_vector with options"]].
|
* [@https://github.com/boostorg/container/pull/163 GitHub #163: ['"container_rebind for small_vector with options"]].
|
||||||
|
* [@https://github.com/boostorg/container/pull/167 GitHub #167: ['"error: the address of 'msg' will always evaluate as 'true' warning with GCC 4.4"]].
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
@@ -426,7 +426,6 @@ struct insert_emplace_proxy_arg##N\
|
|||||||
{\
|
{\
|
||||||
BOOST_ASSERT(n == 1); (void)n;\
|
BOOST_ASSERT(n == 1); (void)n;\
|
||||||
typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
|
typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
|
||||||
BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
|
|
||||||
value_type *vp = reinterpret_cast<value_type *>(v.data);\
|
value_type *vp = reinterpret_cast<value_type *>(v.data);\
|
||||||
alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||||
BOOST_TRY{\
|
BOOST_TRY{\
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include <boost/container/detail/mpl.hpp>
|
#include <boost/container/detail/mpl.hpp>
|
||||||
#include <boost/container/detail/type_traits.hpp>
|
#include <boost/container/detail/type_traits.hpp>
|
||||||
#include <boost/container/detail/construct_in_place.hpp>
|
#include <boost/container/detail/construct_in_place.hpp>
|
||||||
|
#include <boost/container/detail/destroyers.hpp>
|
||||||
|
|
||||||
// move
|
// move
|
||||||
#include <boost/move/adl_move_swap.hpp>
|
#include <boost/move/adl_move_swap.hpp>
|
||||||
@@ -180,7 +181,7 @@ BOOST_CONTAINER_FORCEINLINE F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
|
|||||||
if(BOOST_LIKELY(beg_raw != end_raw && dest_raw && beg_raw)){
|
if(BOOST_LIKELY(beg_raw != end_raw && dest_raw && beg_raw)){
|
||||||
const typename boost::container::iterator_traits<I>::difference_type n = end_raw - beg_raw;
|
const typename boost::container::iterator_traits<I>::difference_type n = end_raw - beg_raw;
|
||||||
std::memmove(dest_raw, beg_raw, sizeof(value_type)*n);
|
std::memmove(dest_raw, beg_raw, sizeof(value_type)*n);
|
||||||
boost::container::iterator_advance(r, n);
|
r += n;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -194,7 +195,7 @@ BOOST_CONTAINER_FORCEINLINE F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
|
|||||||
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
||||||
if(BOOST_LIKELY(n)){
|
if(BOOST_LIKELY(n)){
|
||||||
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
||||||
boost::container::iterator_advance(r, n);
|
r += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -209,7 +210,7 @@ BOOST_CONTAINER_FORCEINLINE I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_
|
|||||||
if(BOOST_LIKELY(n)){
|
if(BOOST_LIKELY(n)){
|
||||||
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
||||||
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
||||||
boost::container::iterator_advance(f, n);
|
f += n;
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@@ -223,8 +224,8 @@ BOOST_CONTAINER_FORCEINLINE I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCE
|
|||||||
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
||||||
if(BOOST_LIKELY(n)){
|
if(BOOST_LIKELY(n)){
|
||||||
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
||||||
boost::container::iterator_advance(f, n);
|
f += n;
|
||||||
boost::container::iterator_advance(r, n);
|
r += n;
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@@ -593,7 +594,7 @@ BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memzero_initializable<F, F>:
|
|||||||
typedef typename boost::container::iterator_traits<F>::value_type value_type;
|
typedef typename boost::container::iterator_traits<F>::value_type value_type;
|
||||||
if (BOOST_LIKELY(n)){
|
if (BOOST_LIKELY(n)){
|
||||||
std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
|
std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
|
||||||
boost::container::iterator_advance(r, n);
|
r += n;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1172,6 +1173,100 @@ void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_tr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Allocator, class Iterator>
|
||||||
|
struct array_destructor
|
||||||
|
{
|
||||||
|
typedef typename ::boost::container::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef typename dtl::if_c
|
||||||
|
<dtl::is_trivially_destructible<value_type>::value
|
||||||
|
,dtl::null_scoped_destructor_range<Allocator>
|
||||||
|
,dtl::scoped_destructor_range<Allocator>
|
||||||
|
>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template
|
||||||
|
<typename Allocator
|
||||||
|
,typename F // F models ForwardIterator
|
||||||
|
,typename O // G models OutputIterator
|
||||||
|
,typename InsertionProxy
|
||||||
|
>
|
||||||
|
void uninitialized_move_and_insert_alloc
|
||||||
|
( Allocator &a
|
||||||
|
, F first
|
||||||
|
, F pos
|
||||||
|
, F last
|
||||||
|
, O d_first
|
||||||
|
, typename allocator_traits<Allocator>::size_type n
|
||||||
|
, InsertionProxy insert_range_proxy)
|
||||||
|
{
|
||||||
|
typedef typename array_destructor<Allocator, F>::type array_destructor_t;
|
||||||
|
|
||||||
|
//Anti-exception rollbacks
|
||||||
|
array_destructor_t new_values_destroyer(d_first, d_first, a);
|
||||||
|
|
||||||
|
//Initialize with [begin(), pos) old buffer
|
||||||
|
//the start of the new buffer
|
||||||
|
O d_last = ::boost::container::uninitialized_move_alloc(a, first, pos, d_first);
|
||||||
|
new_values_destroyer.set_end(d_last);
|
||||||
|
//Initialize new objects, starting from previous point
|
||||||
|
insert_range_proxy.uninitialized_copy_n_and_update(a, d_last, n);
|
||||||
|
d_last += n;
|
||||||
|
new_values_destroyer.set_end(d_last);
|
||||||
|
//Initialize from the rest of the old buffer,
|
||||||
|
//starting from previous point
|
||||||
|
(void) ::boost::container::uninitialized_move_alloc(a, pos, last, d_last);
|
||||||
|
//All construction successful, disable rollbacks
|
||||||
|
new_values_destroyer.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
<typename Allocator
|
||||||
|
,typename F // F models ForwardIterator
|
||||||
|
,typename InsertionProxy
|
||||||
|
>
|
||||||
|
void expand_forward_and_insert_alloc
|
||||||
|
( Allocator &a
|
||||||
|
, F pos
|
||||||
|
, F last
|
||||||
|
, typename allocator_traits<Allocator>::size_type n
|
||||||
|
, InsertionProxy insert_range_proxy)
|
||||||
|
{
|
||||||
|
typedef typename array_destructor<Allocator, F>::type array_destructor_t;
|
||||||
|
|
||||||
|
if (BOOST_UNLIKELY(!n)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (last == pos){
|
||||||
|
insert_range_proxy.uninitialized_copy_n_and_update(a, last, n);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
typedef typename allocator_traits<Allocator>::size_type alloc_size_type;
|
||||||
|
const alloc_size_type elems_after = static_cast<alloc_size_type>(last - pos);
|
||||||
|
if(elems_after >= n){
|
||||||
|
//New elements can be just copied.
|
||||||
|
//Move to uninitialized memory last objects
|
||||||
|
::boost::container::uninitialized_move_alloc_n(a, last - n, n, last);
|
||||||
|
array_destructor_t on_exception(last, last, a);
|
||||||
|
//Copy previous to last objects to the initialized end
|
||||||
|
boost::container::move_backward(pos, last - n, last);
|
||||||
|
//Insert new objects in the pos
|
||||||
|
insert_range_proxy.copy_n_and_update(a, pos, n);
|
||||||
|
on_exception.release();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//The new elements don't fit in the [pos, end()) range.
|
||||||
|
//Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
|
||||||
|
F new_last = ::boost::container::uninitialized_move_alloc(a, pos, last, pos + n);
|
||||||
|
array_destructor_t on_exception(pos + n, new_last, a);
|
||||||
|
//Copy first new elements in pos (gap is still there)
|
||||||
|
insert_range_proxy.copy_n_and_update(a, 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(a, last, n - elems_after);
|
||||||
|
on_exception.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} //namespace container {
|
} //namespace container {
|
||||||
} //namespace boost {
|
} //namespace boost {
|
||||||
|
|
||||||
|
@@ -242,6 +242,72 @@ struct null_scoped_destructor_n
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//!A deleter for scoped_ptr that destroys
|
||||||
|
//!an object using a STL allocator.
|
||||||
|
template <class Allocator>
|
||||||
|
struct scoped_destructor_range
|
||||||
|
{
|
||||||
|
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||||
|
typedef typename AllocTraits::pointer pointer;
|
||||||
|
typedef typename AllocTraits::value_type value_type;
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE scoped_destructor_range(pointer p, pointer e, Allocator& a)
|
||||||
|
: m_p(p), m_e(e), m_a(a)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void release()
|
||||||
|
{ m_p = pointer(); m_e = pointer(); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void set_end(pointer e)
|
||||||
|
{ m_e = e; }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void set_begin(pointer b)
|
||||||
|
{ m_p = b; }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void set_range(pointer b, pointer e)
|
||||||
|
{ m_p = b; m_e = e; }
|
||||||
|
|
||||||
|
~scoped_destructor_range()
|
||||||
|
{
|
||||||
|
while(m_p != m_e){
|
||||||
|
value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
|
||||||
|
AllocTraits::destroy(m_a, raw_ptr);
|
||||||
|
++m_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
pointer m_p;
|
||||||
|
pointer m_e;
|
||||||
|
Allocator & m_a;
|
||||||
|
};
|
||||||
|
|
||||||
|
//!A deleter for scoped_ptr that destroys
|
||||||
|
//!an object using a STL allocator.
|
||||||
|
template <class Allocator>
|
||||||
|
struct null_scoped_destructor_range
|
||||||
|
{
|
||||||
|
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||||
|
typedef typename AllocTraits::pointer pointer;
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_range(pointer, pointer, Allocator&)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void release()
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void set_end(pointer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void set_begin(pointer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void set_range(pointer, pointer)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
class scoped_destructor
|
class scoped_destructor
|
||||||
{
|
{
|
||||||
|
@@ -56,7 +56,12 @@ struct grow_factor_ratio
|
|||||||
else{
|
else{
|
||||||
new_cap *= Numerator;
|
new_cap *= Numerator;
|
||||||
}
|
}
|
||||||
return max_value(SizeType(Minimum), max_value(cur_cap+add_min_cap, min_value(max_cap, new_cap)));
|
return max_value<SizeType>
|
||||||
|
( SizeType(Minimum)
|
||||||
|
, max_value<SizeType>
|
||||||
|
( SizeType(cur_cap+add_min_cap)
|
||||||
|
, min_value<SizeType>(max_cap, new_cap))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -247,10 +247,6 @@ struct vector_value_traits_base
|
|||||||
{
|
{
|
||||||
static const bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
|
static const bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
|
||||||
static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
|
static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
|
||||||
static const bool trivial_copy = dtl::is_trivially_copy_constructible<T>::value;
|
|
||||||
static const bool nothrow_copy = dtl::is_nothrow_copy_constructible<T>::value || trivial_copy;
|
|
||||||
static const bool trivial_assign = dtl::is_trivially_copy_assignable<T>::value;
|
|
||||||
static const bool nothrow_assign = dtl::is_nothrow_copy_assignable<T>::value || trivial_assign;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Allocator>
|
template <class Allocator>
|
||||||
@@ -317,34 +313,41 @@ struct vector_alloc_holder
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
//Constructor, does not throw
|
//Constructor, does not throw
|
||||||
template<class AllocConvertible>
|
template<class AllocConvertible, class SizeType>
|
||||||
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
|
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, SizeType initial_size)
|
||||||
: allocator_type(boost::forward<AllocConvertible>(a))
|
: allocator_type(boost::forward<AllocConvertible>(a))
|
||||||
, m_start()
|
, m_start()
|
||||||
//Size is initialized here so vector should only call uninitialized_xxx after this
|
//Size is initialized here so vector should only call uninitialized_xxx after this
|
||||||
, m_size(static_cast<stored_size_type>(initial_size))
|
, m_size(static_cast<stored_size_type>(initial_size))
|
||||||
, m_capacity()
|
, m_capacity()
|
||||||
{
|
{
|
||||||
if(initial_size){
|
if (initial_size > size_type(-1)){
|
||||||
|
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
|
||||||
|
}
|
||||||
|
else if(initial_size){
|
||||||
pointer reuse = pointer();
|
pointer reuse = pointer();
|
||||||
size_type final_cap = initial_size;
|
size_type final_cap = static_cast<size_type>(initial_size);
|
||||||
m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
|
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
|
||||||
this->set_stored_capacity(final_cap);
|
this->set_stored_capacity(final_cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Constructor, does not throw
|
//Constructor, does not throw
|
||||||
vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
|
template<class SizeType>
|
||||||
|
vector_alloc_holder(vector_uninitialized_size_t, SizeType initial_size)
|
||||||
: allocator_type()
|
: allocator_type()
|
||||||
, m_start()
|
, m_start()
|
||||||
//Size is initialized here so vector should only call uninitialized_xxx after this
|
//Size is initialized here so vector should only call uninitialized_xxx after this
|
||||||
, m_size(static_cast<stored_size_type>(initial_size))
|
, m_size(static_cast<stored_size_type>(initial_size))
|
||||||
, m_capacity()
|
, m_capacity()
|
||||||
{
|
{
|
||||||
if(initial_size){
|
if (initial_size > size_type(-1)){
|
||||||
|
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
|
||||||
|
}
|
||||||
|
else if(initial_size){
|
||||||
pointer reuse = pointer();
|
pointer reuse = pointer();
|
||||||
size_type final_cap = initial_size;
|
size_type final_cap = initial_size;
|
||||||
m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
|
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
|
||||||
this->set_stored_capacity(final_cap);
|
this->set_stored_capacity(final_cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1014,7 +1017,7 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
::boost::container::uninitialized_copy_alloc_n_source
|
::boost::container::uninitialized_copy_alloc_n_source
|
||||||
( this->m_holder.alloc(), il.begin()
|
( this->m_holder.alloc(), il.begin()
|
||||||
, il.size(), this->priv_raw_begin());
|
, static_cast<size_type>(il.size()), this->priv_raw_begin());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1262,7 +1265,12 @@ private:
|
|||||||
{
|
{
|
||||||
//For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
|
//For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
|
||||||
//so we can't do any backwards allocation
|
//so we can't do any backwards allocation
|
||||||
const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last));
|
const typename iterator_traits<FwdIt>::size_type sz = boost::container::iterator_distance(first, last);
|
||||||
|
if (sz > size_type(-1)){
|
||||||
|
boost::container::throw_length_error("vector::assign, FwdIt's max length reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_type input_sz = static_cast<size_type>(sz);
|
||||||
const size_type old_capacity = this->capacity();
|
const size_type old_capacity = this->capacity();
|
||||||
if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
|
if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
|
||||||
size_type real_cap = 0;
|
size_type real_cap = 0;
|
||||||
@@ -1968,8 +1976,13 @@ private:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(pos));
|
BOOST_ASSERT(this->priv_in_range_or_end(pos));
|
||||||
|
const typename iterator_traits<FwdIt>::size_type sz = boost::container::iterator_distance(first, last);
|
||||||
|
if (sz > size_type(-1)){
|
||||||
|
boost::container::throw_length_error("vector::insert, FwdIt's max length reached");
|
||||||
|
}
|
||||||
|
|
||||||
dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
|
dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
|
||||||
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
|
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), static_cast<size_type>(sz), proxy);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2009,7 +2022,7 @@ private:
|
|||||||
//! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
|
//! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
//! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
||||||
iterator insert(const_iterator position, std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator position, std::initializer_list<value_type> il)
|
||||||
{
|
{
|
||||||
//Assertion done in insert()
|
//Assertion done in insert()
|
||||||
return this->insert(position, il.begin(), il.end());
|
return this->insert(position, il.begin(), il.end());
|
||||||
@@ -2021,11 +2034,12 @@ private:
|
|||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant time.
|
//! <b>Complexity</b>: Constant time.
|
||||||
void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
|
BOOST_CONTAINER_FORCEINLINE void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!this->empty());
|
BOOST_ASSERT(!this->empty());
|
||||||
//Destroy last element
|
//Destroy last element
|
||||||
this->priv_destroy_last();
|
allocator_traits_type::destroy(this->get_stored_allocator(), this->priv_raw_end() - 1);
|
||||||
|
--this->m_holder.m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Erases the element at position pos.
|
//! <b>Effects</b>: Erases the element at position pos.
|
||||||
@@ -2039,10 +2053,16 @@ private:
|
|||||||
BOOST_ASSERT(this->priv_in_range(position));
|
BOOST_ASSERT(this->priv_in_range(position));
|
||||||
const pointer p = vector_iterator_get_ptr(position);
|
const pointer p = vector_iterator_get_ptr(position);
|
||||||
T *const pos_ptr = boost::movelib::to_raw_pointer(p);
|
T *const pos_ptr = boost::movelib::to_raw_pointer(p);
|
||||||
T *const beg_ptr = this->priv_raw_begin();
|
T *const end_ptr = this->priv_raw_end();
|
||||||
T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
|
|
||||||
//Move elements forward and destroy last
|
//Move elements forward and destroy last
|
||||||
this->priv_destroy_last(pos_ptr != new_end_ptr);
|
(void)::boost::container::move(pos_ptr + 1, end_ptr, pos_ptr);
|
||||||
|
|
||||||
|
T *const last_ptr = end_ptr-1;
|
||||||
|
if(!value_traits::trivial_dctr_after_move || pos_ptr == last_ptr){
|
||||||
|
allocator_traits_type::destroy(this->get_stored_allocator(), last_ptr);
|
||||||
|
}
|
||||||
|
--this->m_holder.m_size;
|
||||||
return iterator(p);
|
return iterator(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2054,15 +2074,19 @@ private:
|
|||||||
//! plus linear to the elements between pos and the last element.
|
//! 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)
|
||||||
{
|
{
|
||||||
if (first != last){
|
BOOST_ASSERT(this->priv_in_range_or_end(first));
|
||||||
BOOST_ASSERT(this->priv_in_range(first));
|
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(last));
|
BOOST_ASSERT(this->priv_in_range_or_end(last));
|
||||||
BOOST_ASSERT(first < last);
|
BOOST_ASSERT(first <= last);
|
||||||
|
if(first != last){
|
||||||
T* const old_end_ptr = this->priv_raw_end();
|
T* const old_end_ptr = this->priv_raw_end();
|
||||||
T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
|
T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
|
||||||
T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
|
T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
|
||||||
T* const ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
|
T* const new_last_ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
|
||||||
this->priv_destroy_last_n(old_end_ptr - ptr);
|
const size_type n = static_cast<size_type>(old_end_ptr - new_last_ptr);
|
||||||
|
if(!value_traits::trivial_dctr_after_move || old_end_ptr == last_ptr){
|
||||||
|
boost::container::destroy_alloc_n(this->get_stored_allocator(), new_last_ptr, n);
|
||||||
|
}
|
||||||
|
this->m_holder.dec_stored_size(n);
|
||||||
}
|
}
|
||||||
return iterator(vector_iterator_get_ptr(first));
|
return iterator(vector_iterator_get_ptr(first));
|
||||||
}
|
}
|
||||||
@@ -2575,24 +2599,10 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_destroy_last(const bool moved = false) BOOST_NOEXCEPT_OR_NOTHROW
|
|
||||||
{
|
|
||||||
(void)moved;
|
|
||||||
const bool skip_destructor = value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved);
|
|
||||||
if(!skip_destructor){
|
|
||||||
value_type* const p = this->priv_raw_end() - 1;
|
|
||||||
allocator_traits_type::destroy(this->get_stored_allocator(), p);
|
|
||||||
}
|
|
||||||
--this->m_holder.m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(n <= this->m_holder.m_size);
|
BOOST_ASSERT(n <= this->m_holder.m_size);
|
||||||
if(!value_traits::trivial_dctr){
|
boost::container::destroy_alloc_n(this->get_stored_allocator(), this->priv_raw_end() - n, n);
|
||||||
T* const destroy_pos = this->priv_raw_begin() + (this->m_holder.m_size-n);
|
|
||||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
|
|
||||||
}
|
|
||||||
this->m_holder.dec_stored_size(n);
|
this->m_holder.dec_stored_size(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2601,7 +2611,7 @@ private:
|
|||||||
{
|
{
|
||||||
T* const old_end_pos = this->priv_raw_end();
|
T* const old_end_pos = this->priv_raw_end();
|
||||||
T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
|
T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
|
||||||
this->m_holder.inc_stored_size(new_end_pos - old_end_pos);
|
this->m_holder.inc_stored_size(static_cast<size_type>(new_end_pos - old_end_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
|
void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
@@ -2623,6 +2633,13 @@ private:
|
|||||||
this->emplace_back(::boost::forward<U>(u));
|
this->emplace_back(::boost::forward<U>(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Overload to support compiler errors that instantiate too much
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void priv_push_back(::boost::move_detail::nat)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator, ::boost::move_detail::nat)
|
||||||
|
{ return iterator(); }
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<allocator_type, T*> priv_resize_proxy(const T &x)
|
BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<allocator_type, T*> priv_resize_proxy(const T &x)
|
||||||
{ return dtl::insert_n_copies_proxy<allocator_type, T*>(x); }
|
{ return dtl::insert_n_copies_proxy<allocator_type, T*>(x); }
|
||||||
|
|
||||||
@@ -2689,7 +2706,7 @@ private:
|
|||||||
(T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
(T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
||||||
{
|
{
|
||||||
//Check if we have enough memory or try to expand current memory
|
//Check if we have enough memory or try to expand current memory
|
||||||
const size_type n_pos = raw_pos - this->priv_raw_begin();
|
const size_type n_pos = static_cast<size_type>(raw_pos - this->priv_raw_begin());
|
||||||
|
|
||||||
const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
|
const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
|
||||||
//Pass the hint so that allocators can take advantage of this.
|
//Pass the hint so that allocators can take advantage of this.
|
||||||
@@ -2898,16 +2915,17 @@ private:
|
|||||||
BOOST_ASSERT(this->room_enough());
|
BOOST_ASSERT(this->room_enough());
|
||||||
//There is enough memory
|
//There is enough memory
|
||||||
T* const old_finish = this->priv_raw_end();
|
T* const old_finish = this->priv_raw_end();
|
||||||
|
allocator_type & a = this->m_holder.alloc();
|
||||||
|
|
||||||
if (old_finish == raw_pos){
|
if (old_finish == raw_pos){
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, 1);
|
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, 1);
|
||||||
++this->m_holder.m_size;
|
++this->m_holder.m_size;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//New elements can be just copied.
|
//New elements can be just copied.
|
||||||
//Move to uninitialized memory last objects
|
//Move to uninitialized memory last objects
|
||||||
T * const before_old_finish = old_finish-1;
|
T * const before_old_finish = old_finish-1;
|
||||||
allocator_type & a = this->m_holder.alloc();
|
|
||||||
allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
|
allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
|
||||||
++this->m_holder.m_size;
|
++this->m_holder.m_size;
|
||||||
//Copy previous to last objects to the initialized end
|
//Copy previous to last objects to the initialized end
|
||||||
@@ -2918,91 +2936,37 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
void priv_insert_forward_range_expand_forward(T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
|
BOOST_CONTAINER_FORCEINLINE void priv_insert_forward_range_expand_forward(T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
|
||||||
{
|
{
|
||||||
//In case n is 0 there is nothing to do
|
|
||||||
if(BOOST_UNLIKELY(!n))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//There is enough memory
|
//There is enough memory
|
||||||
T* const raw_old_finish = this->priv_raw_end();
|
boost::container::expand_forward_and_insert_alloc
|
||||||
|
( this->m_holder.alloc(), raw_pos, this->priv_raw_end(), n, insert_range_proxy);
|
||||||
if (raw_old_finish == raw_pos){
|
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), raw_old_finish, n);
|
|
||||||
this->m_holder.inc_stored_size(n);
|
this->m_holder.inc_stored_size(n);
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
const size_type elems_after = raw_old_finish - raw_pos;
|
|
||||||
allocator_type & a = this->m_holder.alloc();
|
|
||||||
if(elems_after >= n){
|
|
||||||
//New elements can be just copied.
|
|
||||||
//Move to uninitialized memory last objects
|
|
||||||
::boost::container::uninitialized_move_alloc_n(a, raw_old_finish - n, n, raw_old_finish);
|
|
||||||
this->m_holder.inc_stored_size(n);
|
|
||||||
//Copy previous to last objects to the initialized end
|
|
||||||
boost::container::move_backward(raw_pos, raw_old_finish - n, raw_old_finish);
|
|
||||||
//Insert new objects in the raw_pos
|
|
||||||
insert_range_proxy.copy_n_and_update(a, raw_pos, n);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//The new elements don't fit in the [raw_pos, end()) range.
|
|
||||||
//Copy old [raw_pos, end()) elements to the uninitialized memory (a gap is created)
|
|
||||||
::boost::container::uninitialized_move_alloc(a, raw_pos, raw_old_finish, raw_pos + n);
|
|
||||||
typename value_traits::ArrayDestructor on_exception(raw_pos + n, a, elems_after);
|
|
||||||
//Copy first new elements in raw_pos (gap is still there)
|
|
||||||
insert_range_proxy.copy_n_and_update(a, raw_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(a, raw_old_finish, n - elems_after);
|
|
||||||
this->m_holder.inc_stored_size(n);
|
|
||||||
on_exception.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
void priv_insert_forward_range_new_allocation
|
void priv_insert_forward_range_new_allocation
|
||||||
(T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
(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!
|
//n can be zero, if we want to reallocate!
|
||||||
T *new_finish = new_start;
|
|
||||||
T *old_finish;
|
|
||||||
|
|
||||||
allocator_type &a = this->m_holder.alloc();
|
allocator_type &a = this->m_holder.alloc();
|
||||||
|
T * const raw_old_buffer = this->priv_raw_begin();
|
||||||
|
|
||||||
//Anti-exception rollbacks
|
|
||||||
typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
|
typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
|
||||||
typename value_traits::ArrayDestructor new_values_destroyer(new_start, a, 0u);
|
boost::container::uninitialized_move_and_insert_alloc
|
||||||
|
(a, raw_old_buffer, pos, this->priv_raw_end(), new_start, n, insert_range_proxy);
|
||||||
|
new_buffer_deallocator.release();
|
||||||
|
|
||||||
//Initialize with [begin(), pos) old buffer
|
|
||||||
//the start of the new buffer
|
|
||||||
T * const old_buffer = this->priv_raw_begin();
|
|
||||||
if(old_buffer){
|
|
||||||
new_finish = ::boost::container::uninitialized_move_alloc
|
|
||||||
(a, this->priv_raw_begin(), pos, old_finish = new_finish);
|
|
||||||
new_values_destroyer.increment_size(new_finish - old_finish);
|
|
||||||
}
|
|
||||||
//Initialize new objects, starting from previous point
|
|
||||||
old_finish = new_finish;
|
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n);
|
|
||||||
new_finish += n;
|
|
||||||
new_values_destroyer.increment_size(new_finish - old_finish);
|
|
||||||
//Initialize from the rest of the old buffer,
|
|
||||||
//starting from previous point
|
|
||||||
if(old_buffer){
|
|
||||||
new_finish = ::boost::container::uninitialized_move_alloc
|
|
||||||
(a, pos, old_buffer + this->m_holder.m_size, new_finish);
|
|
||||||
//Destroy and deallocate old elements
|
//Destroy and deallocate old elements
|
||||||
//If there is allocated memory, destroy and deallocate
|
if(raw_old_buffer){
|
||||||
if(!value_traits::trivial_dctr_after_move)
|
BOOST_IF_CONSTEXPR(!has_trivial_destructor_after_move<value_type>::value)
|
||||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
|
boost::container::destroy_alloc_n(a, raw_old_buffer, this->m_holder.m_size);
|
||||||
this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
|
this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_holder.start(new_start);
|
this->m_holder.start(new_start);
|
||||||
m_holder.set_stored_size(new_finish - new_start);
|
this->m_holder.inc_stored_size(n);
|
||||||
this->m_holder.capacity(new_cap);
|
this->m_holder.capacity(new_cap);
|
||||||
//All construction successful, disable rollbacks
|
|
||||||
new_values_destroyer.release();
|
|
||||||
new_buffer_deallocator.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
@@ -3314,7 +3278,7 @@ private:
|
|||||||
//Copy to the old_end part to the uninitialized zone leaving a gap.
|
//Copy to the old_end part to the uninitialized zone leaving a gap.
|
||||||
::boost::container::uninitialized_move_alloc(a, pos, old_finish, old_finish + mid_last_dist);
|
::boost::container::uninitialized_move_alloc(a, pos, old_finish, old_finish + mid_last_dist);
|
||||||
|
|
||||||
array_destructor_t old_end_destroyer(old_finish + mid_last_dist, a, old_finish - pos);
|
array_destructor_t old_end_destroyer(old_finish + mid_last_dist, a, static_cast<size_type>(old_finish - pos));
|
||||||
|
|
||||||
//Copy the first part to the already constructed old_end zone
|
//Copy the first part to the already constructed old_end zone
|
||||||
insert_range_proxy.copy_n_and_update(a, pos, elemsafter);
|
insert_range_proxy.copy_n_and_update(a, pos, elemsafter);
|
||||||
|
@@ -23,6 +23,29 @@ volatile ::boost::container::vector<empty> dummy;
|
|||||||
#include "movable_int.hpp"
|
#include "movable_int.hpp"
|
||||||
#include "dummy_test_allocator.hpp"
|
#include "dummy_test_allocator.hpp"
|
||||||
|
|
||||||
|
class CustomAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef const value_type* const_pointer;
|
||||||
|
typedef unsigned short size_type;
|
||||||
|
typedef short difference_type;
|
||||||
|
|
||||||
|
pointer allocate(size_type count)
|
||||||
|
{ return (pointer)new char[sizeof(value_type)*count]; }
|
||||||
|
|
||||||
|
void deallocate(pointer ptr, size_type )
|
||||||
|
{ delete [](char*)ptr; }
|
||||||
|
|
||||||
|
friend bool operator==(CustomAllocator const&, CustomAllocator const&) BOOST_NOEXCEPT
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
friend bool operator!=(CustomAllocator const& x, CustomAllocator const& y) BOOST_NOEXCEPT
|
||||||
|
{ return !(x == y); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace container {
|
namespace container {
|
||||||
|
|
||||||
@@ -44,6 +67,9 @@ template class boost::container::vector< test::movable_and_copyable_int
|
|||||||
, vector_options< stored_size<unsigned short> >::type
|
, vector_options< stored_size<unsigned short> >::type
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
//test custom allocator with small size_type
|
||||||
|
template class boost::container::vector<int, CustomAllocator>;
|
||||||
|
|
||||||
} //namespace boost {
|
} //namespace boost {
|
||||||
} //namespace container {
|
} //namespace container {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user