From 08bca9a35f41af44020b171a9208d2f746cae944 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 15 Aug 2011 21:34:01 +0000 Subject: [PATCH] Unordered: Support moving allocators. [SVN r73805] --- include/boost/unordered/detail/buckets.hpp | 14 ++- include/boost/unordered/detail/table.hpp | 4 +- include/boost/unordered/detail/util.hpp | 99 +++++++++++++++++++++- 3 files changed, 106 insertions(+), 11 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index df79ccf6..830c53c9 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -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 allocators_; + compressed_pair 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 - buckets(table& x, move_tag) + buckets(table& 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; functions& operator=(functions const&); - typedef ::boost::compressed_pair function_pair; + typedef compressed_pair function_pair; typedef BOOST_DEDUCED_TYPENAME ::boost::aligned_storage< sizeof(function_pair), ::boost::alignment_of::value>::type aligned_function; diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index fa8d4521..86051d99 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -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); } diff --git a/include/boost/unordered/detail/util.hpp b/include/boost/unordered/detail/util.hpp index 81093783..d944a415 100644 --- a/include/boost/unordered/detail/util.hpp +++ b/include/boost/unordered/detail/util.hpp @@ -19,16 +19,17 @@ #include #include #include -#include #include #include #include +#include #include #include #include #include #include #include +#include // Template parameters: // @@ -253,6 +254,102 @@ namespace boost { namespace unordered { namespace detail { return (std::max)(static_cast(insert_size(i, j)) + 1, num_buckets); } + + //////////////////////////////////////////////////////////////////////////// + // compressed_pair + + template + 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 + 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 + struct generate_base + : boost::detail::if_true< + boost::is_empty::value + >:: BOOST_NESTED_TEMPLATE then< + compressed_base, + uncompressed_base + > + {}; + + template + struct compressed_pair + : private generate_base::type, + private generate_base::type + { + typedef BOOST_DEDUCED_TYPENAME generate_base::type base1; + typedef BOOST_DEDUCED_TYPENAME generate_base::type base2; + + typedef T1 first_type; + typedef T2 second_type; + + first_type& first() { + return static_cast(this)->get(); + } + + first_type const& first() const { + return static_cast(this)->get(); + } + + second_type& second() { + return static_cast(this)->get(); + } + + second_type const& second() const { + return static_cast(this)->get(); + } + + template + 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