Fixes #233 ("Can't std::move small_vector with move-only type")

This commit is contained in:
Ion Gaztañaga
2023-03-13 10:06:53 +01:00
parent db96d2ad47
commit 5cc9617487
6 changed files with 410 additions and 111 deletions
+35 -16
View File
@@ -345,7 +345,7 @@ class small_vector_base
public:
//Make it public as it will be inherited by small_vector and container
//must have this public member
typedef typename real_allocator<T, SecAlloc>::type secondary_allocator_t;
typedef typename real_allocator<T, SecAlloc>::type secondary_allocator_t;
typedef typename allocator_traits<secondary_allocator_t>::
template portable_rebind_alloc<void>::type void_allocator_t;
typedef typename dtl::get_small_vector_opt<Options>::type options_t;
@@ -387,6 +387,24 @@ class small_vector_base
: base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a))
{}
BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(maybe_initial_capacity_t, std::size_t initial_capacity, std::size_t initial_size)
: base_type( maybe_initial_capacity_t()
, (initial_capacity >= initial_size) ? this->internal_storage() : pointer()
, (initial_capacity >= initial_size) ? initial_capacity : initial_size
)
{}
template<class AllocFwd>
BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(maybe_initial_capacity_t, std::size_t initial_capacity, std::size_t initial_size, BOOST_FWD_REF(AllocFwd) a)
: base_type(maybe_initial_capacity_t()
, (initial_capacity >= initial_size) ? this->internal_storage() : pointer()
, (initial_capacity >= initial_size) ? initial_capacity : initial_size
, ::boost::forward<AllocFwd>(a)
)
{}
using base_type::protected_set_size;
//~small_vector_base(){}
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -408,9 +426,10 @@ class small_vector_base
this->steal_resources(x);
}
else{
this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
, boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end ()))
);
const typename base_type::size_type sz = x.size();
::boost::container::uninitialized_move_alloc_n_source
(this->base_type::get_stored_allocator(), x.begin(), sz, this->begin());
this->protected_set_size(sz);
x.clear();
}
}
@@ -546,28 +565,28 @@ class small_vector
{}
BOOST_CONTAINER_FORCEINLINE explicit small_vector(size_type n)
: base_type(initial_capacity_t(), internal_capacity())
{ this->resize(n); }
: base_type(maybe_initial_capacity_t(), internal_capacity(), n)
{ this->protected_init_n(n, value_init); }
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
{ this->resize(n); }
: base_type(maybe_initial_capacity_t(), internal_capacity(), n, a)
{ this->protected_init_n(n, value_init); }
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t)
: base_type(initial_capacity_t(), internal_capacity())
{ this->resize(n, default_init_t()); }
: base_type(maybe_initial_capacity_t(), internal_capacity(), n)
{ this->protected_init_n(n, default_init_t()); }
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
{ this->resize(n, default_init_t()); }
: base_type(maybe_initial_capacity_t(), internal_capacity(), n, a)
{ this->protected_init_n(n, default_init_t()); }
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v)
: base_type(initial_capacity_t(), internal_capacity())
{ this->resize(n, v); }
: base_type(maybe_initial_capacity_t(), internal_capacity(), n)
{ this->protected_init_n(n, v); }
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
{ this->resize(n, v); }
: base_type(maybe_initial_capacity_t(), internal_capacity(), n, a)
{ this->protected_init_n(n, v); }
template <class InIt>
BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last
+101 -36
View File
@@ -257,8 +257,6 @@ struct vector_insert_ordered_cursor
BiDirValueIt last_value_it;
};
struct initial_capacity_t{};
template<class Pointer, bool IsConst>
BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
{ return it.get_ptr(); }
@@ -267,9 +265,13 @@ template<class Pointer, bool IsConst>
BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
{ return it.get_ptr(); }
struct initial_capacity_t {};
struct vector_uninitialized_size_t {};
static const vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t();
struct maybe_initial_capacity_t {};
template <class T>
struct vector_value_traits_base
{
@@ -312,6 +314,43 @@ struct vector_alloc_holder
typedef typename allocator_traits_type::size_type size_type;
typedef typename allocator_traits_type::value_type value_type;
private:
template<class SizeType>
void do_initial_capacity(SizeType initial_capacity)
{
if (BOOST_UNLIKELY(initial_capacity > size_type(-1))) {
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
}
else if (initial_capacity) {
pointer reuse = pointer();
size_type final_cap = static_cast<size_type>(initial_capacity);
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
this->set_stored_capacity(final_cap);
}
}
template<class SizeType>
void do_maybe_initial_capacity(pointer p, SizeType initial_capacity)
{
if (BOOST_UNLIKELY(initial_capacity > size_type(-1))) {
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
}
else if (p) {
m_start = p;
}
else {
BOOST_ASSERT(initial_capacity > 0);
pointer reuse = pointer();
size_type final_cap = static_cast<size_type>(initial_capacity);
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
this->set_stored_capacity(final_cap);
}
}
public:
BOOST_CONTAINER_FORCEINLINE
static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
{
@@ -343,7 +382,7 @@ struct vector_alloc_holder
: allocator_type(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
{}
//Constructor, does not throw
template<class AllocConvertible, class SizeType>
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, SizeType initial_size)
: allocator_type(boost::forward<AllocConvertible>(a))
@@ -351,19 +390,8 @@ struct vector_alloc_holder
//Size is initialized here so vector should only call uninitialized_xxx after this
, m_size(static_cast<stored_size_type>(initial_size))
, m_capacity()
{
if (BOOST_UNLIKELY(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();
size_type final_cap = static_cast<size_type>(initial_size);
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
this->set_stored_capacity(final_cap);
}
}
{ this->do_initial_capacity(initial_size); }
//Constructor, does not throw
template<class SizeType>
vector_alloc_holder(vector_uninitialized_size_t, SizeType initial_size)
: allocator_type()
@@ -371,27 +399,7 @@ struct vector_alloc_holder
//Size is initialized here so vector should only call uninitialized_xxx after this
, m_size(static_cast<stored_size_type>(initial_size))
, m_capacity()
{
if (BOOST_UNLIKELY(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();
size_type final_cap = initial_size;
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
this->set_stored_capacity(final_cap);
}
}
vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
: allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
, m_start(holder.m_start)
, m_size(holder.m_size)
, m_capacity(holder.m_capacity)
{
holder.m_start = pointer();
holder.m_size = holder.m_capacity = 0;
}
{ this->do_initial_capacity(initial_size); }
vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
@@ -410,6 +418,34 @@ struct vector_alloc_holder
, m_capacity(n)
{}
template<class AllocConvertible, class SizeType>
vector_alloc_holder(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocConvertible) a)
: allocator_type(boost::forward<AllocConvertible>(a))
//, m_start()
//Size is initialized here so vector should only call uninitialized_xxx after this
, m_size()
, m_capacity(static_cast<stored_size_type>(initial_capacity))
{ this->do_maybe_initial_capacity(p, initial_capacity); }
template<class SizeType>
vector_alloc_holder(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
: allocator_type()
//, m_start()
//Size is initialized here so vector should only call uninitialized_xxx after this
, m_size()
, m_capacity(static_cast<stored_size_type>(initial_capacity))
{ this->do_maybe_initial_capacity(p, initial_capacity); }
vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
: allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
, m_start(holder.m_start)
, m_size(holder.m_size)
, m_capacity(holder.m_capacity)
{
holder.m_start = pointer();
holder.m_size = holder.m_capacity = 0;
}
BOOST_CONTAINER_FORCEINLINE ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
{
if(this->m_capacity){
@@ -822,6 +858,9 @@ private:
BOOST_CONTAINER_FORCEINLINE void steal_resources(vector &x)
{ return this->m_holder.steal_resources(x.m_holder); }
BOOST_CONTAINER_FORCEINLINE void protected_set_size(size_type n)
{ this->m_holder.m_size = static_cast<stored_size_type>(n); }
template<class AllocFwd>
BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a)
: m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
@@ -831,6 +870,32 @@ private:
: m_holder(initial_capacity_t(), initial_memory, cap)
{}
template<class SizeType, class AllocFwd>
BOOST_CONTAINER_FORCEINLINE vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocFwd) a)
: m_holder(maybe_initial_capacity_t(), p, initial_capacity, ::boost::forward<AllocFwd>(a))
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += size_type(p != pointer());
#endif
}
template<class SizeType>
BOOST_CONTAINER_FORCEINLINE vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
: m_holder(maybe_initial_capacity_t(), p, initial_capacity)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += size_type(p != pointer());
#endif
}
template <class U>
void protected_init_n(const size_type new_size, const U& u)
{
BOOST_ASSERT(this->empty());
this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), this->priv_raw_begin(), new_size);
this->m_holder.set_stored_size(new_size);
}
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: