diff options
author | Remko Tronçon <git@el-tramo.be> | 2012-12-23 13:16:26 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-12-23 14:43:26 (GMT) |
commit | 491ddd570a752cf9bda85933bed0c6942e39b1f9 (patch) | |
tree | 10c25c1be8cc08d0497df1dccd56a10fbb30beee /3rdParty/Boost/src/boost/unordered/detail/buckets.hpp | |
parent | da7d7a0ca71b80281aa9ff2526290b61ccb0cc60 (diff) | |
download | swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.zip swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.tar.bz2 |
Update Boost to 1.52.0.
Change-Id: I1e56bea2600bf2ed9c5b3aba8c4f9d2a0f350e77
Diffstat (limited to '3rdParty/Boost/src/boost/unordered/detail/buckets.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/unordered/detail/buckets.hpp | 882 |
1 files changed, 749 insertions, 133 deletions
diff --git a/3rdParty/Boost/src/boost/unordered/detail/buckets.hpp b/3rdParty/Boost/src/boost/unordered/detail/buckets.hpp index 913dbcd..def5c7c 100644 --- a/3rdParty/Boost/src/boost/unordered/detail/buckets.hpp +++ b/3rdParty/Boost/src/boost/unordered/detail/buckets.hpp @@ -1,183 +1,799 @@ // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. -// Copyright (C) 2005-2009 Daniel James +// Copyright (C) 2005-2011 Daniel James // 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) #ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED #define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED -#include <boost/config.hpp> -#include <boost/assert.hpp> -#include <boost/unordered/detail/node.hpp> +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + #include <boost/unordered/detail/util.hpp> +#include <boost/unordered/detail/allocate.hpp> +#include <boost/type_traits/aligned_storage.hpp> +#include <boost/type_traits/alignment_of.hpp> +#include <boost/swap.hpp> +#include <boost/assert.hpp> +#include <boost/limits.hpp> +#include <boost/iterator.hpp> + +namespace boost { namespace unordered { namespace detail { + + template <typename Types> struct table; + template <typename NodePointer> struct bucket; + struct ptr_bucket; + template <typename Types> struct table_impl; + template <typename Types> struct grouped_table_impl; + +}}} + +namespace boost { namespace unordered { namespace iterator_detail { -namespace boost { namespace unordered_detail { - //////////////////////////////////////////////////////////////////////////// - // Buckets - - template <class A, class G> - inline std::size_t hash_buckets<A, G>::max_bucket_count() const { - // -1 to account for the sentinel. - return prev_prime(this->bucket_alloc().max_size() - 1); - } + // Iterators + // + // all no throw - template <class A, class G> - inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr - hash_buckets<A, G>::get_bucket(std::size_t num) const + template <typename NodePointer, typename Value> struct iterator; + template <typename ConstNodePointer, typename NodePointer, + typename Value> struct c_iterator; + template <typename NodePointer, typename Value, typename Policy> + struct l_iterator; + template <typename ConstNodePointer, typename NodePointer, + typename Value, typename Policy> struct cl_iterator; + + // Local Iterators + // + // all no throw + + template <typename NodePointer, typename Value, typename Policy> + struct l_iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + NodePointer, Value&> { - return buckets_ + static_cast<std::ptrdiff_t>(num); - } +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template <typename ConstNodePointer, typename NodePointer2, + typename Value2, typename Policy2> + friend struct boost::unordered::iterator_detail::cl_iterator; + private: +#endif + typedef NodePointer node_pointer; + typedef boost::unordered::iterator_detail::iterator<NodePointer, Value> + iterator; + node_pointer ptr_; + std::size_t bucket_; + std::size_t bucket_count_; + + public: + + l_iterator() : ptr_() {} + + l_iterator(iterator x, std::size_t b, std::size_t c) + : ptr_(x.node_), bucket_(b), bucket_count_(c) {} - template <class A, class G> - inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr - hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const + Value& operator*() const { + return ptr_->value(); + } + + Value* operator->() const { + return ptr_->value_ptr(); + } + + l_iterator& operator++() { + ptr_ = static_cast<node_pointer>(ptr_->next_); + if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) + != bucket_) + ptr_ = node_pointer(); + return *this; + } + + l_iterator operator++(int) { + l_iterator tmp(*this); + ++(*this); + return tmp; + } + + bool operator==(l_iterator x) const { + return ptr_ == x.ptr_; + } + + bool operator!=(l_iterator x) const { + return ptr_ != x.ptr_; + } + }; + + template <typename ConstNodePointer, typename NodePointer, typename Value, + typename Policy> + struct cl_iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + ConstNodePointer, Value const&> { - return get_bucket(hashed % bucket_count_); - } - - template <class A, class G> - std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const + friend struct boost::unordered::iterator_detail::l_iterator + <NodePointer, Value, Policy>; + private: + + typedef NodePointer node_pointer; + typedef boost::unordered::iterator_detail::iterator<NodePointer, Value> + iterator; + node_pointer ptr_; + std::size_t bucket_; + std::size_t bucket_count_; + + public: + + cl_iterator() : ptr_() {} + + cl_iterator(iterator x, std::size_t b, std::size_t c) : + ptr_(x.node_), bucket_(b), bucket_count_(c) {} + + cl_iterator(boost::unordered::iterator_detail::l_iterator< + NodePointer, Value, Policy> const& x) : + ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) + {} + + Value const& + operator*() const { + return ptr_->value(); + } + + Value const* operator->() const { + return ptr_->value_ptr(); + } + + cl_iterator& operator++() { + ptr_ = static_cast<node_pointer>(ptr_->next_); + if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) + != bucket_) + ptr_ = node_pointer(); + return *this; + } + + cl_iterator operator++(int) { + cl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(cl_iterator const& x, cl_iterator const& y) { + return x.ptr_ == y.ptr_; + } + + friend bool operator!=(cl_iterator const& x, cl_iterator const& y) { + return x.ptr_ != y.ptr_; + } + }; + + template <typename NodePointer, typename Value> + struct iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + NodePointer, Value&> { - if(!buckets_) return 0; - bucket_ptr ptr = get_bucket(index)->next_; - std::size_t count = 0; - while(ptr) { - ++count; - ptr = ptr->next_; - } - return count; - } +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template <typename, typename, typename> + friend struct boost::unordered::iterator_detail::c_iterator; + template <typename, typename, typename> + friend struct boost::unordered::iterator_detail::l_iterator; + template <typename, typename, typename, typename> + friend struct boost::unordered::iterator_detail::cl_iterator; + template <typename> + friend struct boost::unordered::detail::table; + template <typename> + friend struct boost::unordered::detail::table_impl; + template <typename> + friend struct boost::unordered::detail::grouped_table_impl; + private: +#endif + typedef NodePointer node_pointer; + node_pointer node_; + + public: - template <class A, class G> - inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr - hash_buckets<A, G>::bucket_begin(std::size_t num) const + iterator() : node_() {} + + explicit iterator(node_pointer const& x) : node_(x) {} + + Value& operator*() const { + return node_->value(); + } + + Value* operator->() const { + return &node_->value(); + } + + iterator& operator++() { + node_ = static_cast<node_pointer>(node_->next_); + return *this; + } + + iterator operator++(int) { + iterator tmp(node_); + node_ = static_cast<node_pointer>(node_->next_); + return tmp; + } + + bool operator==(iterator const& x) const { + return node_ == x.node_; + } + + bool operator!=(iterator const& x) const { + return node_ != x.node_; + } + }; + + template <typename ConstNodePointer, typename NodePointer, typename Value> + struct c_iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + ConstNodePointer, Value const&> { - return buckets_ ? get_bucket(num)->next_ : node_ptr(); - } + friend struct boost::unordered::iterator_detail::iterator< + NodePointer, Value>; - //////////////////////////////////////////////////////////////////////////// - // Delete +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template <typename> + friend struct boost::unordered::detail::table; + template <typename> + friend struct boost::unordered::detail::table_impl; + template <typename> + friend struct boost::unordered::detail::grouped_table_impl; + + private: +#endif + + typedef NodePointer node_pointer; + typedef boost::unordered::iterator_detail::iterator<NodePointer, Value> + iterator; + node_pointer node_; + + public: + + c_iterator() : node_() {} + + explicit c_iterator(node_pointer const& x) : node_(x) {} + + c_iterator(boost::unordered::iterator_detail::iterator< + NodePointer, Value> const& x) : node_(x.node_) {} + + Value const& operator*() const { + return node_->value(); + } + + Value const* operator->() const { + return &node_->value(); + } + + c_iterator& operator++() { + node_ = static_cast<node_pointer>(node_->next_); + return *this; + } + + c_iterator operator++(int) { + c_iterator tmp(node_); + node_ = static_cast<node_pointer>(node_->next_); + return tmp; + } + + friend bool operator==(c_iterator const& x, c_iterator const& y) { + return x.node_ == y.node_; + } + + friend bool operator!=(c_iterator const& x, c_iterator const& y) { + return x.node_ != y.node_; + } + }; +}}} + +namespace boost { namespace unordered { namespace detail { + + /////////////////////////////////////////////////////////////////// + // + // Node construction + + template <typename NodeAlloc> + struct node_constructor + { + private: + + typedef NodeAlloc node_allocator; + typedef boost::unordered::detail::allocator_traits<NodeAlloc> + node_allocator_traits; + typedef typename node_allocator_traits::value_type node; + typedef typename node_allocator_traits::pointer node_pointer; + typedef typename node::value_type value_type; + + protected: + + node_allocator& alloc_; + + private: + + node_pointer node_; + bool node_constructed_; + bool value_constructed_; + + public: + + node_constructor(node_allocator& n) : + alloc_(n), + node_(), + node_constructed_(false), + value_constructed_(false) + { + } + + ~node_constructor(); + + void construct(); + + template <BOOST_UNORDERED_EMPLACE_TEMPLATE> + void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS) + { + construct(); + boost::unordered::detail::construct_value_impl( + alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); + value_constructed_ = true; + } + + template <typename A0> + void construct_with_value2(BOOST_FWD_REF(A0) a0) + { + construct(); + boost::unordered::detail::construct_value_impl( + alloc_, node_->value_ptr(), + BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0))); + value_constructed_ = true; + } - template <class A, class G> - inline void hash_buckets<A, G>::delete_node(node_ptr b) + value_type const& value() const { + BOOST_ASSERT(node_ && node_constructed_ && value_constructed_); + return node_->value(); + } + + // no throw + node_pointer release() + { + BOOST_ASSERT(node_ && node_constructed_); + node_pointer p = node_; + node_ = node_pointer(); + return p; + } + + private: + node_constructor(node_constructor const&); + node_constructor& operator=(node_constructor const&); + }; + + template <typename Alloc> + node_constructor<Alloc>::~node_constructor() { - node* raw_ptr = static_cast<node*>(&*b); - boost::unordered_detail::destroy(raw_ptr->value_ptr()); - real_node_ptr n(node_alloc().address(*raw_ptr)); - node_alloc().destroy(n); - node_alloc().deallocate(n, 1); + if (node_) { + if (value_constructed_) { + boost::unordered::detail::destroy_value_impl(alloc_, + node_->value_ptr()); + } + + if (node_constructed_) { + node_allocator_traits::destroy(alloc_, + boost::addressof(*node_)); + } + + node_allocator_traits::deallocate(alloc_, node_, 1); + } } - template <class A, class G> - inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b) + template <typename Alloc> + void node_constructor<Alloc>::construct() { - node_ptr node_it = b->next_; - b->next_ = node_ptr(); + if(!node_) { + node_constructed_ = false; + value_constructed_ = false; + + node_ = node_allocator_traits::allocate(alloc_, 1); + + node_allocator_traits::construct(alloc_, + boost::addressof(*node_), node()); + node_->init(static_cast<typename node::link_pointer>(node_)); + node_constructed_ = true; + } + else { + BOOST_ASSERT(node_constructed_); - while(node_it) { - node_ptr node_to_delete = node_it; - node_it = node_it->next_; - delete_node(node_to_delete); + if (value_constructed_) + { + boost::unordered::detail::destroy_value_impl(alloc_, + node_->value_ptr()); + value_constructed_ = false; + } } } - template <class A, class G> - inline void hash_buckets<A, G>::delete_buckets() - { - bucket_ptr end = this->get_bucket(this->bucket_count_); + /////////////////////////////////////////////////////////////////// + // + // Node Holder + // + // Temporary store for nodes. Deletes any that aren't used. + + template <typename NodeAlloc> + struct node_holder : private node_constructor<NodeAlloc> + { + private: + typedef node_constructor<NodeAlloc> base; + + typedef NodeAlloc node_allocator; + typedef boost::unordered::detail::allocator_traits<NodeAlloc> + node_allocator_traits; + typedef typename node_allocator_traits::value_type node; + typedef typename node_allocator_traits::pointer node_pointer; + typedef typename node::value_type value_type; + typedef typename node::link_pointer link_pointer; + typedef boost::unordered::iterator_detail:: + iterator<node_pointer, value_type> iterator; - for(bucket_ptr begin = this->buckets_; begin != end; ++begin) { - clear_bucket(begin); + node_pointer nodes_; + + public: + + template <typename Table> + explicit node_holder(Table& b) : + base(b.node_alloc()), + nodes_() + { + if (b.size_) { + typename Table::previous_pointer prev = b.get_previous_start(); + nodes_ = static_cast<node_pointer>(prev->next_); + prev->next_ = link_pointer(); + b.size_ = 0; + } } - // Destroy the buckets (including the sentinel bucket). - ++end; - for(bucket_ptr begin = this->buckets_; begin != end; ++begin) { - bucket_alloc().destroy(begin); + ~node_holder(); + + template <typename T> + inline void assign_impl(T const& v) { + nodes_->value() = v; } - bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1); + template <typename T1, typename T2> + inline void assign_impl(std::pair<T1 const, T2> const& v) { + const_cast<T1&>(nodes_->value().first) = v.first; + nodes_->value().second = v.second; + } - this->buckets_ = bucket_ptr(); - } + template <typename T> + inline void move_assign_impl(T& v) { + nodes_->value() = boost::move(v); + } - template <class A, class G> - inline std::size_t hash_buckets<A, G>::delete_nodes( - node_ptr begin, node_ptr end) + template <typename T1, typename T2> + inline void move_assign_impl(std::pair<T1 const, T2>& v) { + // TODO: Move key as well? + const_cast<T1&>(nodes_->value().first) = + boost::move(const_cast<T1&>(v.first)); + nodes_->value().second = boost::move(v.second); + } + + node_pointer copy_of(value_type const& v) + { + if (nodes_) { + assign_impl(v); + node_pointer p = nodes_; + nodes_ = static_cast<node_pointer>(p->next_); + p->init(static_cast<typename node::link_pointer>(p)); + p->next_ = link_pointer(); + return p; + } + else { + this->construct_with_value2(v); + return base::release(); + } + } + + node_pointer move_copy_of(value_type& v) + { + if (nodes_) { + move_assign_impl(v); + node_pointer p = nodes_; + nodes_ = static_cast<node_pointer>(p->next_); + p->init(static_cast<typename node::link_pointer>(p)); + p->next_ = link_pointer(); + return p; + } + else { + this->construct_with_value2(boost::move(v)); + return base::release(); + } + } + + iterator begin() const + { + return iterator(nodes_); + } + }; + + template <typename Alloc> + node_holder<Alloc>::~node_holder() { - std::size_t count = 0; - while(begin != end) { - node_ptr n = begin; - begin = begin->next_; - delete_node(n); - ++count; - } - return count; + while (nodes_) { + node_pointer p = nodes_; + nodes_ = static_cast<node_pointer>(p->next_); + + boost::unordered::detail::destroy_value_impl(this->alloc_, + p->value_ptr()); + node_allocator_traits::destroy(this->alloc_, boost::addressof(*p)); + node_allocator_traits::deallocate(this->alloc_, p, 1); + } } - //////////////////////////////////////////////////////////////////////////// - // Constructors and Destructors - - template <class A, class G> - inline hash_buckets<A, G>::hash_buckets( - node_allocator const& a, std::size_t bucket_count) - : buckets_(), - bucket_count_(bucket_count), - allocators_(a,a) + /////////////////////////////////////////////////////////////////// + // + // Bucket + + template <typename NodePointer> + struct bucket { - } + typedef NodePointer previous_pointer; + previous_pointer next_; + + bucket() : next_() {} - template <class A, class G> - inline hash_buckets<A, G>::~hash_buckets() + previous_pointer first_from_start() + { + return next_; + } + + enum { extra_node = true }; + }; + + struct ptr_bucket { - if(this->buckets_) { this->delete_buckets(); } - } - - template <class A, class G> - inline void hash_buckets<A, G>::create_buckets() + typedef ptr_bucket* previous_pointer; + previous_pointer next_; + + ptr_bucket() : next_(0) {} + + previous_pointer first_from_start() + { + return this; + } + + enum { extra_node = false }; + }; + + /////////////////////////////////////////////////////////////////// + // + // Hash Policy + // + // Don't really want table to derive from this, but will for now. + + template <typename SizeT> + struct prime_policy { - // The array constructor will clean up in the event of an - // exception. - allocator_array_constructor<bucket_allocator> - constructor(bucket_alloc()); - - // Creates an extra bucket to act as a sentinel. - constructor.construct(bucket(), this->bucket_count_ + 1); - - // Set up the sentinel (node_ptr cast) - bucket_ptr sentinel = constructor.get() + - static_cast<std::ptrdiff_t>(this->bucket_count_); - sentinel->next_ = sentinel; - - // Only release the buckets once everything is successfully - // done. - this->buckets_ = constructor.release(); - } + template <typename Hash, typename T> + static inline SizeT apply_hash(Hash const& hf, T const& x) { + return hf(x); + } + + static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { + return hash % bucket_count; + } + + static inline SizeT new_bucket_count(SizeT min) { + return boost::unordered::detail::next_prime(min); + } + + static inline SizeT prev_bucket_count(SizeT max) { + return boost::unordered::detail::prev_prime(max); + } + }; + + template <typename SizeT> + struct mix64_policy + { + template <typename Hash, typename T> + static inline SizeT apply_hash(Hash const& hf, T const& x) { + SizeT key = hf(x); + key = (~key) + (key << 21); // key = (key << 21) - key - 1; + key = key ^ (key >> 24); + key = (key + (key << 3)) + (key << 8); // key * 265 + key = key ^ (key >> 14); + key = (key + (key << 2)) + (key << 4); // key * 21 + key = key ^ (key >> 28); + key = key + (key << 31); + return key; + } + + static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { + return hash & (bucket_count - 1); + } + + static inline SizeT new_bucket_count(SizeT min) { + if (min <= 4) return 4; + --min; + min |= min >> 1; + min |= min >> 2; + min |= min >> 4; + min |= min >> 8; + min |= min >> 16; + min |= min >> 32; + return min + 1; + } + + static inline SizeT prev_bucket_count(SizeT max) { + max |= max >> 1; + max |= max >> 2; + max |= max >> 4; + max |= max >> 8; + max |= max >> 16; + max |= max >> 32; + return (max >> 1) + 1; + } + }; + + template <int digits, int radix> + struct pick_policy_impl { + typedef prime_policy<std::size_t> type; + }; + + template <> + struct pick_policy_impl<64, 2> { + typedef mix64_policy<std::size_t> type; + }; + + struct pick_policy : + pick_policy_impl< + std::numeric_limits<std::size_t>::digits, + std::numeric_limits<std::size_t>::radix> {}; //////////////////////////////////////////////////////////////////////////// - // Constructors and Destructors + // Functions + + // Assigning and swapping the equality and hash function objects + // needs strong exception safety. To implement that normally we'd + // require one of them to be known to not throw and the other to + // guarantee strong exception safety. Unfortunately they both only + // have basic exception safety. So to acheive strong exception + // safety we have storage space for two copies, and assign the new + // copies to the unused space. Then switch to using that to use + // them. This is implemented in 'set_hash_functions' which + // atomically assigns the new function objects in a strongly + // exception safe manner. + + template <class H, class P> class set_hash_functions; - // no throw - template <class A, class G> - inline void hash_buckets<A, G>::move(hash_buckets& other) + template <class H, class P> + class functions { - BOOST_ASSERT(node_alloc() == other.node_alloc()); - if(this->buckets_) { this->delete_buckets(); } - this->buckets_ = other.buckets_; - this->bucket_count_ = other.bucket_count_; - other.buckets_ = bucket_ptr(); - other.bucket_count_ = 0; - } + friend class boost::unordered::detail::set_hash_functions<H, P>; + functions& operator=(functions const&); + + typedef compressed<H, P> function_pair; + + typedef typename boost::aligned_storage< + sizeof(function_pair), + boost::alignment_of<function_pair>::value>::type aligned_function; + + bool current_; // The currently active functions. + aligned_function funcs_[2]; + + function_pair const& current() const { + return *static_cast<function_pair const*>( + static_cast<void const*>(&funcs_[current_])); + } + + void construct(bool which, H const& hf, P const& eq) + { + new((void*) &funcs_[which]) function_pair(hf, eq); + } + + void construct(bool which, function_pair const& f) + { + new((void*) &funcs_[which]) function_pair(f); + } + + void destroy(bool which) + { + boost::unordered::detail::destroy((function_pair*)(&funcs_[which])); + } + + public: + + functions(H const& hf, P const& eq) + : current_(false) + { + construct(current_, hf, eq); + } - template <class A, class G> - inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other) + functions(functions const& bf) + : current_(false) + { + construct(current_, bf.current()); + } + + ~functions() { + this->destroy(current_); + } + + H const& hash_function() const { + return current().first(); + } + + P const& key_eq() const { + return current().second(); + } + }; + + template <class H, class P> + class set_hash_functions { - BOOST_ASSERT(node_alloc() == other.node_alloc()); - std::swap(buckets_, other.buckets_); - std::swap(bucket_count_, other.bucket_count_); - } -}} + set_hash_functions(set_hash_functions const&); + set_hash_functions& operator=(set_hash_functions const&); + + functions<H,P>& functions_; + bool tmp_functions_; + + public: + + set_hash_functions(functions<H,P>& f, H const& h, P const& p) + : functions_(f), + tmp_functions_(!f.current_) + { + f.construct(tmp_functions_, h, p); + } + + set_hash_functions(functions<H,P>& f, functions<H,P> const& other) + : functions_(f), + tmp_functions_(!f.current_) + { + f.construct(tmp_functions_, other.current()); + } + + ~set_hash_functions() + { + functions_.destroy(tmp_functions_); + } + + void commit() + { + functions_.current_ = tmp_functions_; + tmp_functions_ = !tmp_functions_; + } + }; + + //////////////////////////////////////////////////////////////////////////// + // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter + // e.g. for int + +#if !defined(BOOST_NO_RVALUE_REFERENCES) +# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T) +#else + struct please_ignore_this_overload { + typedef please_ignore_this_overload type; + }; + + template <typename T> + struct rv_ref_impl { + typedef BOOST_RV_REF(T) type; + }; + + template <typename T> + struct rv_ref : + boost::detail::if_true< + boost::is_class<T>::value + >::BOOST_NESTED_TEMPLATE then < + boost::unordered::detail::rv_ref_impl<T>, + please_ignore_this_overload + >::type + {}; + +# define BOOST_UNORDERED_RV_REF(T) \ + typename boost::unordered::detail::rv_ref<T>::type +#endif +}}} #endif |