Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / intrusive / unordered_set.hpp
index a06d74b..e47f3ba 100644 (file)
@@ -1,7 +1,7 @@
 /////////////////////////////////////////////////////////////////////////////
 //
 // (C) Copyright Olaf Krzikalla 2004-2006.
-// (C) Copyright Ion Gaztanaga  2006-2012
+// (C) Copyright Ion Gaztanaga  2006-2014
 //
 // Distributed under the Boost Software License, Version 1.0.
 //    (See accompanying file LICENSE_1_0.txt or copy at
 #ifndef BOOST_INTRUSIVE_UNORDERED_SET_HPP
 #define BOOST_INTRUSIVE_UNORDERED_SET_HPP
 
+#if defined(_MSC_VER)
+#  pragma once
+#endif
+
 #include <boost/intrusive/detail/config_begin.hpp>
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <boost/intrusive/hashtable.hpp>
-#include <boost/move/move.hpp>
-#include <iterator>
-
+#include <boost/move/utility_core.hpp>
+#include <boost/static_assert.hpp>
 
 namespace boost {
 namespace intrusive {
@@ -61,13 +64,14 @@ namespace intrusive {
 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
 template<class T, class ...Options>
 #else
-template<class Config>
+template<class ValueTraits, class Hash, class Equal, class SizeType, class BucketTraits, std::size_t BoolFlags>
 #endif
 class unordered_set_impl
+   : public hashtable_impl<ValueTraits, Hash, Equal, SizeType, BucketTraits, BoolFlags>
 {
    /// @cond
    private:
-   typedef hashtable_impl<Config> table_type;
+   typedef hashtable_impl<ValueTraits, Hash, Equal, SizeType, BucketTraits, BoolFlags> table_type;
 
    //! This class is
    //! movable
@@ -102,11 +106,6 @@ class unordered_set_impl
    typedef typename implementation_defined::const_node_ptr              const_node_ptr;
    typedef typename implementation_defined::node_algorithms             node_algorithms;
 
-   /// @cond
-   private:
-   table_type table_;
-   /// @endcond
-
    public:
 
    //! <b>Requires</b>: buckets must not be being used by any other resource.
@@ -122,11 +121,11 @@ class unordered_set_impl
    //!
    //! <b>Notes</b>: buckets array must be disposed only after
    //!   *this is disposed.
-   unordered_set_impl( const bucket_traits &b_traits
-                     , const hasher & hash_func = hasher()
-                     , const key_equal &equal_func = key_equal()
-                     , const value_traits &v_traits = value_traits())
-      :  table_(b_traits, hash_func, equal_func, v_traits)
+   explicit unordered_set_impl( const bucket_traits &b_traits
+                              , const hasher & hash_func = hasher()
+                              , const key_equal &equal_func = key_equal()
+                              , const value_traits &v_traits = value_traits())
+      :  table_type(b_traits, hash_func, equal_func, v_traits)
    {}
 
    //! <b>Requires</b>: buckets must not be being used by any other resource
@@ -151,20 +150,21 @@ class unordered_set_impl
                      , const hasher & hash_func = hasher()
                      , const key_equal &equal_func = key_equal()
                      , const value_traits &v_traits = value_traits())
-      :  table_(b_traits, hash_func, equal_func, v_traits)
-   {  table_.insert_unique(b, e);  }
+      :  table_type(b_traits, hash_func, equal_func, v_traits)
+   {  table_type::insert_unique(b, e);  }
 
    //! <b>Effects</b>: to-do
    //!
    unordered_set_impl(BOOST_RV_REF(unordered_set_impl) x)
-      :  table_(::boost::move(x.table_))
+      :  table_type(::boost::move(static_cast<table_type&>(x)))
    {}
 
    //! <b>Effects</b>: to-do
    //!
    unordered_set_impl& operator=(BOOST_RV_REF(unordered_set_impl) x)
-   {  table_ = ::boost::move(x.table_);  return *this;  }
+   {  return static_cast<unordered_set_impl&>(table_type::operator=(::boost::move(static_cast<table_type&>(x)))); }
 
+   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
    //! <b>Effects</b>: Detaches all elements from this. The objects in the unordered_set
    //!   are not deleted (i.e. no destructors are called).
    //!
@@ -182,7 +182,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    iterator begin()
-   { return table_.begin();  }
+   { return table_type::begin();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //!   of the unordered_set.
@@ -192,7 +192,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator begin() const
-   { return table_.begin();  }
+   { return table_type::begin();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //!   of the unordered_set.
@@ -202,7 +202,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cbegin() const
-   { return table_.cbegin();  }
+   { return table_type::cbegin();  }
 
    //! <b>Effects</b>: Returns an iterator pointing to the end of the unordered_set.
    //!
@@ -210,7 +210,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    iterator end()
-   { return table_.end();  }
+   { return table_type::end();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the end of the unordered_set.
    //!
@@ -218,7 +218,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator end() const
-   { return table_.end();  }
+   { return table_type::end();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the end of the unordered_set.
    //!
@@ -226,7 +226,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cend() const
-   { return table_.cend();  }
+   { return table_type::cend();  }
 
    //! <b>Effects</b>: Returns the hasher object used by the unordered_set.
    //!
@@ -234,7 +234,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If hasher copy-constructor throws.
    hasher hash_function() const
-   { return table_.hash_function(); }
+   { return table_type::hash_function(); }
 
    //! <b>Effects</b>: Returns the key_equal object used by the unordered_set.
    //!
@@ -242,7 +242,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If key_equal copy-constructor throws.
    key_equal key_eq() const
-   { return table_.key_eq(); }
+   { return table_type::key_eq(); }
 
    //! <b>Effects</b>: Returns true if the container is empty.
    //!
@@ -252,7 +252,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    bool empty() const
-   { return table_.empty(); }
+   { return table_type::empty(); }
 
    //! <b>Effects</b>: Returns the number of elements stored in the unordered_set.
    //!
@@ -261,7 +261,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    size_type size() const
-   { return table_.size(); }
+   { return table_type::size(); }
 
    //! <b>Requires</b>: the hasher and the equality function unqualified swap
    //!   call should not throw.
@@ -274,7 +274,7 @@ class unordered_set_impl
    //! <b>Throws</b>: If the swap() call for the comparison or hash functors
    //!   found using ADL throw. Basic guarantee.
    void swap(unordered_set_impl& other)
-   { table_.swap(other.table_); }
+   { table_type::swap(other.table_); }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!   Cloner should yield to nodes that compare equal and produce the same
@@ -297,7 +297,9 @@ class unordered_set_impl
    //!   throws. Basic guarantee.
    template <class Cloner, class Disposer>
    void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer)
-   {  table_.clone_from(src.table_, cloner, disposer);  }
+   {  table_type::clone_from(src.table_, cloner, disposer);  }
+
+   #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 
    //! <b>Requires</b>: value must be an lvalue
    //!
@@ -316,7 +318,7 @@ class unordered_set_impl
    //! <b>Note</b>: Does not affect the validity of iterators and references.
    //!   No copy-constructors are called.
    std::pair<iterator, bool> insert(reference value)
-   {  return table_.insert_unique(value);  }
+   {  return table_type::insert_unique(value);  }
 
    //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
    //!   of type value_type.
@@ -332,7 +334,7 @@ class unordered_set_impl
    //!   No copy-constructors are called.
    template<class Iterator>
    void insert(Iterator b, Iterator e)
-   {  table_.insert_unique(b, e);  }
+   {  table_type::insert_unique(b, e);  }
 
    //! <b>Requires</b>: "hasher" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -372,7 +374,7 @@ class unordered_set_impl
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    std::pair<iterator, bool> insert_check
       (const KeyType &key, KeyHasher hasher, KeyValueEqual key_value_equal, insert_commit_data &commit_data)
-   {  return table_.insert_unique_check(key, hasher, key_value_equal, commit_data); }
+   {  return table_type::insert_unique_check(key, hasher, key_value_equal, commit_data); }
 
    //! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
    //!   must have been obtained from a previous call to "insert_check".
@@ -394,7 +396,9 @@ class unordered_set_impl
    //!
    //!   After a successful rehashing insert_commit_data remains valid.
    iterator insert_commit(reference value, const insert_commit_data &commit_data)
-   {  return table_.insert_unique_commit(value, commit_data); }
+   {  return table_type::insert_unique_commit(value, commit_data); }
+
+   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 
    //! <b>Effects</b>: Erases the element pointed to by i.
    //!
@@ -405,7 +409,7 @@ class unordered_set_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased element. No destructors are called.
    void erase(const_iterator i)
-   {  table_.erase(i);  }
+   {  table_type::erase(i);  }
 
    //! <b>Effects</b>: Erases the range pointed to by b end e.
    //!
@@ -417,7 +421,7 @@ class unordered_set_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased elements. No destructors are called.
    void erase(const_iterator b, const_iterator e)
-   {  table_.erase(b, e);  }
+   {  table_type::erase(b, e);  }
 
    //! <b>Effects</b>: Erases all the elements with the given value.
    //!
@@ -431,7 +435,7 @@ class unordered_set_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased elements. No destructors are called.
    size_type erase(const_reference value)
-   {  return table_.erase(value);  }
+   {  return table_type::erase(value);  }
 
    //! <b>Requires</b>: "hasher" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -455,7 +459,7 @@ class unordered_set_impl
    //!    to the erased elements. No destructors are called.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func)
-   {  return table_.erase(key, hash_func, equal_func);  }
+   {  return table_type::erase(key, hash_func, equal_func);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -474,7 +478,7 @@ class unordered_set_impl
                               , typename detail::enable_if_c<!detail::is_convertible<Disposer, const_iterator>::value >::type * = 0
                               /// @endcond
                               )
-   {  table_.erase_and_dispose(i, disposer);  }
+   {  table_type::erase_and_dispose(i, disposer);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -490,7 +494,7 @@ class unordered_set_impl
    //!    to the erased elements.
    template<class Disposer>
    void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer)
-   {  table_.erase_and_dispose(b, e, disposer);  }
+   {  table_type::erase_and_dispose(b, e, disposer);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -508,7 +512,7 @@ class unordered_set_impl
    //!    to the erased elements. No destructors are called.
    template<class Disposer>
    size_type erase_and_dispose(const_reference value, Disposer disposer)
-   {  return table_.erase_and_dispose(value, disposer);  }
+   {  return table_type::erase_and_dispose(value, disposer);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -527,7 +531,7 @@ class unordered_set_impl
    //!    to the erased elements.
    template<class KeyType, class KeyHasher, class KeyValueEqual, class Disposer>
    size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer)
-   {  return table_.erase_and_dispose(key, hash_func, equal_func, disposer);  }
+   {  return table_type::erase_and_dispose(key, hash_func, equal_func, disposer);  }
 
    //! <b>Effects</b>: Erases all of the elements.
    //!
@@ -539,7 +543,7 @@ class unordered_set_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased elements. No destructors are called.
    void clear()
-   {  return table_.clear();  }
+   {  return table_type::clear();  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -554,7 +558,7 @@ class unordered_set_impl
    //!    to the erased elements. No destructors are called.
    template<class Disposer>
    void clear_and_dispose(Disposer disposer)
-   {  return table_.clear_and_dispose(disposer);  }
+   {  return table_type::clear_and_dispose(disposer);  }
 
    //! <b>Effects</b>: Returns the number of contained elements with the given value
    //!
@@ -562,7 +566,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    size_type count(const_reference value) const
-   {  return table_.find(value) != end();  }
+   {  return table_type::find(value) != end();  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -579,7 +583,7 @@ class unordered_set_impl
    //! <b>Throws</b>: If hash_func or equal_func throw.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const
-   {  return table_.find(key, hash_func, equal_func) != end();  }
+   {  return table_type::find(key, hash_func, equal_func) != end();  }
 
    //! <b>Effects</b>: Finds an iterator to the first element is equal to
    //!   "value" or end() if that element does not exist.
@@ -588,7 +592,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    iterator find(const_reference value)
-   {  return table_.find(value);  }
+   {  return table_type::find(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -611,7 +615,7 @@ class unordered_set_impl
    //!   key type. Usually this key is part of the value_type.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func)
-   {  return table_.find(key, hash_func, equal_func);  }
+   {  return table_type::find(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
    //!   "key" or end() if that element does not exist.
@@ -620,7 +624,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    const_iterator find(const_reference value) const
-   {  return table_.find(value);  }
+   {  return table_type::find(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -643,7 +647,7 @@ class unordered_set_impl
    //!   key type. Usually this key is part of the value_type.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const
-   {  return table_.find(key, hash_func, equal_func);  }
+   {  return table_type::find(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Returns a range containing all elements with values equivalent
    //!   to value. Returns std::make_pair(this->end(), this->end()) if no such
@@ -653,7 +657,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    std::pair<iterator,iterator> equal_range(const_reference value)
-   {  return table_.equal_range(value);  }
+   {  return table_type::equal_range(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -677,7 +681,7 @@ class unordered_set_impl
    //!   key type. Usually this key is part of the value_type.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    std::pair<iterator,iterator> equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func)
-   {  return table_.equal_range(key, hash_func, equal_func);  }
+   {  return table_type::equal_range(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Returns a range containing all elements with values equivalent
    //!   to value. Returns std::make_pair(this->end(), this->end()) if no such
@@ -688,7 +692,7 @@ class unordered_set_impl
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    std::pair<const_iterator, const_iterator>
       equal_range(const_reference value) const
-   {  return table_.equal_range(value);  }
+   {  return table_type::equal_range(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -713,7 +717,7 @@ class unordered_set_impl
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    std::pair<const_iterator, const_iterator>
       equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const
-   {  return table_.equal_range(key, hash_func, equal_func);  }
+   {  return table_type::equal_range(key, hash_func, equal_func);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -725,7 +729,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the internal hash function throws.
    iterator iterator_to(reference value)
-   {  return table_.iterator_to(value);  }
+   {  return table_type::iterator_to(value);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -737,7 +741,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the internal hash function throws.
    const_iterator iterator_to(const_reference value) const
-   {  return table_.iterator_to(value);  }
+   {  return table_type::iterator_to(value);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -779,7 +783,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    local_iterator local_iterator_to(reference value)
-   {  return table_.local_iterator_to(value);  }
+   {  return table_type::local_iterator_to(value);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -791,7 +795,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_local_iterator local_iterator_to(const_reference value) const
-   {  return table_.local_iterator_to(value);  }
+   {  return table_type::local_iterator_to(value);  }
 
    //! <b>Effects</b>: Returns the number of buckets passed in the constructor
    //!   or the last rehash function.
@@ -800,7 +804,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    size_type bucket_count() const
-   {  return table_.bucket_count();   }
+   {  return table_type::bucket_count();   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -810,7 +814,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    size_type bucket_size(size_type n) const
-   {  return table_.bucket_size(n);   }
+   {  return table_type::bucket_size(n);   }
 
    //! <b>Effects</b>: Returns the index of the bucket in which elements
    //!   with keys equivalent to k would be found, if any such element existed.
@@ -821,7 +825,7 @@ class unordered_set_impl
    //!
    //! <b>Note</b>: the return value is in the range [0, this->bucket_count()).
    size_type bucket(const value_type& k) const
-   {  return table_.bucket(k);   }
+   {  return table_type::bucket(k);   }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -837,7 +841,7 @@ class unordered_set_impl
    //! <b>Note</b>: the return value is in the range [0, this->bucket_count()).
    template<class KeyType, class KeyHasher>
    size_type bucket(const KeyType& k,  KeyHasher hash_func) const
-   {  return table_.bucket(k, hash_func);   }
+   {  return table_type::bucket(k, hash_func);   }
 
    //! <b>Effects</b>: Returns the bucket array pointer passed in the constructor
    //!   or the last rehash function.
@@ -846,7 +850,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: Nothing.
    bucket_ptr bucket_pointer() const
-   {  return table_.bucket_pointer();   }
+   {  return table_type::bucket_pointer();   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -860,7 +864,7 @@ class unordered_set_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    local_iterator begin(size_type n)
-   {  return table_.begin(n);   }
+   {  return table_type::begin(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -874,7 +878,7 @@ class unordered_set_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator begin(size_type n) const
-   {  return table_.begin(n);   }
+   {  return table_type::begin(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -888,7 +892,7 @@ class unordered_set_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator cbegin(size_type n) const
-   {  return table_.cbegin(n);   }
+   {  return table_type::cbegin(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -902,7 +906,7 @@ class unordered_set_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    local_iterator end(size_type n)
-   {  return table_.end(n);   }
+   {  return table_type::end(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -916,7 +920,7 @@ class unordered_set_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator end(size_type n) const
-   {  return table_.end(n);   }
+   {  return table_type::end(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -930,7 +934,7 @@ class unordered_set_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator cend(size_type n) const
-   {  return table_.cend(n);   }
+   {  return table_type::cend(n);   }
 
    //! <b>Requires</b>: new_buckets must be a pointer to a new bucket array
    //!   or the same as the old bucket array. new_size is the length of the
@@ -946,7 +950,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>: If the hasher functor throws. Basic guarantee.
    void rehash(const bucket_traits &new_bucket_traits)
-   {  table_.rehash(new_bucket_traits); }
+   {  table_type::rehash(new_bucket_traits); }
 
    //! <b>Requires</b>:
    //!
@@ -958,11 +962,11 @@ class unordered_set_impl
    //!
    //! <b>Note</b>: this method is only available if incremental<true> option is activated.
    bool incremental_rehash(bool grow = true)
-   {  return table_.incremental_rehash(grow);  }
+   {  return table_type::incremental_rehash(grow);  }
 
    //! <b>Note</b>: this method is only available if incremental<true> option is activated.
    bool incremental_rehash(const bucket_traits &new_bucket_traits)
-   {  return table_.incremental_rehash(new_bucket_traits);  }
+   {  return table_type::incremental_rehash(new_bucket_traits);  }
 
    //! <b>Requires</b>:
    //!
@@ -972,7 +976,7 @@ class unordered_set_impl
    //!
    //! <b>Throws</b>:
    size_type split_count() const
-   {  return table_.split_count(); }
+   {  return table_type::split_count(); }
 
    //! <b>Effects</b>: Returns the nearest new bucket count optimized for
    //!   the container that is bigger than n. This suggestion can be used
@@ -997,6 +1001,8 @@ class unordered_set_impl
    //! <b>Throws</b>: Nothing.
    static size_type suggested_lower_bucket_count(size_type n)
    {  return table_type::suggested_lower_bucket_count(n);  }
+
+   #endif   //   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 };
 
 //! Helper metafunction to define an \c unordered_set that yields to the same type when the
@@ -1004,26 +1010,45 @@ class unordered_set_impl
 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
 template<class T, class ...Options>
 #else
-template<class T, class O1 = none, class O2 = none
-                , class O3 = none, class O4 = none
-                , class O5 = none, class O6 = none
-                , class O7 = none, class O8 = none
-                , class O9 = none, class O10= none
+template<class T, class O1 = void, class O2 = void
+                , class O3 = void, class O4 = void
+                , class O5 = void, class O6 = void
+                , class O7 = void, class O8 = void
+                , class O9 = void, class O10= void
                 >
 #endif
 struct make_unordered_set
 {
    /// @cond
+   typedef typename pack_options
+      < hashtable_defaults,
+         #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+         O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+         #else
+         Options...
+         #endif
+      >::type packed_options;
+
+   typedef typename detail::get_value_traits
+      <T, typename packed_options::proto_value_traits>::type value_traits;
+
+   typedef typename make_bucket_traits
+            <T, true, packed_options>::type bucket_traits;
+
    typedef unordered_set_impl
-      <  typename make_hashtable_opt
-            <T, true,
-               #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
-               O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
-               #else
-               Options...
-               #endif
-            >::type
+      < value_traits
+      , typename packed_options::hash
+      , typename packed_options::equal
+      , typename packed_options::size_type
+      , bucket_traits
+      ,  (std::size_t(true)*hash_bool_flags::unique_keys_pos)
+      |  (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
+      |  (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
+      |  (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
+      |  (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
+      |  (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
       > implementation_defined;
+
    /// @endcond
    typedef implementation_defined type;
 };
@@ -1067,10 +1092,10 @@ class unordered_set
    typedef typename Base::hasher             hasher;
    typedef typename Base::key_equal          key_equal;
 
-   unordered_set  ( const bucket_traits &b_traits
-                  , const hasher & hash_func = hasher()
-                  , const key_equal &equal_func = key_equal()
-                  , const value_traits &v_traits = value_traits())
+   explicit unordered_set  ( const bucket_traits &b_traits
+                           , const hasher & hash_func = hasher()
+                           , const key_equal &equal_func = key_equal()
+                           , const value_traits &v_traits = value_traits())
       :  Base(b_traits, hash_func, equal_func, v_traits)
    {}
 
@@ -1089,7 +1114,7 @@ class unordered_set
    {}
 
    unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
-   {  this->Base::operator=(::boost::move(static_cast<Base&>(x))); return *this;  }
+   {  return static_cast<unordered_set&>(this->Base::operator=(::boost::move(static_cast<Base&>(x))));  }
 };
 
 #endif
@@ -1133,13 +1158,14 @@ class unordered_set
 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
 template<class T, class ...Options>
 #else
-template<class Config>
+template<class ValueTraits, class Hash, class Equal, class SizeType, class BucketTraits, std::size_t BoolFlags>
 #endif
 class unordered_multiset_impl
+   : public hashtable_impl<ValueTraits, Hash, Equal, SizeType, BucketTraits, BoolFlags>
 {
    /// @cond
    private:
-   typedef hashtable_impl<Config> table_type;
+   typedef hashtable_impl<ValueTraits, Hash, Equal, SizeType, BucketTraits, BoolFlags> table_type;
    /// @endcond
 
    //Movable
@@ -1173,11 +1199,6 @@ class unordered_multiset_impl
    typedef typename implementation_defined::const_node_ptr              const_node_ptr;
    typedef typename implementation_defined::node_algorithms             node_algorithms;
 
-   /// @cond
-   private:
-   table_type table_;
-   /// @endcond
-
    public:
 
    //! <b>Requires</b>: buckets must not be being used by any other resource.
@@ -1193,11 +1214,11 @@ class unordered_multiset_impl
    //!
    //! <b>Notes</b>: buckets array must be disposed only after
    //!   *this is disposed.
-   unordered_multiset_impl ( const bucket_traits &b_traits
-                           , const hasher & hash_func = hasher()
-                           , const key_equal &equal_func = key_equal()
-                           , const value_traits &v_traits = value_traits())
-      :  table_(b_traits, hash_func, equal_func, v_traits)
+   explicit unordered_multiset_impl ( const bucket_traits &b_traits
+                                    , const hasher & hash_func = hasher()
+                                    , const key_equal &equal_func = key_equal()
+                                    , const value_traits &v_traits = value_traits())
+      :  table_type(b_traits, hash_func, equal_func, v_traits)
    {}
 
    //! <b>Requires</b>: buckets must not be being used by any other resource
@@ -1222,19 +1243,21 @@ class unordered_multiset_impl
                            , const hasher & hash_func = hasher()
                            , const key_equal &equal_func = key_equal()
                            , const value_traits &v_traits = value_traits())
-      :  table_(b_traits, hash_func, equal_func, v_traits)
-   {  table_.insert_equal(b, e);  }
+      :  table_type(b_traits, hash_func, equal_func, v_traits)
+   {  table_type::insert_equal(b, e);  }
 
    //! <b>Effects</b>: to-do
    //!
    unordered_multiset_impl(BOOST_RV_REF(unordered_multiset_impl) x)
-      :  table_(::boost::move(x.table_))
+      :  table_type(::boost::move(static_cast<table_type&>(x)))
    {}
 
    //! <b>Effects</b>: to-do
    //!
    unordered_multiset_impl& operator=(BOOST_RV_REF(unordered_multiset_impl) x)
-   {  table_ = ::boost::move(x.table_);  return *this;  }
+   {  return static_cast<unordered_multiset_impl&>(table_type::operator=(::boost::move(static_cast<table_type&>(x))));  }
+
+   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 
    //! <b>Effects</b>: Detaches all elements from this. The objects in the unordered_multiset
    //!   are not deleted (i.e. no destructors are called).
@@ -1253,7 +1276,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    iterator begin()
-   { return table_.begin();  }
+   { return table_type::begin();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //!   of the unordered_multiset.
@@ -1263,7 +1286,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator begin() const
-   { return table_.begin();  }
+   { return table_type::begin();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //!   of the unordered_multiset.
@@ -1273,7 +1296,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cbegin() const
-   { return table_.cbegin();  }
+   { return table_type::cbegin();  }
 
    //! <b>Effects</b>: Returns an iterator pointing to the end of the unordered_multiset.
    //!
@@ -1281,7 +1304,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    iterator end()
-   { return table_.end();  }
+   { return table_type::end();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the end of the unordered_multiset.
    //!
@@ -1289,7 +1312,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator end() const
-   { return table_.end();  }
+   { return table_type::end();  }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the end of the unordered_multiset.
    //!
@@ -1297,7 +1320,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cend() const
-   { return table_.cend();  }
+   { return table_type::cend();  }
 
    //! <b>Effects</b>: Returns the hasher object used by the unordered_set.
    //!
@@ -1305,7 +1328,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If hasher copy-constructor throws.
    hasher hash_function() const
-   { return table_.hash_function(); }
+   { return table_type::hash_function(); }
 
    //! <b>Effects</b>: Returns the key_equal object used by the unordered_multiset.
    //!
@@ -1313,7 +1336,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If key_equal copy-constructor throws.
    key_equal key_eq() const
-   { return table_.key_eq(); }
+   { return table_type::key_eq(); }
 
    //! <b>Effects</b>: Returns true if the container is empty.
    //!
@@ -1323,7 +1346,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    bool empty() const
-   { return table_.empty(); }
+   { return table_type::empty(); }
 
    //! <b>Effects</b>: Returns the number of elements stored in the unordered_multiset.
    //!
@@ -1332,7 +1355,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    size_type size() const
-   { return table_.size(); }
+   { return table_type::size(); }
 
    //! <b>Requires</b>: the hasher and the equality function unqualified swap
    //!   call should not throw.
@@ -1346,7 +1369,7 @@ class unordered_multiset_impl
    //! <b>Throws</b>: If the swap() call for the comparison or hash functors
    //!   found using ADL throw. Basic guarantee.
    void swap(unordered_multiset_impl& other)
-   { table_.swap(other.table_); }
+   { table_type::swap(other.table_); }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!   Cloner should yield to nodes that compare equal and produce the same
@@ -1369,7 +1392,9 @@ class unordered_multiset_impl
    //!   throws. Basic guarantee.
    template <class Cloner, class Disposer>
    void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer)
-   {  table_.clone_from(src.table_, cloner, disposer);  }
+   {  table_type::clone_from(src.table_, cloner, disposer);  }
+
+   #endif   //   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 
    //! <b>Requires</b>: value must be an lvalue
    //!
@@ -1384,7 +1409,7 @@ class unordered_multiset_impl
    //! <b>Note</b>: Does not affect the validity of iterators and references.
    //!   No copy-constructors are called.
    iterator insert(reference value)
-   {  return table_.insert_equal(value);  }
+   {  return table_type::insert_equal(value);  }
 
    //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
    //!   of type value_type.
@@ -1400,7 +1425,9 @@ class unordered_multiset_impl
    //!   No copy-constructors are called.
    template<class Iterator>
    void insert(Iterator b, Iterator e)
-   {  table_.insert_equal(b, e);  }
+   {  table_type::insert_equal(b, e);  }
+
+   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 
    //! <b>Effects</b>: Erases the element pointed to by i.
    //!
@@ -1411,7 +1438,7 @@ class unordered_multiset_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased element. No destructors are called.
    void erase(const_iterator i)
-   {  table_.erase(i);  }
+   {  table_type::erase(i);  }
 
    //! <b>Effects</b>: Erases the range pointed to by b end e.
    //!
@@ -1423,7 +1450,7 @@ class unordered_multiset_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased elements. No destructors are called.
    void erase(const_iterator b, const_iterator e)
-   {  table_.erase(b, e);  }
+   {  table_type::erase(b, e);  }
 
    //! <b>Effects</b>: Erases all the elements with the given value.
    //!
@@ -1437,7 +1464,7 @@ class unordered_multiset_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased elements. No destructors are called.
    size_type erase(const_reference value)
-   {  return table_.erase(value);  }
+   {  return table_type::erase(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1462,7 +1489,7 @@ class unordered_multiset_impl
    //!    to the erased elements. No destructors are called.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func)
-   {  return table_.erase(key, hash_func, equal_func);  }
+   {  return table_type::erase(key, hash_func, equal_func);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -1481,7 +1508,7 @@ class unordered_multiset_impl
                               , typename detail::enable_if_c<!detail::is_convertible<Disposer, const_iterator>::value >::type * = 0
                               /// @endcond
                               )
-   {  table_.erase_and_dispose(i, disposer);  }
+   {  table_type::erase_and_dispose(i, disposer);  }
 
    #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
    template<class Disposer>
@@ -1503,7 +1530,7 @@ class unordered_multiset_impl
    //!    to the erased elements.
    template<class Disposer>
    void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer)
-   {  table_.erase_and_dispose(b, e, disposer);  }
+   {  table_type::erase_and_dispose(b, e, disposer);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -1521,7 +1548,7 @@ class unordered_multiset_impl
    //!    to the erased elements. No destructors are called.
    template<class Disposer>
    size_type erase_and_dispose(const_reference value, Disposer disposer)
-   {  return table_.erase_and_dispose(value, disposer);  }
+   {  return table_type::erase_and_dispose(value, disposer);  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -1540,7 +1567,7 @@ class unordered_multiset_impl
    //!    to the erased elements.
    template<class KeyType, class KeyHasher, class KeyValueEqual, class Disposer>
    size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer)
-   {  return table_.erase_and_dispose(key, hash_func, equal_func, disposer);  }
+   {  return table_type::erase_and_dispose(key, hash_func, equal_func, disposer);  }
 
    //! <b>Effects</b>: Erases all the elements of the container.
    //!
@@ -1552,7 +1579,7 @@ class unordered_multiset_impl
    //! <b>Note</b>: Invalidates the iterators (but not the references)
    //!    to the erased elements. No destructors are called.
    void clear()
-   {  return table_.clear();  }
+   {  return table_type::clear();  }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -1567,7 +1594,7 @@ class unordered_multiset_impl
    //!    to the erased elements. No destructors are called.
    template<class Disposer>
    void clear_and_dispose(Disposer disposer)
-   {  return table_.clear_and_dispose(disposer);  }
+   {  return table_type::clear_and_dispose(disposer);  }
 
    //! <b>Effects</b>: Returns the number of contained elements with the given key
    //!
@@ -1575,7 +1602,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    size_type count(const_reference value) const
-   {  return table_.count(value);  }
+   {  return table_type::count(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1592,7 +1619,7 @@ class unordered_multiset_impl
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const
-   {  return table_.count(key, hash_func, equal_func);  }
+   {  return table_type::count(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Finds an iterator to the first element whose value is
    //!   "value" or end() if that element does not exist.
@@ -1601,7 +1628,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    iterator find(const_reference value)
-   {  return table_.find(value);  }
+   {  return table_type::find(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1624,7 +1651,7 @@ class unordered_multiset_impl
    //!   key type. Usually this key is part of the value_type.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func)
-   {  return table_.find(key, hash_func, equal_func);  }
+   {  return table_type::find(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
    //!   "key" or end() if that element does not exist.
@@ -1633,7 +1660,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    const_iterator find(const_reference value) const
-   {  return table_.find(value);  }
+   {  return table_type::find(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1656,7 +1683,7 @@ class unordered_multiset_impl
    //!   key type. Usually this key is part of the value_type.
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const
-   {  return table_.find(key, hash_func, equal_func);  }
+   {  return table_type::find(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Returns a range containing all elements with values equivalent
    //!   to value. Returns std::make_pair(this->end(), this->end()) if no such
@@ -1666,7 +1693,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    std::pair<iterator,iterator> equal_range(const_reference value)
-   {  return table_.equal_range(value);  }
+   {  return table_type::equal_range(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1691,7 +1718,7 @@ class unordered_multiset_impl
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    std::pair<iterator,iterator> equal_range
       (const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func)
-   {  return table_.equal_range(key, hash_func, equal_func);  }
+   {  return table_type::equal_range(key, hash_func, equal_func);  }
 
    //! <b>Effects</b>: Returns a range containing all elements with values equivalent
    //!   to value. Returns std::make_pair(this->end(), this->end()) if no such
@@ -1702,7 +1729,7 @@ class unordered_multiset_impl
    //! <b>Throws</b>: If the internal hasher or the equality functor throws.
    std::pair<const_iterator, const_iterator>
       equal_range(const_reference value) const
-   {  return table_.equal_range(value);  }
+   {  return table_type::equal_range(value);  }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1727,7 +1754,7 @@ class unordered_multiset_impl
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    std::pair<const_iterator, const_iterator>
       equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const
-   {  return table_.equal_range(key, hash_func, equal_func);  }
+   {  return table_type::equal_range(key, hash_func, equal_func);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_multiset of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -1739,7 +1766,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the hash function throws.
    iterator iterator_to(reference value)
-   {  return table_.iterator_to(value);  }
+   {  return table_type::iterator_to(value);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_multiset of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -1751,7 +1778,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the hash function throws.
    const_iterator iterator_to(const_reference value) const
-   {  return table_.iterator_to(value);  }
+   {  return table_type::iterator_to(value);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -1793,7 +1820,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    local_iterator local_iterator_to(reference value)
-   {  return table_.local_iterator_to(value);  }
+   {  return table_type::local_iterator_to(value);  }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //!   appropriate type. Otherwise the behavior is undefined.
@@ -1805,7 +1832,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    const_local_iterator local_iterator_to(const_reference value) const
-   {  return table_.local_iterator_to(value);  }
+   {  return table_type::local_iterator_to(value);  }
 
    //! <b>Effects</b>: Returns the number of buckets passed in the constructor
    //!   or the last rehash function.
@@ -1814,7 +1841,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    size_type bucket_count() const
-   {  return table_.bucket_count();   }
+   {  return table_type::bucket_count();   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1824,7 +1851,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    size_type bucket_size(size_type n) const
-   {  return table_.bucket_size(n);   }
+   {  return table_type::bucket_size(n);   }
 
    //! <b>Effects</b>: Returns the index of the bucket in which elements
    //!   with keys equivalent to k would be found, if any such element existed.
@@ -1835,7 +1862,7 @@ class unordered_multiset_impl
    //!
    //! <b>Note</b>: the return value is in the range [0, this->bucket_count()).
    size_type bucket(const value_type& k) const
-   {  return table_.bucket(k);   }
+   {  return table_type::bucket(k);   }
 
    //! <b>Requires</b>: "hash_func" must be a hash function that induces
    //!   the same hash values as the stored hasher. The difference is that
@@ -1851,7 +1878,7 @@ class unordered_multiset_impl
    //! <b>Note</b>: the return value is in the range [0, this->bucket_count()).
    template<class KeyType, class KeyHasher>
    size_type bucket(const KeyType& k, const KeyHasher &hash_func) const
-   {  return table_.bucket(k, hash_func);   }
+   {  return table_type::bucket(k, hash_func);   }
 
    //! <b>Effects</b>: Returns the bucket array pointer passed in the constructor
    //!   or the last rehash function.
@@ -1860,7 +1887,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: Nothing.
    bucket_ptr bucket_pointer() const
-   {  return table_.bucket_pointer();   }
+   {  return table_type::bucket_pointer();   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1874,7 +1901,7 @@ class unordered_multiset_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    local_iterator begin(size_type n)
-   {  return table_.begin(n);   }
+   {  return table_type::begin(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1888,7 +1915,7 @@ class unordered_multiset_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator begin(size_type n) const
-   {  return table_.begin(n);   }
+   {  return table_type::begin(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1902,7 +1929,7 @@ class unordered_multiset_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator cbegin(size_type n) const
-   {  return table_.cbegin(n);   }
+   {  return table_type::cbegin(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1916,7 +1943,7 @@ class unordered_multiset_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    local_iterator end(size_type n)
-   {  return table_.end(n);   }
+   {  return table_type::end(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1930,7 +1957,7 @@ class unordered_multiset_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator end(size_type n) const
-   {  return table_.end(n);   }
+   {  return table_type::end(n);   }
 
    //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
    //!
@@ -1944,7 +1971,7 @@ class unordered_multiset_impl
    //! <b>Note</b>:  [this->begin(n), this->end(n)) is a valid range
    //!   containing all of the elements in the nth bucket.
    const_local_iterator cend(size_type n) const
-   {  return table_.cend(n);   }
+   {  return table_type::cend(n);   }
 
    //! <b>Requires</b>: new_buckets must be a pointer to a new bucket array
    //!   or the same as the old bucket array. new_size is the length of the
@@ -1960,7 +1987,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>: If the hasher functor throws.
    void rehash(const bucket_traits &new_bucket_traits)
-   {  table_.rehash(new_bucket_traits); }
+   {  table_type::rehash(new_bucket_traits); }
 
    //! <b>Requires</b>:
    //!
@@ -1972,11 +1999,11 @@ class unordered_multiset_impl
    //!
    //! <b>Note</b>: this method is only available if incremental<true> option is activated.
    bool incremental_rehash(bool grow = true)
-   {  return table_.incremental_rehash(grow);  }
+   {  return table_type::incremental_rehash(grow);  }
 
    //! <b>Note</b>: this method is only available if incremental<true> option is activated.
    bool incremental_rehash(const bucket_traits &new_bucket_traits)
-   {  return table_.incremental_rehash(new_bucket_traits);  }
+   {  return table_type::incremental_rehash(new_bucket_traits);  }
 
    //! <b>Requires</b>:
    //!
@@ -1986,7 +2013,7 @@ class unordered_multiset_impl
    //!
    //! <b>Throws</b>:
    size_type split_count() const
-   {  return table_.split_count(); }
+   {  return table_type::split_count(); }
 
    //! <b>Effects</b>: Returns the nearest new bucket count optimized for
    //!   the container that is bigger than n. This suggestion can be used
@@ -2011,6 +2038,8 @@ class unordered_multiset_impl
    //! <b>Throws</b>: Nothing.
    static size_type suggested_lower_bucket_count(size_type n)
    {  return table_type::suggested_lower_bucket_count(n);  }
+
+   #endif   //   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 };
 
 //! Helper metafunction to define an \c unordered_multiset that yields to the same type when the
@@ -2018,26 +2047,45 @@ class unordered_multiset_impl
 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
 template<class T, class ...Options>
 #else
-template<class T, class O1 = none, class O2 = none
-                , class O3 = none, class O4 = none
-                , class O5 = none, class O6 = none
-                , class O7 = none, class O8 = none
-                , class O9 = none, class O10= none
+template<class T, class O1 = void, class O2 = void
+                , class O3 = void, class O4 = void
+                , class O5 = void, class O6 = void
+                , class O7 = void, class O8 = void
+                , class O9 = void, class O10= void
                 >
 #endif
 struct make_unordered_multiset
 {
    /// @cond
+   typedef typename pack_options
+      < hashtable_defaults,
+         #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+         O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+         #else
+         Options...
+         #endif
+      >::type packed_options;
+
+   typedef typename detail::get_value_traits
+      <T, typename packed_options::proto_value_traits>::type value_traits;
+
+   typedef typename make_bucket_traits
+            <T, true, packed_options>::type bucket_traits;
+
    typedef unordered_multiset_impl
-      <  typename make_hashtable_opt
-            <T, false,
-               #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
-               O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
-               #else
-               Options...
-               #endif
-            >::type
+      < value_traits
+      , typename packed_options::hash
+      , typename packed_options::equal
+      , typename packed_options::size_type
+      , bucket_traits
+      ,  (std::size_t(false)*hash_bool_flags::unique_keys_pos)
+      |  (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
+      |  (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
+      |  (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
+      |  (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
+      |  (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
       > implementation_defined;
+
    /// @endcond
    typedef implementation_defined type;
 };
@@ -2080,10 +2128,10 @@ class unordered_multiset
    typedef typename Base::hasher             hasher;
    typedef typename Base::key_equal          key_equal;
 
-   unordered_multiset( const bucket_traits &b_traits
-                     , const hasher & hash_func = hasher()
-                     , const key_equal &equal_func = key_equal()
-                     , const value_traits &v_traits = value_traits())
+   explicit unordered_multiset( const bucket_traits &b_traits
+                              , const hasher & hash_func = hasher()
+                              , const key_equal &equal_func = key_equal()
+                              , const value_traits &v_traits = value_traits())
       :  Base(b_traits, hash_func, equal_func, v_traits)
    {}
 
@@ -2102,7 +2150,7 @@ class unordered_multiset
    {}
 
    unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
-   {  this->Base::operator=(::boost::move(static_cast<Base&>(x))); return *this;  }
+   {  return static_cast<unordered_multiset&>(this->Base::operator=(::boost::move(static_cast<Base&>(x))));  }
 };
 
 #endif