Sync from upstream.

This commit is contained in:
Rene Rivera
2024-05-30 11:21:12 -05:00
30 changed files with 830 additions and 375 deletions

View File

@@ -26,7 +26,6 @@ target_link_libraries(boost_container
Boost::config
Boost::intrusive
Boost::move
Boost::static_assert
)
target_compile_definitions(boost_container

View File

@@ -293,7 +293,7 @@ void test_vectors()
#endif
std::size_t numele [] = { 100000 };
#elif defined SIMPLE_IT
std::size_t numit [] = { 100 };
std::size_t numit [] = { 10 };
std::size_t numele [] = { 100000 };
#else
#ifdef NDEBUG

View File

@@ -1409,6 +1409,16 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes Release Notes]
[section:release_notes_boost_1_86_00 Boost 1.86 Release]
* Fixed bugs/issues:
* [@https://github.com/boostorg/container/issues/280 GitHub #280: ['"Several containers don't support non-movable types when move assigning"]].
* [@https://github.com/boostorg/container/issues/277 GitHub #277: ['"Remove dep on boost::static_assert"]].
* [@https://github.com/boostorg/container/issues/273 GitHub #273: ['"flat_map/vector crashes on appends (memory corruption)"]].
* [@https://github.com/boostorg/container/issues/269 GitHub #269: ['"flat_multimap::emplace not sorting elements under GCC"]].
[endsect]
[section:release_notes_boost_1_85_00 Boost 1.85 Release]
* Removed Boost.StaticAssert dependency.

View File

@@ -1318,28 +1318,13 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
|| allocator_traits_type::is_always_equal::value)
{
if (BOOST_LIKELY(this != &x)) {
allocator_type &this_alloc = this->alloc();
allocator_type &x_alloc = x.alloc();
const bool propagate_alloc = allocator_traits_type::
propagate_on_container_move_assignment::value;
dtl::bool_<propagate_alloc> flag;
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
//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){
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
dtl::move_alloc(this_alloc, x_alloc, flag);
dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
//Nothrow swap
this->swap_members(x);
}
//Else do a one by one move
else{
this->assign( boost::make_move_iterator(x.begin())
, boost::make_move_iterator(x.end()));
}
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
return *this;
}
@@ -2378,6 +2363,30 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_move_assign(BOOST_RV_REF(deque) x, dtl::bool_<true> /*steal_resources*/)
{
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
dtl::move_alloc(this->alloc(), x.alloc(), flag);
dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
//Nothrow swap
this->swap_members(x);
}
void priv_move_assign(BOOST_RV_REF(deque) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (this->alloc() == x.alloc()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
this->assign(boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
}
}
inline size_type priv_index_of(const_iterator p) const
{
BOOST_ASSERT(this->cbegin() <= p);
@@ -2493,7 +2502,8 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
void priv_destroy_range(iterator p, iterator p2)
{
if(!Base::traits_t::trivial_dctr){
(void)p; (void)p2;
BOOST_IF_CONSTEXPR(!Base::traits_t::trivial_dctr){
for(;p != p2; ++p){
allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p));
}
@@ -2502,7 +2512,8 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
void priv_destroy_range(pointer p, pointer p2)
{
if(!Base::traits_t::trivial_dctr){
(void)p; (void)p2;
BOOST_IF_CONSTEXPR(!Base::traits_t::trivial_dctr){
for(;p != p2; ++p){
allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p));
}

View File

@@ -25,15 +25,17 @@
#include <boost/container/container_fwd.hpp>
// container/detail
#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/transform_iterator.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/placement_new.hpp>
#include <boost/container/detail/iterator.hpp>
// intrusive
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/twin.hpp>
// move
#include <boost/move/utility_core.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
namespace boost {
namespace container {
@@ -187,15 +189,100 @@ class basic_multiallocation_chain
}
};
template<class T>
struct cast_functor
template <class Iterator, class T>
class multialloc_iterator
: public boost::container::iterator
< typename Iterator::iterator_category
, T
, typename Iterator::difference_type
, T*
, T&
>
{
typedef typename dtl::add_reference<T>::type result_type;
template<class U>
result_type operator()(U &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
public:
inline explicit multialloc_iterator(const Iterator &it)
: m_it(it)
{}
inline explicit multialloc_iterator()
: m_it()
{}
//Constructors
inline multialloc_iterator& operator++()
{ increment(); return *this; }
inline multialloc_iterator operator++(int)
{
multialloc_iterator result (*this);
increment();
return result;
}
inline friend bool operator== (const multialloc_iterator& i, const multialloc_iterator& i2)
{ return i.equal(i2); }
inline friend bool operator!= (const multialloc_iterator& i, const multialloc_iterator& i2)
{ return !(i == i2); }
inline friend typename Iterator::difference_type operator- (const multialloc_iterator& i, const multialloc_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
inline multialloc_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
inline multialloc_iterator operator+(typename Iterator::difference_type off) const
{
multialloc_iterator other(*this);
other.advance(off);
return other;
}
inline friend multialloc_iterator operator+(typename Iterator::difference_type off, const multialloc_iterator& right)
{ return right + off; }
inline multialloc_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
inline multialloc_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
inline T& operator*() const
{ return *this->operator->(); }
inline T* operator->() const
{ return static_cast<T*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(m_it))); }
inline Iterator & base()
{ return m_it; }
inline const Iterator & base() const
{ return m_it; }
private:
Iterator m_it;
inline void increment()
{ ++m_it; }
inline void decrement()
{ --m_it; }
inline bool equal(const multialloc_iterator &other) const
{ return m_it == other.m_it; }
inline bool less(const multialloc_iterator &other) const
{ return other.m_it < m_it; }
inline void advance(typename Iterator::difference_type n)
{ boost::container::iterator_advance(m_it, n); }
inline typename Iterator::difference_type distance_to(const multialloc_iterator &other)const
{ return boost::container::iterator_distance(other.m_it, m_it); }
};
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
: public MultiallocationChain
@@ -217,9 +304,8 @@ class transform_multiallocation_chain
{ return pointer_traits::static_cast_from(p); }
public:
typedef transform_iterator
< typename MultiallocationChain::iterator
, dtl::cast_functor <T> > iterator;
typedef multialloc_iterator
<typename MultiallocationChain::iterator, T> iterator;
typedef typename MultiallocationChain::size_type size_type;
typedef boost::intrusive::twin<pointer> pointer_pair;

View File

@@ -688,40 +688,13 @@ class tree
boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
{
if (BOOST_LIKELY(this != &x)) {
NodeAlloc &this_alloc = this->node_alloc();
NodeAlloc &x_alloc = x.node_alloc();
const bool propagate_alloc = allocator_traits<NodeAlloc>::
propagate_on_container_move_assignment::value;
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
//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){
//Destroy
this->clear();
//Move allocator if needed
this->AllocHolder::move_assign_alloc(x);
//Obtain resources
this->icont() = boost::move(x.icont());
}
//Else do a one by one move
else{
//Transfer all the nodes to a temporary tree
//If anything goes wrong, all the nodes will be destroyed
//automatically
Icont other_tree(::boost::move(this->icont()));
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
(::boost::move(x.icont())
, RecyclingCloner<AllocHolder, true>(*this, other_tree)
, Destroyer(this->node_alloc()));
//If there are remaining nodes, destroy them
NodePtr p;
while((p = other_tree.unlink_leftmost_without_rebalance())){
AllocHolder::destroy_node(p);
}
}
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
return *this;
}
@@ -895,6 +868,42 @@ class tree
private:
void priv_move_assign(BOOST_RV_REF(tree) x, dtl::bool_<true> /*steal_resources*/)
{
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
this->AllocHolder::move_assign_alloc(x);
//Obtain resources
this->icont() = boost::move(x.icont());
}
void priv_move_assign(BOOST_RV_REF(tree) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (this->node_alloc() == x.node_alloc()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
//Transfer all the nodes to a temporary tree
//If anything goes wrong, all the nodes will be destroyed
//automatically
Icont other_tree(::boost::move(this->icont()));
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
(::boost::move(x.icont())
, RecyclingCloner<AllocHolder, true>(*this, other_tree)
, Destroyer(this->node_alloc()));
//If there are remaining nodes, destroy them
NodePtr p;
while ((p = other_tree.unlink_leftmost_without_rebalance())) {
AllocHolder::destroy_node(p);
}
}
}
template<class KeyConvertible, class M>
iiterator priv_insert_or_assign_commit

View File

@@ -512,20 +512,21 @@ class devector
const devector &x = rhs;
if (this == &x) { return *this; } // skip self
BOOST_IF_CONSTEXPR(allocator_traits_type::propagate_on_container_copy_assignment::value)
const bool do_propagate = allocator_traits_type::propagate_on_container_copy_assignment::value;
BOOST_IF_CONSTEXPR(do_propagate)
{
allocator_type &this_alloc = this->get_allocator_ref();
const allocator_type &other_alloc = x.get_allocator_ref();
if (this_alloc != other_alloc)
{
// new allocator cannot free existing storage
this->clear();
this->deallocate_buffer();
m_.capacity = 0u;
m_.buffer = pointer();
}
this_alloc = other_alloc;
allocator_type &this_alloc = this->get_allocator_ref();
const allocator_type &other_alloc = x.get_allocator_ref();
if (this_alloc != other_alloc)
{
// new allocator cannot free existing storage
this->clear();
this->deallocate_buffer();
m_.capacity = 0u;
m_.buffer = pointer();
}
dtl::bool_<do_propagate> flag;
dtl::assign_alloc(this_alloc, other_alloc, flag);
}
size_type n = x.size();
@@ -565,53 +566,16 @@ class devector
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
BOOST_CONSTEXPR_OR_CONST bool copy_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
BOOST_IF_CONSTEXPR (copy_alloc || get_allocator_ref() == x.get_allocator_ref())
{
this->clear();
this->deallocate_buffer();
if (copy_alloc)
{
this->get_allocator_ref() = boost::move(x.get_allocator_ref());
}
m_.capacity = x.m_.capacity;
m_.buffer = x.m_.buffer;
m_.front_idx = x.m_.front_idx;
m_.back_idx = x.m_.back_idx;
// leave x in valid state
x.m_.capacity = 0u;
x.m_.buffer = pointer();
x.m_.back_idx = x.m_.front_idx = 0;
if (BOOST_LIKELY(this != &x)) {
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
else
{
// if the allocator shouldn't be copied and they do not compare equal
// we can't steal memory.
move_iterator<iterator> xbegin = boost::make_move_iterator(x.begin());
move_iterator<iterator> xend = boost::make_move_iterator(x.end());
if (copy_alloc)
{
get_allocator_ref() = boost::move(x.get_allocator_ref());
}
if (m_.capacity >= x.size())
{
overwrite_buffer(xbegin, xend);
}
else
{
allocate_and_copy_range(xbegin, xend);
}
}
BOOST_ASSERT(invariants_ok());
return *this;
}
@@ -1309,6 +1273,78 @@ class devector
return m_.buffer[m_.front_idx + n];
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns an iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(n <= size());
return iterator(m_.buffer + (m_.front_idx + n));
}
//! <b>Requires</b>: size() >= n.
//!
//! <b>Effects</b>: Returns a const_iterator to the nth element
//! from the beginning of the container. Returns end()
//! if n == size().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(n <= size());
return const_iterator(m_.buffer + (m_.front_idx + n));
}
//! <b>Requires</b>: begin() <= p <= end().
//!
//! <b>Effects</b>: Returns the index of the element pointed by p
//! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(p >= begin());
BOOST_ASSERT(p <= end());
return static_cast<size_type>(p - this->begin());
}
//! <b>Requires</b>: begin() <= p <= end().
//!
//! <b>Effects</b>: Returns the index of the element pointed by p
//! and size() if p == end().
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(p >= cbegin());
BOOST_ASSERT(p <= cend());
return static_cast<size_type>(p - this->cbegin());
}
/**
* **Returns**: A reference to the `n`th element in the devector.
*
@@ -2136,6 +2172,53 @@ class devector
private:
void priv_move_assign(BOOST_RV_REF(devector) x, dtl::bool_<true> /*steal_resources*/)
{
this->clear();
this->deallocate_buffer();
//Move allocator if needed
dtl::bool_<allocator_traits_type::
propagate_on_container_move_assignment::value> flag;
dtl::move_alloc(this->get_allocator_ref(), x.get_allocator_ref(), flag);
m_.capacity = x.m_.capacity;
m_.buffer = x.m_.buffer;
m_.front_idx = x.m_.front_idx;
m_.back_idx = x.m_.back_idx;
// leave x in valid state
x.m_.capacity = 0u;
x.m_.buffer = pointer();
x.m_.back_idx = x.m_.front_idx = 0;
}
void priv_move_assign(BOOST_RV_REF(devector) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (get_allocator_ref() == x.get_allocator_ref()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
// We can't steal memory.
move_iterator<iterator> xbegin = boost::make_move_iterator(x.begin());
move_iterator<iterator> xend = boost::make_move_iterator(x.end());
//Move allocator if needed
dtl::bool_<allocator_traits_type::
propagate_on_container_move_assignment::value> flag;
dtl::move_alloc(this->get_allocator_ref(), x.get_allocator_ref(), flag);
if (m_.capacity >= x.size()) {
overwrite_buffer(xbegin, xend);
}
else {
allocate_and_copy_range(xbegin, xend);
}
}
}
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
size_type pos_to_index(const_iterator i) const
{

View File

@@ -343,26 +343,13 @@ class list
|| allocator_traits_type::is_always_equal::value)
{
if (BOOST_LIKELY(this != &x)) {
NodeAlloc &this_alloc = this->node_alloc();
NodeAlloc &x_alloc = x.node_alloc();
const bool propagate_alloc = allocator_traits_type::
propagate_on_container_move_assignment::value;
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
//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){
//Destroy
this->clear();
//Move allocator if needed
this->AllocHolder::move_assign_alloc(x);
//Obtain resources
this->icont() = boost::move(x.icont());
}
//Else do a one by one move
else{
this->assign( boost::make_move_iterator(x.begin())
, boost::make_move_iterator(x.end()));
}
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
return *this;
}
@@ -1391,6 +1378,28 @@ class list
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_move_assign(BOOST_RV_REF(list) x, dtl::bool_<true> /*steal_resources*/)
{
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
this->AllocHolder::move_assign_alloc(x);
//Obtain resources
this->icont() = boost::move(x.icont());
}
void priv_move_assign(BOOST_RV_REF(list) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (this->node_alloc() == x.node_alloc()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
this->assign(boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
}
}
static bool priv_is_linked(const_iterator const position)
{
const_iterator cur(position);

View File

@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
#define BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
#ifndef BOOST_CONTAINER_NODE_ALLOCATOR_HPP
#define BOOST_CONTAINER_NODE_ALLOCATOR_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
@@ -26,6 +26,7 @@
#include <boost/container/detail/node_pool.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/dlmalloc.hpp>
#include <boost/container/detail/singleton.hpp>
@@ -225,7 +226,10 @@ class node_allocator
typedef dtl::singleton_default<shared_pool_t> singleton_t;
typename shared_pool_t::multiallocation_chain ch;
singleton_t::instance().allocate_nodes(num_elements, ch);
chain.incorporate_after(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
chain.incorporate_after(chain.before_begin()
, (T*)boost::movelib::iterator_to_raw_pointer(ch.begin())
, (T*)boost::movelib::iterator_to_raw_pointer(ch.last())
, ch.size());
}
//!Deallocates memory previously allocated with allocate_one().
@@ -246,7 +250,10 @@ class node_allocator
typedef dtl::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef dtl::singleton_default<shared_pool_t> singleton_t;
typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
typename shared_pool_t::multiallocation_chain ch
( boost::movelib::iterator_to_raw_pointer(chain.begin())
, boost::movelib::iterator_to_raw_pointer(chain.last())
, chain.size());
singleton_t::instance().deallocate_nodes(ch);
}
@@ -285,8 +292,8 @@ class node_allocator
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_CONTAINER_STATIC_ASSERT(( Version > 1 ));
void *first = &*chain.begin();
void *last = &*chain.last();
void *first = boost::movelib::iterator_to_raw_pointer(chain.begin());
void *last = boost::movelib::iterator_to_raw_pointer(chain.last());
size_t num = chain.size();
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
@@ -337,4 +344,4 @@ class node_allocator
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
#endif //#ifndef BOOST_CONTAINER_NODE_ALLOCATOR_HPP

View File

@@ -232,7 +232,7 @@ class node_handle
if(was_nh_non_null){
if(was_this_non_null){
this->destroy_deallocate_node();
if(nator_traits::propagate_on_container_move_assignment::value){
BOOST_IF_CONSTEXPR(nator_traits::propagate_on_container_move_assignment::value){
this->node_alloc() = ::boost::move(nh.node_alloc());
}
}
@@ -336,7 +336,7 @@ class node_handle
if(was_nh_non_null){
if(was_this_non_null){
if(nator_traits::propagate_on_container_swap::value){
BOOST_IF_CONSTEXPR(nator_traits::propagate_on_container_swap::value){
::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
}
}

View File

@@ -617,7 +617,7 @@ typedef deque_opt<0u, 0u> deque_null_opt;
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::deque.
//! Supported options are: \c boost::container::block_bytes
//! Supported options are: \c boost::container::block_bytes and \c boost::container::block_size
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
template<class ...Options>
#else

View File

@@ -368,28 +368,14 @@ class slist
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
slist & sr = x;
if (BOOST_LIKELY(this != &sr)) {
NodeAlloc &this_alloc = this->node_alloc();
NodeAlloc &x_alloc = sr.node_alloc();
const bool propagate_alloc = allocator_traits_type::
propagate_on_container_move_assignment::value;
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
//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){
//Destroy
this->clear();
//Move allocator if needed
this->AllocHolder::move_assign_alloc(sr);
//Obtain resources
this->icont() = boost::move(sr.icont());
}
//Else do a one by one move
else{
this->assign( boost::make_move_iterator(sr.begin())
, boost::make_move_iterator(sr.end()));
}
if (BOOST_LIKELY(this != &x)) {
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
return *this;
}
@@ -1579,6 +1565,27 @@ class slist
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_move_assign(BOOST_RV_REF(slist) x, dtl::bool_<true> /*steal_resources*/)
{
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
this->AllocHolder::move_assign_alloc(x);
//Obtain resources
this->icont() = boost::move(x.icont());
}
void priv_move_assign(BOOST_RV_REF(slist) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (this->node_alloc() == x.node_alloc()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
this->assign(boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
}
}
template<class U>
void priv_push_front(BOOST_FWD_REF(U) x)

View File

@@ -346,9 +346,10 @@ 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 allocator_type;
typedef typename allocator_traits<allocator_type>::
template portable_rebind_alloc<void>::type void_allocator_t;
typedef typename real_allocator<T, SecAlloc>::type underlying_allocator_t;
typedef typename allocator_traits<underlying_allocator_t>::
template portable_rebind_alloc<void>::type void_underlying_allocator_t;
typedef small_vector_allocator<T, void_underlying_allocator_t, Options>allocator_type;
typedef typename dtl::get_small_vector_opt<Options>::type options_t;
typedef typename dtl::vector_for_small_vector
<T, SecAlloc, Options>::type base_type;
@@ -356,12 +357,12 @@ class small_vector_base
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
typedef typename allocator_traits<allocator_type>::void_pointer void_pointer;
typedef typename allocator_traits<allocator_type>::const_void_pointer const_void_pointer;
typedef small_vector_allocator<T, void_allocator_t, Options> small_allocator_type;
private:
BOOST_COPYABLE_AND_MOVABLE(small_vector_base)
friend class small_vector_allocator<T, void_allocator_t, Options>;
friend class small_vector_allocator<T, void_underlying_allocator_t, Options>;
inline
const_pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW

View File

@@ -872,31 +872,14 @@ class stable_vector
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
//for move constructor, no aliasing (&x != this) is assumed.
if (BOOST_LIKELY(this != &x)) {
node_allocator_type &this_alloc = this->priv_node_alloc();
node_allocator_type &x_alloc = x.priv_node_alloc();
const bool propagate_alloc = allocator_traits_type::
propagate_on_container_move_assignment::value;
dtl::bool_<propagate_alloc> flag;
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
//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){
BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
dtl::move_alloc(this_alloc, x_alloc, flag);
//Take resources
this->index.swap(x.index);
this->priv_swap_members(x);
}
//Else do a one by one move
else{
this->assign( boost::make_move_iterator(x.begin())
, boost::make_move_iterator(x.end()));
}
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
return *this;
}
@@ -1852,6 +1835,35 @@ class stable_vector
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_move_assign(BOOST_RV_REF(stable_vector) x, dtl::bool_<true> /*steal_resources*/)
{
//Resources can be transferred if both allocators are
//going to be equal after this function (either propagated or already equal)
BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
dtl::bool_<allocator_traits_type::
propagate_on_container_move_assignment::value> flag;
dtl::move_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
//Take resources
this->index = boost::move(x.index); //this also moves the vector's allocator if needed
this->priv_swap_members(x);
}
void priv_move_assign(BOOST_RV_REF(stable_vector) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (this->priv_node_alloc() == x.priv_node_alloc()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
this->assign(boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
}
}
bool priv_in_range(const_iterator pos) const
{
return (this->begin() <= pos) && (pos < this->end());

View File

@@ -913,26 +913,13 @@ class basic_string
|| allocator_traits_type::is_always_equal::value)
{
if (BOOST_LIKELY(this != &x)) {
allocator_type &this_alloc = this->alloc();
allocator_type &x_alloc = x.alloc();
const bool propagate_alloc = allocator_traits_type::
propagate_on_container_move_assignment::value;
dtl::bool_<propagate_alloc> flag;
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
//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){
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
dtl::move_alloc(this_alloc, x_alloc, flag);
//Nothrow swap
this->swap_data(x);
}
//Else do a one by one move
else{
this->assign( x.begin(), x.end());
}
//We know resources can be transferred at comiple time if both allocators are
//always equal or the allocator is going to be propagated
const bool can_steal_resources_alloc
= allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value;
dtl::bool_<can_steal_resources_alloc> flag;
this->priv_move_assign(boost::move(x), flag);
}
return *this;
}
@@ -2908,6 +2895,30 @@ class basic_string
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_move_assign(BOOST_RV_REF(basic_string) x, dtl::bool_<true> /*steal_resources*/)
{
//Destroy objects but retain memory in case x reuses it in the future
this->clear();
//Move allocator if needed
dtl::bool_<allocator_traits_type::
propagate_on_container_move_assignment::value> flag;
dtl::move_alloc(this->alloc(), x.alloc(), flag);
//Nothrow swap
this->swap_data(x);
}
void priv_move_assign(BOOST_RV_REF(basic_string) x, dtl::bool_<false> /*steal_resources*/)
{
//We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
//Resources can be transferred if both allocators are equal
if (this->alloc() == x.alloc()) {
this->priv_move_assign(boost::move(x), dtl::true_());
}
else {
this->assign(x.begin(), x.end());
}
}
bool priv_reserve_no_null_end(size_type res_arg)
{
if (res_arg > this->max_size()){

View File

@@ -2531,6 +2531,38 @@ private:
x.clear();
}
template<class OtherA>
void priv_move_assign_steal_or_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x, dtl::true_type /*data_can_be_always_stolen*/)
{
this->clear();
if (BOOST_LIKELY(!!this->m_holder.m_start))
this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
this->m_holder.steal_resources(x.m_holder);
}
template<class OtherA>
void priv_move_assign_steal_or_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x, dtl::false_type /*data_can_be_always_stolen*/)
{
const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
allocator_type& this_alloc = this->m_holder.alloc();
allocator_type& x_alloc = x.m_holder.alloc();
//In this allocator move constructor the allocator might will be propagated, but to support small_vector-like
//types, we need to check the currently owned buffers to know if they are propagable.
const bool is_buffer_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
if (is_buffer_propagable_from_x) {
this->priv_move_assign_steal_or_assign(boost::move(x), dtl::true_type());
}
//Else do a one by one move. Also, clear the source as users find confusing
//elements are still alive in the source container.
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())) );
x.clear();
}
}
template<class OtherA>
void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
, typename dtl::disable_if_or
@@ -2542,30 +2574,16 @@ private:
//for move assignment, no aliasing (&x != this) is assumed.
//x.size() == 0 is allowed for buggy std libraries.
BOOST_ASSERT(this != &x || x.size() == 0);
allocator_type &this_alloc = this->m_holder.alloc();
allocator_type &x_alloc = x.m_holder.alloc();
const bool alloc_is_always_equal = allocator_traits_type::is_always_equal::value;
const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
const bool partially_propagable_alloc = allocator_traits_type::is_partially_propagable::value;
const bool data_can_be_always_be_stolen = alloc_is_always_equal || (propagate_alloc && !partially_propagable_alloc);
//In this allocator move constructor the allocator maybe will be propagated -----------------------v
const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
this->priv_move_assign_steal_or_assign(boost::move(x), dtl::bool_<data_can_be_always_be_stolen>());
//Resources can be transferred if both allocators are
//going to be equal after this function (either propagated or already equal)
if(is_propagable_from_x){
this->clear();
if(BOOST_LIKELY(!!this->m_holder.m_start))
this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
this->m_holder.steal_resources(x.m_holder);
}
//Else do a one by one move. Also, clear the source as users find confusing
//elements are still alive in the source container.
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() ))
);
x.clear();
}
//Move allocator if needed
allocator_type& this_alloc = this->m_holder.alloc();
allocator_type& x_alloc = x.m_holder.alloc();
dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
}

View File

@@ -307,14 +307,17 @@ int test_cont_variants()
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
if(test::vector_test<MyCont>())
if (test::vector_test<MyCont>())
return 1;
if(test::vector_test<MyMoveCont>())
if (test::vector_test<MyMoveCont>())
return 1;
if(test::vector_test<MyCopyMoveCont>())
if (test::vector_test<MyCopyMoveCont>())
return 1;
if(test::vector_test<MyCopyCont>())
if (test::vector_test<MyCopyCont>())
return 1;
if (test::vector_test<MyMoveConstructCont>())
return 1;
return 0;
}

View File

@@ -3903,7 +3903,7 @@ struct GetAllocatorCont
template<class ValueType>
struct apply
{
typedef vector< ValueType
typedef devector< ValueType
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type
> type;
@@ -3962,14 +3962,19 @@ int test_cont_variants()
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
if(test::vector_test<MyCont>())
if (test::vector_test<MyCont>())
return 1;
if(test::vector_test<MyMoveCont>())
if (test::vector_test<MyMoveCont>())
return 1;
if(test::vector_test<MyCopyMoveCont>())
if (test::vector_test<MyCopyMoveCont>())
return 1;
if(test::vector_test<MyCopyCont>())
if (test::vector_test<MyCopyCont>())
return 1;
if (test::vector_test<MyCopyCont>())
return 1;
if (test::vector_test<MyMoveConstructCont>())
return 1;
return 0;
}

View File

@@ -10,6 +10,7 @@
#include <boost/container/list.hpp>
#include <boost/container/adaptive_pool.hpp>
#include <boost/container/node_allocator.hpp>
#include "dummy_test_allocator.hpp"
#include <memory>
@@ -78,9 +79,9 @@ struct GetAllocatorCont
struct apply
{
typedef list< ValueType
, typename allocator_traits<VoidAllocator>
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type
> type;
> type;
};
};
@@ -91,9 +92,11 @@ int test_cont_variants()
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
if(test::list_test<MyCont, true>())
return 1;
if(test::list_test<MyMoveCont, true>())
return 1;
if(test::list_test<MyCopyMoveCont, true>())
@@ -102,6 +105,8 @@ int test_cont_variants()
return 1;
if(test::list_test<MyCopyCont, true>())
return 1;
if (test::list_test<MyMoveConstructCont, true>())
return 1;
return 0;
}
@@ -171,20 +176,27 @@ int main ()
////////////////////////////////////
// Testing allocator implementations
////////////////////////////////////
// int variants
if (test::list_test<list<int, std::allocator<int> >, true>())
if (test_cont_variants< new_allocator<void> >()) {
std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
return 1;
if (test::list_test<list<int>, true>())
}
if (test_cont_variants< std::allocator<void> >()) {
std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
return 1;
}
if (test::list_test<list<int, adaptive_pool<int> >, true>())
return 1;
if (test::list_test<list<test::movable_int>, true>())
return 1;
if (test::list_test<list<test::movable_and_copyable_int>, true>())
return 1;
if (test::list_test<list<test::copyable_int>, true>())
return 1;
if (test::list_test<list<int, node_allocator<int> >, false>())
return 1;
/*
// boost::container::allocator
if (test_cont_variants< allocator<void> >()) {
std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
return 1;
}
*/
////////////////////////////////////
// Emplace testing
////////////////////////////////////

View File

@@ -166,6 +166,61 @@ struct list_pop_back_function<false>
}
};
template<class
, bool>
int list_move_assignable_only(boost::container::dtl::false_type)
{
return 0;
}
//Function to check if both sets are equal
template < class MyBoostList
, bool DoublyLinked >
int list_move_assignable_only(boost::container::dtl::true_type)
{
typedef std::list<int> MyStdList;
typedef typename MyBoostList::value_type IntType;
const std::size_t max = 100u;
typedef list_push_data_function<DoublyLinked> push_data_t;
{
::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100u);
::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100u);
MyBoostList& boostlist = *boostlistp;
MyStdList& stdlist = *stdlistp;
if (push_data_t::execute(max, boostlist, stdlist)) {
return 1;
}
IntType aux_vect[50];
for (int i = 0; i < 50; ++i) {
aux_vect[i] = -1;
}
int aux_vect2[50];
for (int i = 0; i < 50; ++i) {
aux_vect2[i] = -1;
}
boostlist.assign(boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(&aux_vect[50]));
stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
if (!CheckEqualContainers(boostlist, stdlist)) return 1;
for (int i = 0; i < 50; ++i) {
aux_vect[i] = -1;
}
for (int i = 0; i < 50; ++i) {
aux_vect2[i] = -1;
}
boostlist.assign(boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
, boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
if (!CheckEqualContainers(boostlist, stdlist)) return 1;
}
return 0;
}
template<class MyBoostList
,bool DoublyLinked>
int list_test (bool copied_allocators_equal = true)
@@ -203,9 +258,10 @@ int list_test (bool copied_allocators_equal = true)
::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100u);
::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>();
*boostlistp2 = ::boost::move(*boostlistp);
if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
if (!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
}
::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>();
::boost::movelib::unique_ptr<MyStdList> const pstdlist = ::boost::movelib::make_unique<MyStdList>();
@@ -228,34 +284,8 @@ int list_test (bool copied_allocators_equal = true)
stdlist.pop_front();
if(!CheckEqualContainers(boostlist, stdlist)) return 1;
{
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
boostlist.assign(boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(&aux_vect[50]));
stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
if(!CheckEqualContainers(boostlist, stdlist)) return 1;
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
}
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
boostlist.assign(boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
if(!CheckEqualContainers(boostlist, stdlist)) return 1;
}
if (0 != list_move_assignable_only<MyBoostList, DoublyLinked>(dtl::bool_<boost::container::test::is_move_assignable<IntType>::value>()))
return 1;
if(copied_allocators_equal){
boostlist.sort();
@@ -274,8 +304,7 @@ int list_test (bool copied_allocators_equal = true)
{
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = -1;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -294,8 +323,7 @@ int list_test (bool copied_allocators_equal = true)
return 1;
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = -1;
}
for(int i = 0; i < 50; ++i){

View File

@@ -557,6 +557,15 @@ int main ()
std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl;
return 1;
}
if (0 != test::map_test
< GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::moveconstruct_int>::map_type
, MyStdMap
, GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::moveconstruct_int>::multimap_type
, MyStdMultiMap>()) {
std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl;
return 1;
}
}
////////////////////////////////////

View File

@@ -54,6 +54,78 @@ void map_test_rebalanceable(C &c, boost::container::dtl::true_type)
c.rebalance();
}
template<class MyBoostMap
, class MyStdMap
, class MyBoostMultiMap
, class MyStdMultiMap>
int map_move_assignable_only(boost::container::dtl::false_type)
{
return 0;
}
//Function to check if both sets are equal
template<class MyBoostMap
, class MyStdMap
, class MyBoostMultiMap
, class MyStdMultiMap>
int map_move_assignable_only(boost::container::dtl::true_type)
{
typedef typename MyBoostMap::key_type IntType;
typedef dtl::pair<IntType, IntType> IntPairType;
//This is really nasty, but we have no other simple choice
IntPairType aux_vect[(std::size_t)MaxElem];
for (int i = 0; i < MaxElem; ++i) {
IntType i1(i / 2);
IntType i2(i / 2);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
}
typedef typename MyStdMap::value_type StdValueType;
typedef typename MyStdMap::key_type StdKeyType;
typedef typename MyStdMap::mapped_type StdMappedType;
StdValueType aux_vect2[(std::size_t)MaxElem];
for (int i = 0; i < MaxElem; ++i) {
new(&aux_vect2[i])StdValueType(StdKeyType(i / 2), StdMappedType(i / 2));
}
IntPairType aux_vect3[(std::size_t)MaxElem];
for (int i = 0; i < MaxElem; ++i) {
IntType i1(i / 2);
IntType i2(i / 2);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
}
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>
(boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(&aux_vect[0] + MaxElem));
::boost::movelib::unique_ptr<MyStdMap> const pstdmap2 = ::boost::movelib::make_unique<MyStdMap>
(&aux_vect2[0], &aux_vect2[0] + MaxElem);
::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>
(boost::make_move_iterator(&aux_vect3[0])
, boost::make_move_iterator(&aux_vect3[0] + MaxElem));
::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap2 = ::boost::movelib::make_unique<MyStdMultiMap>
(&aux_vect2[0], &aux_vect2[0] + MaxElem);
MyBoostMap& boostmap2 = *pboostmap2;
MyStdMap& stdmap2 = *pstdmap2;
/* fix assignable */
{
IntType i0(0);
IntType i1(1);
boostmap2[::boost::move(i0)] = ::boost::move(i1);
}
{
IntType i1(1);
boostmap2[IntType(0)] = ::boost::move(i1);
}
stdmap2[0] = 1;
if (!CheckEqualContainers(boostmap2, stdmap2)) return 1;
return 0;
}
template<class MyBoostMap
,class MyStdMap
,class MyBoostMultiMap
@@ -67,8 +139,8 @@ template<class MyBoostMap
,class MyStdMultiMap>
int map_test_copyable(boost::container::dtl::true_type)
{
typedef typename MyBoostMap::key_type IntType;
typedef dtl::pair<IntType, IntType> IntPairType;
typedef typename MyBoostMap::key_type IntType;
typedef dtl::pair<IntType, IntType> IntPairType;
typedef typename MyStdMap::value_type StdPairType;
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>();
@@ -366,6 +438,9 @@ int map_test_step(MyBoostMap &, MyStdMap &, MyBoostMultiMap &, MyStdMultiMap &)
return 1;
}
if (0 != map_move_assignable_only<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>(dtl::bool_<boost::container::test::is_move_assignable<IntType>::value>()))
return 1;
{
IntType i0(0);
boostmap2.erase(i0);
@@ -373,17 +448,6 @@ int map_test_step(MyBoostMap &, MyStdMap &, MyBoostMultiMap &, MyStdMultiMap &)
stdmap2.erase(0);
stdmultimap2.erase(0);
}
{
IntType i0(0);
IntType i1(1);
boostmap2[::boost::move(i0)] = ::boost::move(i1);
}
{
IntType i1(1);
boostmap2[IntType(0)] = ::boost::move(i1);
}
stdmap2[0] = 1;
if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
}
return 0;
}
@@ -819,12 +883,12 @@ int map_test_indexing(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &b
IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
}
/*
for(int i = 0; i < MaxElem; ++i){
boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second);
stdmap[i] = i;
}
*/
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
}
@@ -934,14 +998,20 @@ int map_test_insert_or_assign_impl()
return 0;
}
template< class MyBoostMap, class StdMap, class Copyable>
int map_test_insert_or_assign(dtl::bool_<false>, Copyable)//noncopyable
{
return 0;
}
template< class MyBoostMap, class StdMap>
int map_test_insert_or_assign(dtl::bool_<false> )//noncopyable
int map_test_insert_or_assign(dtl::bool_<true>, dtl::bool_<false> )//noncopyable
{
return map_test_insert_or_assign_impl<MyBoostMap, StdMap, move_op>();
}
template< class MyBoostMap, class StdMap>
int map_test_insert_or_assign(dtl::bool_<true> )//copyable
int map_test_insert_or_assign(dtl::bool_<true>, dtl::bool_<true> )//copyable
{
int r = map_test_insert_or_assign_impl<MyBoostMap, StdMap, const_ref_op>();
if (r)
@@ -1165,6 +1235,7 @@ int map_test()
MyBoostMultiMap &boostmultimap = *pboostmultimap;
MyStdMultiMap &stdmultimap = *pstdmultimap;
typedef dtl::bool_<boost::container::test::is_copyable<IntType>::value> copyable_t;
typedef dtl::bool_<boost::container::test::is_move_assignable<IntType>::value> move_assignable_t;
if (map_test_step(boostmap, stdmap, boostmultimap, stdmultimap))
return 1;
@@ -1190,7 +1261,7 @@ int map_test()
if (map_test_merge(boostmap, stdmap, boostmultimap, stdmultimap))
return 1;
if (map_test_insert_or_assign<MyBoostMap, MyStdMap>(copyable_t()))
if (map_test_insert_or_assign<MyBoostMap, MyStdMap>(move_assignable_t(), copyable_t()))
return 1;
if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>(copyable_t()))

View File

@@ -37,6 +37,11 @@ struct is_move_assignable
static const bool value = true;
};
template<class T>
struct is_move_constructible
{
static const bool value = true;
};
/////////////////////////
@@ -594,6 +599,13 @@ struct life_count< non_copymovable_int >
{ return c == non_copymovable_int::count; }
};
template<>
struct is_move_constructible<non_copymovable_int>
{
static const bool value = false;
};
} //namespace test {
} //namespace container {
} //namespace boost {

View File

@@ -544,6 +544,15 @@ int main ()
std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl;
return 1;
}
if (0 != test::set_test
< GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::moveconstruct_int>::set_type
, MyStdSet
, GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::moveconstruct_int>::multiset_type
, MyStdMultiSet>()) {
std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl;
return 1;
}
}
////////////////////////////////////

View File

@@ -161,8 +161,7 @@ int set_test ()
{ //Set(beg, end, compare)
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(i/2);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = i/2;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -170,8 +169,7 @@ int set_test ()
}
IntType aux_vect3[50];
for(int i = 0; i < 50; ++i){
IntType move_me(i/2);
aux_vect3[i] = boost::move(move_me);
aux_vect3[i] = i/2;
}
::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::key_compare());
@@ -185,8 +183,7 @@ int set_test ()
{ //Set(beg, end, alloc)
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(i/2);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = i/2;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -194,8 +191,7 @@ int set_test ()
}
IntType aux_vect3[50];
for(int i = 0; i < 50; ++i){
IntType move_me(i/2);
aux_vect3[i] = boost::move(move_me);
aux_vect3[i] = i/2;
}
::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::allocator_type());
@@ -209,8 +205,7 @@ int set_test ()
{
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(i/2);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = i/2;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -218,8 +213,7 @@ int set_test ()
}
IntType aux_vect3[50];
for(int i = 0; i < 50; ++i){
IntType move_me(i/2);
aux_vect3[i] = boost::move(move_me);
aux_vect3[i] = i/2;
}
::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
@@ -249,8 +243,7 @@ int set_test ()
//ordered range insertion
for(int i = 0; i < 50; ++i){
IntType move_me(i);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = i;
}
for(int i = 0; i < 50; ++i){
@@ -258,8 +251,7 @@ int set_test ()
}
for(int i = 0; i < 50; ++i){
IntType move_me(i);
aux_vect3[i] = boost::move(move_me);
aux_vect3[i] = i;
}
//some comparison operators
@@ -410,8 +402,7 @@ int set_test ()
{
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = -1;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -419,8 +410,7 @@ int set_test ()
}
IntType aux_vect3[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect3[i] = boost::move(move_me);
aux_vect3[i] = -1;
}
boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
@@ -455,8 +445,7 @@ int set_test ()
{
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
aux_vect[i] = -1;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -464,20 +453,17 @@ int set_test ()
}
IntType aux_vect3[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect3[i] = boost::move(move_me);
aux_vect3[i] = -1;
}
IntType aux_vect4[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect4[i] = boost::move(move_me);
aux_vect4[i] = -1;
}
IntType aux_vect5[50];
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect5[i] = boost::move(move_me);
aux_vect5[i] = -1;
}
boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));

View File

@@ -9,6 +9,7 @@
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/slist.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/container/adaptive_pool.hpp>
#include <memory>
#include "dummy_test_allocator.hpp"
@@ -54,6 +55,32 @@ struct GetAllocatorCont
};
};
template<class VoidAllocator>
int test_cont_variants()
{
typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
if(test::list_test<MyCont, false>())
return 1;
if(test::list_test<MyMoveCont, false>())
return 1;
if(test::list_test<MyCopyMoveCont, false>())
return 1;
if(test::list_test<MyCopyMoveCont, false>())
return 1;
if(test::list_test<MyCopyCont, false>())
return 1;
if (test::list_test<MyMoveConstructCont, false>())
return 1;
return 0;
}
bool test_support_for_initializer_list()
{
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -168,18 +195,18 @@ int main ()
////////////////////////////////////
// Testing allocator implementations
////////////////////////////////////
if (test::list_test<slist<int, std::allocator<int> >, false>())
if (test_cont_variants< new_allocator<void> >()) {
std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
return 1;
if (test::list_test<slist<int>, false>())
}
if (test_cont_variants< std::allocator<void> >()) {
std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
return 1;
}
if (test::list_test<slist<int, adaptive_pool<int> >, false>())
return 1;
if (test::list_test<slist<int, node_allocator<int> >, false>())
return 1;
if (test::list_test<slist<test::movable_int>, false>())
return 1;
if (test::list_test<slist<test::movable_and_copyable_int>, false>())
return 1;
if (test::list_test<slist<test::copyable_int>, false>())
return 1;
////////////////////////////////////
// Emplace testing

View File

@@ -193,10 +193,10 @@ int main()
if(!test_swap())
return 1;
if(test::vector_test< small_vector<int, 0> >())
if (test::vector_test< small_vector<int, 0> >())
return 1;
if(test::vector_test< small_vector<int, 2000> >())
if (test::vector_test< small_vector<int, 2000> >())
return 1;
if (test_cont_variants< new_allocator<void> >())

View File

@@ -72,14 +72,17 @@ int test_cont_variants()
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
if(test::vector_test<MyCont>())
if (test::vector_test<MyCont>())
return 1;
if(test::vector_test<MyMoveCont>())
if (test::vector_test<MyMoveCont>())
return 1;
if(test::vector_test<MyCopyMoveCont>())
if (test::vector_test<MyCopyMoveCont>())
return 1;
if(test::vector_test<MyCopyCont>())
if (test::vector_test<MyCopyCont>())
return 1;
if (test::vector_test<MyMoveConstructCont>())
return 1;
return 0;

View File

@@ -19,6 +19,8 @@
#include <boost/container/vector.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/container/adaptive_pool.hpp>
#include <boost/move/utility_core.hpp>
#include "check_equal_containers.hpp"
@@ -129,13 +131,13 @@ int test_cont_variants()
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
if(test::vector_test<MyCont>())
if (test::vector_test<MyCont>())
return 1;
if(test::vector_test<MyMoveCont>())
if (test::vector_test<MyMoveCont>())
return 1;
if(test::vector_test<MyCopyMoveCont>())
if (test::vector_test<MyCopyMoveCont>())
return 1;
if(test::vector_test<MyCopyCont>())
if (test::vector_test<MyCopyCont>())
return 1;
if (test::vector_test<MyMoveConstructCont>())
return 1;

View File

@@ -269,6 +269,8 @@ bool vector_copyable_only(MyBoostVector &boostvector, MyStdVector &stdvector, bo
return true;
}
template<class MyBoostVector>
int vector_move_assignable_only(boost::container::dtl::false_type)
{
@@ -345,9 +347,7 @@ int vector_move_assignable_only(boost::container::dtl::true_type)
//Initialize values
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType new_int(-1);
BOOST_CONTAINER_STATIC_ASSERT((boost::container::test::is_copyable<boost::container::test::movable_int>::value == false));
aux_vect[i] = boost::move(new_int);
aux_vect[i] = -1;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -374,8 +374,7 @@ int vector_move_assignable_only(boost::container::dtl::true_type)
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
IntType new_int(-i);
aux_vect[i] = boost::move(new_int);
aux_vect[i] = -i;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
@@ -391,8 +390,7 @@ int vector_move_assignable_only(boost::container::dtl::true_type)
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
for(int i = 0; i < 50; ++i){
IntType new_int(-i);
aux_vect[i] = boost::move(new_int);
aux_vect[i] = -i;
}
for(int i = 0; i < 50; ++i){
@@ -511,6 +509,30 @@ int vector_move_assignable_only(boost::container::dtl::true_type)
return 0;
}
template<class MyBoostVector>
int vector_test_fully_propagable(dtl::true_ /* fully_propagable */)
{
typedef std::vector<int> MyStdVector;
{
//operator=(Vector &&)
::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
::boost::movelib::make_unique<MyStdVector>(100u);
::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
::boost::movelib::make_unique<MyBoostVector>(100u);
::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
::boost::movelib::make_unique<MyBoostVector>();
*boostvectorp2 = ::boost::move(*boostvectorp);
if (!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
}
return 0;
}
template<class MyBoostVector>
int vector_test_fully_propagable(dtl::false_ /* fully_propagable */)
{
return 0;
}
template<class MyBoostVector>
int vector_test()
{
@@ -551,7 +573,10 @@ int vector_test()
if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
}
if (0 != vector_move_assignable_only< MyBoostVector>(dtl::bool_<boost::container::test::is_copyable<IntType>::value>()))
if (0 != vector_test_fully_propagable<MyBoostVector>
( dtl::bool_< !allocator_traits<typename MyBoostVector::allocator_type>::is_partially_propagable::value >() )) return 1;
if (0 != vector_move_assignable_only< MyBoostVector>(dtl::bool_<boost::container::test::is_move_assignable<IntType>::value>()))
return 1;
std::cout << std::endl << "Test OK!" << std::endl;