mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Unordered: Support moving allocators.
[SVN r73805]
This commit is contained in:
@ -65,7 +65,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
bucket_ptr buckets_;
|
||||
std::size_t bucket_count_;
|
||||
std::size_t size_;
|
||||
::boost::compressed_pair<bucket_allocator, node_allocator> allocators_;
|
||||
compressed_pair<bucket_allocator, node_allocator> allocators_;
|
||||
|
||||
// Data access
|
||||
|
||||
@ -106,22 +106,20 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Need to move allocators_, not copy. But compressed_pair
|
||||
// doesn't support move parameters.
|
||||
buckets(buckets& b, move_tag)
|
||||
buckets(buckets& b, move_tag m)
|
||||
: buckets_(),
|
||||
bucket_count_(b.bucket_count_),
|
||||
size_(),
|
||||
allocators_(b.allocators_)
|
||||
allocators_(b.allocators_, m)
|
||||
{
|
||||
swap(b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
buckets(table<T>& x, move_tag)
|
||||
buckets(table<T>& x, move_tag m)
|
||||
: buckets_(),
|
||||
bucket_count_(x.bucket_count_),
|
||||
allocators_(x.allocators_)
|
||||
allocators_(x.allocators_, m)
|
||||
{
|
||||
swap(x);
|
||||
x.size_ = 0;
|
||||
@ -424,7 +422,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
friend class set_hash_functions<H, P>;
|
||||
functions& operator=(functions const&);
|
||||
|
||||
typedef ::boost::compressed_pair<H, P> function_pair;
|
||||
typedef compressed_pair<H, P> function_pair;
|
||||
typedef BOOST_DEDUCED_TYPENAME ::boost::aligned_storage<
|
||||
sizeof(function_pair),
|
||||
::boost::alignment_of<function_pair>::value>::type aligned_function;
|
||||
|
@ -245,7 +245,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// aren't deleted with the wrong allocator.
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
// TODO: Can allocator assignment throw?
|
||||
this->allocators_ = x.allocators_;
|
||||
this->allocators_.assign(x.allocators_);
|
||||
this->swap(tmp, false_type());
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
void move_assign(table& x, true_type)
|
||||
{
|
||||
if(this->buckets_) this->delete_buckets();
|
||||
this->allocators_ = x.allocators_; // TODO: Move allocators, not copy.
|
||||
this->allocators_.move_assign(x.allocators_);
|
||||
move_assign_no_alloc(x);
|
||||
}
|
||||
|
||||
|
@ -19,16 +19,17 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/compressed_pair.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
|
||||
// Template parameters:
|
||||
//
|
||||
@ -253,6 +254,102 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
|
||||
num_buckets);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// compressed_pair
|
||||
|
||||
template <typename T, int Index>
|
||||
struct compressed_base : private T
|
||||
{
|
||||
compressed_base(T const& x) : T(x) {}
|
||||
compressed_base(T& x, move_tag) : T(boost::move(x)) {}
|
||||
|
||||
T& get() { return *this; }
|
||||
T const& get() const { return *this; }
|
||||
};
|
||||
|
||||
template <typename T, int Index>
|
||||
struct uncompressed_base
|
||||
{
|
||||
uncompressed_base(T const& x) : value_(x) {}
|
||||
uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
|
||||
|
||||
T& get() { return value_; }
|
||||
T const& get() const { return value_; }
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
template <typename T, int Index>
|
||||
struct generate_base
|
||||
: boost::detail::if_true<
|
||||
boost::is_empty<T>::value
|
||||
>:: BOOST_NESTED_TEMPLATE then<
|
||||
compressed_base<T, Index>,
|
||||
uncompressed_base<T, Index>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct compressed_pair
|
||||
: private generate_base<T1, 1>::type,
|
||||
private generate_base<T2, 2>::type
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME generate_base<T1, 1>::type base1;
|
||||
typedef BOOST_DEDUCED_TYPENAME generate_base<T2, 2>::type base2;
|
||||
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
first_type& first() {
|
||||
return static_cast<base1*>(this)->get();
|
||||
}
|
||||
|
||||
first_type const& first() const {
|
||||
return static_cast<base1 const*>(this)->get();
|
||||
}
|
||||
|
||||
second_type& second() {
|
||||
return static_cast<base2*>(this)->get();
|
||||
}
|
||||
|
||||
second_type const& second() const {
|
||||
return static_cast<base2 const*>(this)->get();
|
||||
}
|
||||
|
||||
template <typename First, typename Second>
|
||||
compressed_pair(First const& x1, Second const& x2)
|
||||
: base1(x1), base2(x2) {}
|
||||
|
||||
compressed_pair(compressed_pair const& x)
|
||||
: base1(x.first()), base2(x.second()) {}
|
||||
|
||||
compressed_pair(compressed_pair& x, move_tag m)
|
||||
: base1(x.first(), m), base2(x.second(), m) {}
|
||||
|
||||
void assign(compressed_pair const& x)
|
||||
{
|
||||
first() = x.first();
|
||||
second() = x.second();
|
||||
}
|
||||
|
||||
void move_assign(compressed_pair& x)
|
||||
{
|
||||
first() = boost::move(x.first());
|
||||
second() = boost::move(x.second());
|
||||
}
|
||||
|
||||
void swap(compressed_pair& x)
|
||||
{
|
||||
boost::swap(first(), x.first());
|
||||
boost::swap(second(), x.second());
|
||||
}
|
||||
|
||||
private:
|
||||
// Prevent assignment just to make use of assign or
|
||||
// move_assign explicit.
|
||||
compressed_pair& operator=(compressed_pair const&);
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user