1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Olaf Krzikalla 2004-2006.
4 // (C) Copyright Ion Gaztanaga  2006-2014
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 //    (See accompanying file LICENSE_1_0.txt or copy at
8 //          http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // See http://www.boost.org/libs/intrusive for documentation.
11 //
12 /////////////////////////////////////////////////////////////////////////////
13 #ifndef BOOST_INTRUSIVE_UNORDERED_SET_HPP
14 #define BOOST_INTRUSIVE_UNORDERED_SET_HPP
15 
16 #include <boost/intrusive/detail/config_begin.hpp>
17 #include <boost/intrusive/intrusive_fwd.hpp>
18 #include <boost/intrusive/hashtable.hpp>
19 #include <boost/move/utility_core.hpp>
20 #include <boost/static_assert.hpp>
21 
22 #if defined(BOOST_HAS_PRAGMA_ONCE)
23 #  pragma once
24 #endif
25 
26 namespace boost {
27 namespace intrusive {
28 
29 //! The class template unordered_set is an intrusive container, that mimics most of
30 //! the interface of std::tr1::unordered_set as described in the C++ TR1.
31 //!
32 //! unordered_set is a semi-intrusive container: each object to be stored in the
33 //! container must contain a proper hook, but the container also needs
34 //! additional auxiliary memory to work: unordered_set needs a pointer to an array
35 //! of type `bucket_type` to be passed in the constructor. This bucket array must
36 //! have at least the same lifetime as the container. This makes the use of
37 //! unordered_set more complicated than purely intrusive containers.
38 //! `bucket_type` is default-constructible, copyable and assignable
39 //!
40 //! The template parameter \c T is the type to be managed by the container.
41 //! The user can specify additional options and if no options are provided
42 //! default options are used.
43 //!
44 //! The container supports the following options:
45 //! \c base_hook<>/member_hook<>/value_traits<>,
46 //! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
47 //! \c bucket_traits<>, \c power_2_buckets<> and \c cache_begin<>.
48 //!
49 //! unordered_set only provides forward iterators but it provides 4 iterator types:
50 //! iterator and const_iterator to navigate through the whole container and
51 //! local_iterator and const_local_iterator to navigate through the values
52 //! stored in a single bucket. Local iterators are faster and smaller.
53 //!
54 //! It's not recommended to use non constant-time size unordered_sets because several
55 //! key functions, like "empty()", become non-constant time functions. Non
56 //! constant-time size unordered_sets are mainly provided to support auto-unlink hooks.
57 //!
58 //! unordered_set, unlike std::unordered_set, does not make automatic rehashings nor
59 //! offers functions related to a load factor. Rehashing can be explicitly requested
60 //! and the user must provide a new bucket array that will be used from that moment.
61 //!
62 //! Since no automatic rehashing is done, iterators are never invalidated when
63 //! inserting or erasing elements. Iterators are only invalidated when rehasing.
64 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
65 template<class T, class ...Options>
66 #else
67 template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
68 #endif
69 class unordered_set_impl
70    : public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags|hash_bool_flags::unique_keys_pos>
71 {
72    /// @cond
73    private:
74    typedef hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags|hash_bool_flags::unique_keys_pos> table_type;
75 
76    template<class Iterator, class MaybeConstThis, class KeyType, class KeyHasher, class KeyEqual>
priv_equal_range(MaybeConstThis & c,const KeyType & key,KeyHasher hash_func,KeyEqual equal_func)77    static std::pair<Iterator,Iterator> priv_equal_range(MaybeConstThis &c, const KeyType& key, KeyHasher hash_func, KeyEqual equal_func)
78    {
79       Iterator const it = c.find(key, hash_func, equal_func);
80       std::pair<Iterator,Iterator> ret(it, it);
81       if(it != c.end())
82          ++ret.second;
83       return ret;
84    }
85 
86    //! This class is
87    //! movable
88    BOOST_MOVABLE_BUT_NOT_COPYABLE(unordered_set_impl)
89 
90    typedef table_type implementation_defined;
91    /// @endcond
92 
93    public:
94    typedef typename implementation_defined::value_type                  value_type;
95    typedef typename implementation_defined::key_type                    key_type;
96    typedef typename implementation_defined::key_of_value                key_of_value;
97    typedef typename implementation_defined::value_traits                value_traits;
98    typedef typename implementation_defined::bucket_traits               bucket_traits;
99    typedef typename implementation_defined::pointer                     pointer;
100    typedef typename implementation_defined::const_pointer               const_pointer;
101    typedef typename implementation_defined::reference                   reference;
102    typedef typename implementation_defined::const_reference             const_reference;
103    typedef typename implementation_defined::difference_type             difference_type;
104    typedef typename implementation_defined::size_type                   size_type;
105    typedef typename implementation_defined::key_equal                   key_equal;
106    typedef typename implementation_defined::hasher                      hasher;
107    typedef typename implementation_defined::bucket_type                 bucket_type;
108    typedef typename implementation_defined::bucket_ptr                  bucket_ptr;
109    typedef typename implementation_defined::iterator                    iterator;
110    typedef typename implementation_defined::const_iterator              const_iterator;
111    typedef typename implementation_defined::insert_commit_data          insert_commit_data;
112    typedef typename implementation_defined::local_iterator              local_iterator;
113    typedef typename implementation_defined::const_local_iterator        const_local_iterator;
114    typedef typename implementation_defined::node_traits                 node_traits;
115    typedef typename implementation_defined::node                        node;
116    typedef typename implementation_defined::node_ptr                    node_ptr;
117    typedef typename implementation_defined::const_node_ptr              const_node_ptr;
118    typedef typename implementation_defined::node_algorithms             node_algorithms;
119 
120    public:
121 
122    //! @copydoc ::boost::intrusive::hashtable::hashtable(const bucket_traits &,const hasher &,const key_equal &,const value_traits &)
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 ())123    BOOST_INTRUSIVE_FORCEINLINE explicit unordered_set_impl( const bucket_traits &b_traits
124                               , const hasher & hash_func = hasher()
125                               , const key_equal &equal_func = key_equal()
126                               , const value_traits &v_traits = value_traits())
127       :  table_type(b_traits, hash_func, equal_func, v_traits)
128    {}
129 
130    //! @copydoc ::boost::intrusive::hashtable::hashtable(bool,Iterator,Iterator,const bucket_traits &,const hasher &,const key_equal &,const value_traits &)
131    template<class Iterator>
unordered_set_impl(Iterator b,Iterator e,const bucket_traits & b_traits,const hasher & hash_func=hasher (),const key_equal & equal_func=key_equal (),const value_traits & v_traits=value_traits ())132    BOOST_INTRUSIVE_FORCEINLINE unordered_set_impl( Iterator b
133                      , Iterator e
134                      , const bucket_traits &b_traits
135                      , const hasher & hash_func = hasher()
136                      , const key_equal &equal_func = key_equal()
137                      , const value_traits &v_traits = value_traits())
138       :  table_type(true, b, e, b_traits, hash_func, equal_func, v_traits)
139    {}
140 
141    //! @copydoc ::boost::intrusive::hashtable::hashtable(hashtable&&)
unordered_set_impl(BOOST_RV_REF (unordered_set_impl)x)142    BOOST_INTRUSIVE_FORCEINLINE unordered_set_impl(BOOST_RV_REF(unordered_set_impl) x)
143       :  table_type(BOOST_MOVE_BASE(table_type, x))
144    {}
145 
146    //! @copydoc ::boost::intrusive::hashtable::operator=(hashtable&&)
operator =(BOOST_RV_REF (unordered_set_impl)x)147    BOOST_INTRUSIVE_FORCEINLINE unordered_set_impl& operator=(BOOST_RV_REF(unordered_set_impl) x)
148    {  return static_cast<unordered_set_impl&>(table_type::operator=(BOOST_MOVE_BASE(table_type, x))); }
149 
150    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
151    //! @copydoc ::boost::intrusive::hashtable::~hashtable()
152    ~unordered_set_impl();
153 
154    //! @copydoc ::boost::intrusive::hashtable::begin()
155    iterator begin();
156 
157    //! @copydoc ::boost::intrusive::hashtable::begin()const
158    const_iterator begin() const;
159 
160    //! @copydoc ::boost::intrusive::hashtable::cbegin()const
161    const_iterator cbegin() const;
162 
163    //! @copydoc ::boost::intrusive::hashtable::end()
164    iterator end();
165 
166    //! @copydoc ::boost::intrusive::hashtable::end()const
167    const_iterator end() const;
168 
169    //! @copydoc ::boost::intrusive::hashtable::cend()const
170    const_iterator cend() const;
171 
172    //! @copydoc ::boost::intrusive::hashtable::hash_function()const
173    hasher hash_function() const;
174 
175    //! @copydoc ::boost::intrusive::hashtable::key_eq()const
176    key_equal key_eq() const;
177 
178    //! @copydoc ::boost::intrusive::hashtable::empty()const
179    bool empty() const;
180 
181    //! @copydoc ::boost::intrusive::hashtable::size()const
182    size_type size() const;
183 
184    //! @copydoc ::boost::intrusive::hashtable::hashtable
185    void swap(unordered_set_impl& other);
186 
187    //! @copydoc ::boost::intrusive::hashtable::clone_from(const hashtable&,Cloner,Disposer)
188    template <class Cloner, class Disposer>
189    void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer);
190 
191    #else
192 
193    using table_type::clone_from;
194 
195    #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
196 
197    //! @copydoc ::boost::intrusive::hashtable::clone_from(hashtable&&,Cloner,Disposer)
198    template <class Cloner, class Disposer>
clone_from(BOOST_RV_REF (unordered_set_impl)src,Cloner cloner,Disposer disposer)199    BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_set_impl) src, Cloner cloner, Disposer disposer)
200    {  table_type::clone_from(BOOST_MOVE_BASE(table_type, src), cloner, disposer);  }
201 
202    //! @copydoc ::boost::intrusive::hashtable::insert_unique(reference)
insert(reference value)203    BOOST_INTRUSIVE_FORCEINLINE std::pair<iterator, bool> insert(reference value)
204    {  return table_type::insert_unique(value);  }
205 
206    //! @copydoc ::boost::intrusive::hashtable::insert_unique(Iterator,Iterator)
207    template<class Iterator>
insert(Iterator b,Iterator e)208    BOOST_INTRUSIVE_FORCEINLINE void insert(Iterator b, Iterator e)
209    {  table_type::insert_unique(b, e);  }
210 
211    //! @copydoc ::boost::intrusive::hashtable::insert_unique_check(const key_type&,insert_commit_data&)
insert_check(const key_type & key,insert_commit_data & commit_data)212    BOOST_INTRUSIVE_FORCEINLINE std::pair<iterator, bool> insert_check(const key_type &key, insert_commit_data &commit_data)
213    {  return table_type::insert_unique_check(key, commit_data); }
214 
215    //! @copydoc ::boost::intrusive::hashtable::insert_unique_check(const KeyType&,KeyHasher,KeyEqual,insert_commit_data&)
216    template<class KeyType, class KeyHasher, class KeyEqual>
insert_check(const KeyType & key,KeyHasher hasher,KeyEqual key_value_equal,insert_commit_data & commit_data)217    BOOST_INTRUSIVE_FORCEINLINE std::pair<iterator, bool> insert_check
218       (const KeyType &key, KeyHasher hasher, KeyEqual key_value_equal, insert_commit_data &commit_data)
219    {  return table_type::insert_unique_check(key, hasher, key_value_equal, commit_data); }
220 
221    //! @copydoc ::boost::intrusive::hashtable::insert_unique_commit
insert_commit(reference value,const insert_commit_data & commit_data)222    BOOST_INTRUSIVE_FORCEINLINE iterator insert_commit(reference value, const insert_commit_data &commit_data)
223    {  return table_type::insert_unique_commit(value, commit_data); }
224 
225    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
226 
227    //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator)
228    void erase(const_iterator i);
229 
230    //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator,const_iterator)
231    void erase(const_iterator b, const_iterator e);
232 
233    //! @copydoc ::boost::intrusive::hashtable::erase(const key_type &)
234    size_type erase(const key_type &key);
235 
236    //! @copydoc ::boost::intrusive::hashtable::erase(const KeyType&,KeyHasher,KeyEqual)
237    template<class KeyType, class KeyHasher, class KeyEqual>
238    size_type erase(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func);
239 
240    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,Disposer)
241    template<class Disposer>
242    BOOST_INTRUSIVE_DOC1ST(void
243       , typename detail::disable_if_convertible<Disposer BOOST_INTRUSIVE_I const_iterator>::type)
244       erase_and_dispose(const_iterator i, Disposer disposer);
245 
246    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,const_iterator,Disposer)
247    template<class Disposer>
248    void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
249 
250    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const key_type &,Disposer)
251    template<class Disposer>
252    size_type erase_and_dispose(const key_type &key, Disposer disposer);
253 
254    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const KeyType&,KeyHasher,KeyEqual,Disposer)
255    template<class KeyType, class KeyHasher, class KeyEqual, class Disposer>
256    size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func, Disposer disposer);
257 
258    //! @copydoc ::boost::intrusive::hashtable::clear
259    void clear();
260 
261    //! @copydoc ::boost::intrusive::hashtable::clear_and_dispose
262    template<class Disposer>
263    void clear_and_dispose(Disposer disposer);
264 
265    //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const
266    size_type count(const key_type &key) const;
267 
268    //! @copydoc ::boost::intrusive::hashtable::count(const KeyType&,KeyHasher,KeyEqual)const
269    template<class KeyType, class KeyHasher, class KeyEqual>
270    size_type count(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const;
271 
272    //! @copydoc ::boost::intrusive::hashtable::find(const key_type &)
273    iterator find(const key_type &key);
274 
275    //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual)
276    template<class KeyType, class KeyHasher, class KeyEqual>
277    iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func);
278 
279    //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const
280    const_iterator find(const key_type &key) const;
281 
282    //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual)const
283    template<class KeyType, class KeyHasher, class KeyEqual>
284    const_iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const;
285    #endif
286 
287    //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&)
equal_range(const key_type & key)288    std::pair<iterator,iterator> equal_range(const key_type &key)
289    {  return this->equal_range(key, this->hash_function(), this->key_eq());  }
290 
291    //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual)
292    template<class KeyType, class KeyHasher, class KeyEqual>
equal_range(const KeyType & key,KeyHasher hash_func,KeyEqual equal_func)293    std::pair<iterator,iterator> equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func)
294    {  return this->priv_equal_range<iterator>(*this, key, hash_func, equal_func); }
295 
296    //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&)const
297    std::pair<const_iterator, const_iterator>
equal_range(const key_type & key) const298       equal_range(const key_type &key) const
299    {  return this->equal_range(key, this->hash_function(), this->key_eq());  }
300 
301    //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual)const
302    template<class KeyType, class KeyHasher, class KeyEqual>
303    std::pair<const_iterator, const_iterator>
equal_range(const KeyType & key,KeyHasher hash_func,KeyEqual equal_func) const304       equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const
305    {  return this->priv_equal_range<const_iterator>(*this, key, hash_func, equal_func); }
306 
307    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
308    //! @copydoc ::boost::intrusive::hashtable::iterator_to(reference)
309    iterator iterator_to(reference value);
310 
311    //! @copydoc ::boost::intrusive::hashtable::iterator_to(const_reference)const
312    const_iterator iterator_to(const_reference value) const;
313 
314    //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(reference)
315    static local_iterator s_local_iterator_to(reference value);
316 
317    //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(const_reference)
318    static const_local_iterator s_local_iterator_to(const_reference value);
319 
320    //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(reference)
321    local_iterator local_iterator_to(reference value);
322 
323    //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(const_reference)
324    const_local_iterator local_iterator_to(const_reference value) const;
325 
326    //! @copydoc ::boost::intrusive::hashtable::bucket_count
327    size_type bucket_count() const;
328 
329    //! @copydoc ::boost::intrusive::hashtable::bucket_size
330    size_type bucket_size(size_type n) const;
331 
332    //! @copydoc ::boost::intrusive::hashtable::bucket(const key_type&)const
333    size_type bucket(const key_type& k) const;
334 
335    //! @copydoc ::boost::intrusive::hashtable::bucket(const KeyType&,KeyHasher)const
336    template<class KeyType, class KeyHasher>
337    size_type bucket(const KeyType& k,  KeyHasher hash_func) const;
338 
339    //! @copydoc ::boost::intrusive::hashtable::bucket_pointer
340    bucket_ptr bucket_pointer() const;
341 
342    //! @copydoc ::boost::intrusive::hashtable::begin(size_type)
343    local_iterator begin(size_type n);
344 
345    //! @copydoc ::boost::intrusive::hashtable::begin(size_type)const
346    const_local_iterator begin(size_type n) const;
347 
348    //! @copydoc ::boost::intrusive::hashtable::cbegin(size_type)const
349    const_local_iterator cbegin(size_type n) const;
350 
351    //! @copydoc ::boost::intrusive::hashtable::end(size_type)
352    local_iterator end(size_type n);
353 
354    //! @copydoc ::boost::intrusive::hashtable::end(size_type)const
355    const_local_iterator end(size_type n) const;
356 
357    //! @copydoc ::boost::intrusive::hashtable::cend(size_type)const
358    const_local_iterator cend(size_type n) const;
359 
360    //! @copydoc ::boost::intrusive::hashtable::rehash(const bucket_traits &)
361    void rehash(const bucket_traits &new_bucket_traits);
362 
363    //! @copydoc ::boost::intrusive::hashtable::full_rehash
364    void full_rehash();
365 
366    //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(bool)
367    bool incremental_rehash(bool grow = true);
368 
369    //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(const bucket_traits &)
370    bool incremental_rehash(const bucket_traits &new_bucket_traits);
371 
372    //! @copydoc ::boost::intrusive::hashtable::split_count
373    size_type split_count() const;
374 
375    //! @copydoc ::boost::intrusive::hashtable::suggested_upper_bucket_count
376    static size_type suggested_upper_bucket_count(size_type n);
377 
378    //! @copydoc ::boost::intrusive::hashtable::suggested_lower_bucket_count
379    static size_type suggested_lower_bucket_count(size_type n);
380 
381    #endif   //   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
382 
operator ==(const unordered_set_impl & x,const unordered_set_impl & y)383    friend bool operator==(const unordered_set_impl &x, const unordered_set_impl &y)
384    {
385       if(table_type::constant_time_size && x.size() != y.size()){
386          return false;
387       }
388       //Find each element of x in y
389       for (const_iterator ix = x.cbegin(), ex = x.cend(), ey = y.cend(); ix != ex; ++ix){
390          const_iterator iy = y.find(key_of_value()(*ix));
391          if (iy == ey || !(*ix == *iy))
392             return false;
393       }
394       return true;
395    }
396 
operator !=(const unordered_set_impl & x,const unordered_set_impl & y)397    friend bool operator!=(const unordered_set_impl &x, const unordered_set_impl &y)
398    {  return !(x == y); }
399 
operator <(const unordered_set_impl & x,const unordered_set_impl & y)400    friend bool operator<(const unordered_set_impl &x, const unordered_set_impl &y)
401    {  return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }
402 
operator >(const unordered_set_impl & x,const unordered_set_impl & y)403    friend bool operator>(const unordered_set_impl &x, const unordered_set_impl &y)
404    {  return y < x;  }
405 
operator <=(const unordered_set_impl & x,const unordered_set_impl & y)406    friend bool operator<=(const unordered_set_impl &x, const unordered_set_impl &y)
407    {  return !(y < x);  }
408 
operator >=(const unordered_set_impl & x,const unordered_set_impl & y)409    friend bool operator>=(const unordered_set_impl &x, const unordered_set_impl &y)
410    {  return !(x < y);  }
411 };
412 
413 //! Helper metafunction to define an \c unordered_set that yields to the same type when the
414 //! same options (either explicitly or implicitly) are used.
415 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
416 template<class T, class ...Options>
417 #else
418 template<class T, class O1 = void, class O2 = void
419                 , class O3 = void, class O4 = void
420                 , class O5 = void, class O6 = void
421                 , class O7 = void, class O8 = void
422                 , class O9 = void, class O10= void
423                 >
424 #endif
425 struct make_unordered_set
426 {
427    /// @cond
428    typedef typename pack_options
429       < hashtable_defaults,
430          #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
431          O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
432          #else
433          Options...
434          #endif
435       >::type packed_options;
436 
437    typedef typename detail::get_value_traits
438       <T, typename packed_options::proto_value_traits>::type value_traits;
439 
440    typedef typename make_bucket_traits
441             <T, true, packed_options>::type bucket_traits;
442 
443    typedef unordered_set_impl
444       < value_traits
445       , typename packed_options::key_of_value
446       , typename packed_options::hash
447       , typename packed_options::equal
448       , typename packed_options::size_type
449       , bucket_traits
450       ,  (std::size_t(true)*hash_bool_flags::unique_keys_pos)
451       |  (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
452       |  (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
453       |  (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
454       |  (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
455       |  (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
456       > implementation_defined;
457 
458    /// @endcond
459    typedef implementation_defined type;
460 };
461 
462 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
463 
464 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
465 template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
466 #else
467 template<class T, class ...Options>
468 #endif
469 class unordered_set
470    :  public make_unordered_set<T,
471          #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
472          O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
473          #else
474          Options...
475          #endif
476       >::type
477 {
478    typedef typename make_unordered_set
479       <T,
480          #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
481          O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
482          #else
483          Options...
484          #endif
485       >::type   Base;
486 
487    //Assert if passed value traits are compatible with the type
488    BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
489    BOOST_MOVABLE_BUT_NOT_COPYABLE(unordered_set)
490 
491    public:
492    typedef typename Base::value_traits       value_traits;
493    typedef typename Base::bucket_traits      bucket_traits;
494    typedef typename Base::iterator           iterator;
495    typedef typename Base::const_iterator     const_iterator;
496    typedef typename Base::bucket_ptr         bucket_ptr;
497    typedef typename Base::size_type          size_type;
498    typedef typename Base::hasher             hasher;
499    typedef typename Base::key_equal          key_equal;
500 
501    BOOST_INTRUSIVE_FORCEINLINE
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 ())502    explicit unordered_set  ( const bucket_traits &b_traits
503                            , const hasher & hash_func = hasher()
504                            , const key_equal &equal_func = key_equal()
505                            , const value_traits &v_traits = value_traits())
506       :  Base(b_traits, hash_func, equal_func, v_traits)
507    {}
508 
509    template<class Iterator>
510    BOOST_INTRUSIVE_FORCEINLINE
unordered_set(Iterator b,Iterator e,const bucket_traits & b_traits,const hasher & hash_func=hasher (),const key_equal & equal_func=key_equal (),const value_traits & v_traits=value_traits ())511    unordered_set
512                   ( Iterator b, Iterator e
513                   , const bucket_traits &b_traits
514                   , const hasher & hash_func = hasher()
515                   , const key_equal &equal_func = key_equal()
516                   , const value_traits &v_traits = value_traits())
517       :  Base(b, e, b_traits, hash_func, equal_func, v_traits)
518    {}
519 
unordered_set(BOOST_RV_REF (unordered_set)x)520    BOOST_INTRUSIVE_FORCEINLINE unordered_set(BOOST_RV_REF(unordered_set) x)
521       :  Base(BOOST_MOVE_BASE(Base, x))
522    {}
523 
operator =(BOOST_RV_REF (unordered_set)x)524    BOOST_INTRUSIVE_FORCEINLINE unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
525    {  return static_cast<unordered_set&>(this->Base::operator=(BOOST_MOVE_BASE(Base, x)));  }
526 
527    template <class Cloner, class Disposer>
clone_from(const unordered_set & src,Cloner cloner,Disposer disposer)528    BOOST_INTRUSIVE_FORCEINLINE void clone_from(const unordered_set &src, Cloner cloner, Disposer disposer)
529    {  Base::clone_from(src, cloner, disposer);  }
530 
531    template <class Cloner, class Disposer>
clone_from(BOOST_RV_REF (unordered_set)src,Cloner cloner,Disposer disposer)532    BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_set) src, Cloner cloner, Disposer disposer)
533    {  Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer);  }
534 };
535 
536 #endif
537 
538 
539 //! The class template unordered_multiset is an intrusive container, that mimics most of
540 //! the interface of std::tr1::unordered_multiset as described in the C++ TR1.
541 //!
542 //! unordered_multiset is a semi-intrusive container: each object to be stored in the
543 //! container must contain a proper hook, but the container also needs
544 //! additional auxiliary memory to work: unordered_multiset needs a pointer to an array
545 //! of type `bucket_type` to be passed in the constructor. This bucket array must
546 //! have at least the same lifetime as the container. This makes the use of
547 //! unordered_multiset more complicated than purely intrusive containers.
548 //! `bucket_type` is default-constructible, copyable and assignable
549 //!
550 //! The template parameter \c T is the type to be managed by the container.
551 //! The user can specify additional options and if no options are provided
552 //! default options are used.
553 //!
554 //! The container supports the following options:
555 //! \c base_hook<>/member_hook<>/value_traits<>,
556 //! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
557 //! \c bucket_traits<>, \c power_2_buckets<> and \c cache_begin<>.
558 //!
559 //! unordered_multiset only provides forward iterators but it provides 4 iterator types:
560 //! iterator and const_iterator to navigate through the whole container and
561 //! local_iterator and const_local_iterator to navigate through the values
562 //! stored in a single bucket. Local iterators are faster and smaller.
563 //!
564 //! It's not recommended to use non constant-time size unordered_multisets because several
565 //! key functions, like "empty()", become non-constant time functions. Non
566 //! constant-time size unordered_multisets are mainly provided to support auto-unlink hooks.
567 //!
568 //! unordered_multiset, unlike std::unordered_set, does not make automatic rehashings nor
569 //! offers functions related to a load factor. Rehashing can be explicitly requested
570 //! and the user must provide a new bucket array that will be used from that moment.
571 //!
572 //! Since no automatic rehashing is done, iterators are never invalidated when
573 //! inserting or erasing elements. Iterators are only invalidated when rehasing.
574 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
575 template<class T, class ...Options>
576 #else
577 template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
578 #endif
579 class unordered_multiset_impl
580    : public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags>
581 {
582    /// @cond
583    private:
584    typedef hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags> table_type;
585    /// @endcond
586 
587    //Movable
588    BOOST_MOVABLE_BUT_NOT_COPYABLE(unordered_multiset_impl)
589 
590    typedef table_type implementation_defined;
591 
592    public:
593    typedef typename implementation_defined::value_type                  value_type;
594    typedef typename implementation_defined::key_type                    key_type;
595    typedef typename implementation_defined::value_traits                value_traits;
596    typedef typename implementation_defined::bucket_traits               bucket_traits;
597    typedef typename implementation_defined::pointer                     pointer;
598    typedef typename implementation_defined::const_pointer               const_pointer;
599    typedef typename implementation_defined::reference                   reference;
600    typedef typename implementation_defined::const_reference             const_reference;
601    typedef typename implementation_defined::difference_type             difference_type;
602    typedef typename implementation_defined::size_type                   size_type;
603    typedef typename implementation_defined::key_equal                   key_equal;
604    typedef typename implementation_defined::hasher                      hasher;
605    typedef typename implementation_defined::bucket_type                 bucket_type;
606    typedef typename implementation_defined::bucket_ptr                  bucket_ptr;
607    typedef typename implementation_defined::iterator                    iterator;
608    typedef typename implementation_defined::const_iterator              const_iterator;
609    typedef typename implementation_defined::insert_commit_data          insert_commit_data;
610    typedef typename implementation_defined::local_iterator              local_iterator;
611    typedef typename implementation_defined::const_local_iterator        const_local_iterator;
612    typedef typename implementation_defined::node_traits                 node_traits;
613    typedef typename implementation_defined::node                        node;
614    typedef typename implementation_defined::node_ptr                    node_ptr;
615    typedef typename implementation_defined::const_node_ptr              const_node_ptr;
616    typedef typename implementation_defined::node_algorithms             node_algorithms;
617 
618    public:
619 
620    //! @copydoc ::boost::intrusive::hashtable::hashtable(const bucket_traits &,const hasher &,const key_equal &,const value_traits &)
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 ())621    BOOST_INTRUSIVE_FORCEINLINE explicit unordered_multiset_impl ( const bucket_traits &b_traits
622                                     , const hasher & hash_func = hasher()
623                                     , const key_equal &equal_func = key_equal()
624                                     , const value_traits &v_traits = value_traits())
625       :  table_type(b_traits, hash_func, equal_func, v_traits)
626    {}
627 
628    //! @copydoc ::boost::intrusive::hashtable::hashtable(bool,Iterator,Iterator,const bucket_traits &,const hasher &,const key_equal &,const value_traits &)
629    template<class Iterator>
unordered_multiset_impl(Iterator b,Iterator e,const bucket_traits & b_traits,const hasher & hash_func=hasher (),const key_equal & equal_func=key_equal (),const value_traits & v_traits=value_traits ())630    BOOST_INTRUSIVE_FORCEINLINE unordered_multiset_impl ( Iterator b
631                            , Iterator e
632                            , const bucket_traits &b_traits
633                            , const hasher & hash_func = hasher()
634                            , const key_equal &equal_func = key_equal()
635                            , const value_traits &v_traits = value_traits())
636       :  table_type(false, b, e, b_traits, hash_func, equal_func, v_traits)
637    {}
638 
639    //! <b>Effects</b>: to-do
640    //!
unordered_multiset_impl(BOOST_RV_REF (unordered_multiset_impl)x)641    BOOST_INTRUSIVE_FORCEINLINE unordered_multiset_impl(BOOST_RV_REF(unordered_multiset_impl) x)
642       :  table_type(BOOST_MOVE_BASE(table_type, x))
643    {}
644 
645    //! <b>Effects</b>: to-do
646    //!
operator =(BOOST_RV_REF (unordered_multiset_impl)x)647    BOOST_INTRUSIVE_FORCEINLINE unordered_multiset_impl& operator=(BOOST_RV_REF(unordered_multiset_impl) x)
648    {  return static_cast<unordered_multiset_impl&>(table_type::operator=(BOOST_MOVE_BASE(table_type, x)));  }
649 
650    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
651 
652    //! @copydoc ::boost::intrusive::hashtable::~hashtable()
653    ~unordered_multiset_impl();
654 
655    //! @copydoc ::boost::intrusive::hashtable::begin()
656    iterator begin();
657 
658    //! @copydoc ::boost::intrusive::hashtable::begin()const
659    const_iterator begin() const;
660 
661    //! @copydoc ::boost::intrusive::hashtable::cbegin()const
662    const_iterator cbegin() const;
663 
664    //! @copydoc ::boost::intrusive::hashtable::end()
665    iterator end();
666 
667    //! @copydoc ::boost::intrusive::hashtable::end()const
668    const_iterator end() const;
669 
670    //! @copydoc ::boost::intrusive::hashtable::cend()const
671    const_iterator cend() const;
672 
673    //! @copydoc ::boost::intrusive::hashtable::hash_function()const
674    hasher hash_function() const;
675 
676    //! @copydoc ::boost::intrusive::hashtable::key_eq()const
677    key_equal key_eq() const;
678 
679    //! @copydoc ::boost::intrusive::hashtable::empty()const
680    bool empty() const;
681 
682    //! @copydoc ::boost::intrusive::hashtable::size()const
683    size_type size() const;
684 
685    //! @copydoc ::boost::intrusive::hashtable::hashtable
686    void swap(unordered_multiset_impl& other);
687 
688    //! @copydoc ::boost::intrusive::hashtable::clone_from(const hashtable&,Cloner,Disposer)
689    template <class Cloner, class Disposer>
690    void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer);
691 
692    #else
693 
694    using table_type::clone_from;
695 
696    #endif   //   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
697 
698    //! @copydoc ::boost::intrusive::hashtable::clone_from(hashtable&&,Cloner,Disposer)
699    template <class Cloner, class Disposer>
clone_from(BOOST_RV_REF (unordered_multiset_impl)src,Cloner cloner,Disposer disposer)700    BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_multiset_impl) src, Cloner cloner, Disposer disposer)
701    {  table_type::clone_from(BOOST_MOVE_BASE(table_type, src), cloner, disposer);  }
702 
703    //! @copydoc ::boost::intrusive::hashtable::insert_equal(reference)
insert(reference value)704    BOOST_INTRUSIVE_FORCEINLINE iterator insert(reference value)
705    {  return table_type::insert_equal(value);  }
706 
707    //! @copydoc ::boost::intrusive::hashtable::insert_equal(Iterator,Iterator)
708    template<class Iterator>
insert(Iterator b,Iterator e)709    BOOST_INTRUSIVE_FORCEINLINE void insert(Iterator b, Iterator e)
710    {  table_type::insert_equal(b, e);  }
711 
712    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
713 
714    //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator)
715    void erase(const_iterator i);
716 
717    //! @copydoc ::boost::intrusive::hashtable::erase(const_iterator,const_iterator)
718    void erase(const_iterator b, const_iterator e);
719 
720    //! @copydoc ::boost::intrusive::hashtable::erase(const key_type &)
721    size_type erase(const key_type &key);
722 
723    //! @copydoc ::boost::intrusive::hashtable::erase(const KeyType&,KeyHasher,KeyEqual)
724    template<class KeyType, class KeyHasher, class KeyEqual>
725    size_type erase(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func);
726 
727    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,Disposer)
728    template<class Disposer>
729    BOOST_INTRUSIVE_DOC1ST(void
730       , typename detail::disable_if_convertible<Disposer BOOST_INTRUSIVE_I const_iterator>::type)
731       erase_and_dispose(const_iterator i, Disposer disposer);
732 
733    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const_iterator,const_iterator,Disposer)
734    template<class Disposer>
735    void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
736 
737    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const key_type &,Disposer)
738    template<class Disposer>
739    size_type erase_and_dispose(const key_type &key, Disposer disposer);
740 
741    //! @copydoc ::boost::intrusive::hashtable::erase_and_dispose(const KeyType&,KeyHasher,KeyEqual,Disposer)
742    template<class KeyType, class KeyHasher, class KeyEqual, class Disposer>
743    size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func, Disposer disposer);
744 
745    //! @copydoc ::boost::intrusive::hashtable::clear
746    void clear();
747 
748    //! @copydoc ::boost::intrusive::hashtable::clear_and_dispose
749    template<class Disposer>
750    void clear_and_dispose(Disposer disposer);
751 
752    //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const
753    size_type count(const key_type &key) const;
754 
755    //! @copydoc ::boost::intrusive::hashtable::count(const KeyType&,KeyHasher,KeyEqual)const
756    template<class KeyType, class KeyHasher, class KeyEqual>
757    size_type count(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const;
758 
759    //! @copydoc ::boost::intrusive::hashtable::find(const key_type &)
760    iterator find(const key_type &key);
761 
762    //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual)
763    template<class KeyType, class KeyHasher, class KeyEqual>
764    iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func);
765 
766    //! @copydoc ::boost::intrusive::hashtable::count(const key_type &)const
767    const_iterator find(const key_type &key) const;
768 
769    //! @copydoc ::boost::intrusive::hashtable::find(const KeyType &,KeyHasher,KeyEqual)const
770    template<class KeyType, class KeyHasher, class KeyEqual>
771    const_iterator find(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const;
772 
773    //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&)
774    std::pair<iterator,iterator> equal_range(const key_type &key);
775 
776    //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual)
777    template<class KeyType, class KeyHasher, class KeyEqual>
778    std::pair<iterator,iterator> equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func);
779 
780    //! @copydoc ::boost::intrusive::hashtable::equal_range(const key_type&)const
781    std::pair<const_iterator, const_iterator>
782       equal_range(const key_type &key) const;
783 
784    //! @copydoc ::boost::intrusive::hashtable::equal_range(const KeyType &,KeyHasher,KeyEqual)const
785    template<class KeyType, class KeyHasher, class KeyEqual>
786    std::pair<const_iterator, const_iterator>
787       equal_range(const KeyType& key, KeyHasher hash_func, KeyEqual equal_func) const;
788 
789    //! @copydoc ::boost::intrusive::hashtable::iterator_to(reference)
790    iterator iterator_to(reference value);
791 
792    //! @copydoc ::boost::intrusive::hashtable::iterator_to(const_reference)const
793    const_iterator iterator_to(const_reference value) const;
794 
795    //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(reference)
796    static local_iterator s_local_iterator_to(reference value);
797 
798    //! @copydoc ::boost::intrusive::hashtable::s_local_iterator_to(const_reference)
799    static const_local_iterator s_local_iterator_to(const_reference value);
800 
801    //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(reference)
802    local_iterator local_iterator_to(reference value);
803 
804    //! @copydoc ::boost::intrusive::hashtable::local_iterator_to(const_reference)
805    const_local_iterator local_iterator_to(const_reference value) const;
806 
807    //! @copydoc ::boost::intrusive::hashtable::bucket_count
808    size_type bucket_count() const;
809 
810    //! @copydoc ::boost::intrusive::hashtable::bucket_size
811    size_type bucket_size(size_type n) const;
812 
813    //! @copydoc ::boost::intrusive::hashtable::bucket(const key_type&)const
814    size_type bucket(const key_type& k) const;
815 
816    //! @copydoc ::boost::intrusive::hashtable::bucket(const KeyType&,KeyHasher)const
817    template<class KeyType, class KeyHasher>
818    size_type bucket(const KeyType& k, KeyHasher hash_func) const;
819 
820    //! @copydoc ::boost::intrusive::hashtable::bucket_pointer
821    bucket_ptr bucket_pointer() const;
822 
823    //! @copydoc ::boost::intrusive::hashtable::begin(size_type)
824    local_iterator begin(size_type n);
825 
826    //! @copydoc ::boost::intrusive::hashtable::begin(size_type)const
827    const_local_iterator begin(size_type n) const;
828 
829    //! @copydoc ::boost::intrusive::hashtable::cbegin(size_type)const
830    const_local_iterator cbegin(size_type n) const;
831 
832    //! @copydoc ::boost::intrusive::hashtable::end(size_type)
833    local_iterator end(size_type n);
834 
835    //! @copydoc ::boost::intrusive::hashtable::end(size_type)const
836    const_local_iterator end(size_type n) const;
837 
838    //! @copydoc ::boost::intrusive::hashtable::cend(size_type)const
839    const_local_iterator cend(size_type n) const;
840 
841    //! @copydoc ::boost::intrusive::hashtable::rehash(const bucket_traits &)
842    void rehash(const bucket_traits &new_bucket_traits);
843 
844    //! @copydoc ::boost::intrusive::hashtable::full_rehash
845    void full_rehash();
846 
847    //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(bool)
848    bool incremental_rehash(bool grow = true);
849 
850    //! @copydoc ::boost::intrusive::hashtable::incremental_rehash(const bucket_traits &)
851    bool incremental_rehash(const bucket_traits &new_bucket_traits);
852 
853    //! @copydoc ::boost::intrusive::hashtable::split_count
854    size_type split_count() const;
855 
856    //! @copydoc ::boost::intrusive::hashtable::suggested_upper_bucket_count
857    static size_type suggested_upper_bucket_count(size_type n);
858 
859    //! @copydoc ::boost::intrusive::hashtable::suggested_lower_bucket_count
860    static size_type suggested_lower_bucket_count(size_type n);
861 
862    #endif   //   #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
863 };
864 
865 //! Helper metafunction to define an \c unordered_multiset that yields to the same type when the
866 //! same options (either explicitly or implicitly) are used.
867 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
868 template<class T, class ...Options>
869 #else
870 template<class T, class O1 = void, class O2 = void
871                 , class O3 = void, class O4 = void
872                 , class O5 = void, class O6 = void
873                 , class O7 = void, class O8 = void
874                 , class O9 = void, class O10= void
875                 >
876 #endif
877 struct make_unordered_multiset
878 {
879    /// @cond
880    typedef typename pack_options
881       < hashtable_defaults,
882          #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
883          O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
884          #else
885          Options...
886          #endif
887       >::type packed_options;
888 
889    typedef typename detail::get_value_traits
890       <T, typename packed_options::proto_value_traits>::type value_traits;
891 
892    typedef typename make_bucket_traits
893             <T, true, packed_options>::type bucket_traits;
894 
895    typedef unordered_multiset_impl
896       < value_traits
897       , typename packed_options::key_of_value
898       , typename packed_options::hash
899       , typename packed_options::equal
900       , typename packed_options::size_type
901       , bucket_traits
902       ,  (std::size_t(false)*hash_bool_flags::unique_keys_pos)
903       |  (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
904       |  (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
905       |  (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
906       |  (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
907       |  (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
908       > implementation_defined;
909 
910    /// @endcond
911    typedef implementation_defined type;
912 };
913 
914 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
915 
916 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
917 template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
918 #else
919 template<class T, class ...Options>
920 #endif
921 class unordered_multiset
922    :  public make_unordered_multiset<T,
923          #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
924          O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
925          #else
926          Options...
927          #endif
928       >::type
929 {
930    typedef typename make_unordered_multiset
931       <T,
932          #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
933          O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
934          #else
935          Options...
936          #endif
937       >::type   Base;
938    //Assert if passed value traits are compatible with the type
939    BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
940    BOOST_MOVABLE_BUT_NOT_COPYABLE(unordered_multiset)
941 
942    public:
943    typedef typename Base::value_traits       value_traits;
944    typedef typename Base::bucket_traits      bucket_traits;
945    typedef typename Base::iterator           iterator;
946    typedef typename Base::const_iterator     const_iterator;
947    typedef typename Base::bucket_ptr         bucket_ptr;
948    typedef typename Base::size_type          size_type;
949    typedef typename Base::hasher             hasher;
950    typedef typename Base::key_equal          key_equal;
951 
952    BOOST_INTRUSIVE_FORCEINLINE
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 ())953    explicit unordered_multiset( const bucket_traits &b_traits
954                               , const hasher & hash_func = hasher()
955                               , const key_equal &equal_func = key_equal()
956                               , const value_traits &v_traits = value_traits())
957       :  Base(b_traits, hash_func, equal_func, v_traits)
958    {}
959 
960    template<class Iterator>
961    BOOST_INTRUSIVE_FORCEINLINE
unordered_multiset(Iterator b,Iterator e,const bucket_traits & b_traits,const hasher & hash_func=hasher (),const key_equal & equal_func=key_equal (),const value_traits & v_traits=value_traits ())962    unordered_multiset( Iterator b
963                      , Iterator e
964                      , const bucket_traits &b_traits
965                      , const hasher & hash_func = hasher()
966                      , const key_equal &equal_func = key_equal()
967                      , const value_traits &v_traits = value_traits())
968       :  Base(b, e, b_traits, hash_func, equal_func, v_traits)
969    {}
970 
unordered_multiset(BOOST_RV_REF (unordered_multiset)x)971    BOOST_INTRUSIVE_FORCEINLINE unordered_multiset(BOOST_RV_REF(unordered_multiset) x)
972       :  Base(BOOST_MOVE_BASE(Base, x))
973    {}
974 
operator =(BOOST_RV_REF (unordered_multiset)x)975    BOOST_INTRUSIVE_FORCEINLINE unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
976    {  return static_cast<unordered_multiset&>(this->Base::operator=(BOOST_MOVE_BASE(Base, x)));  }
977 
978    template <class Cloner, class Disposer>
clone_from(const unordered_multiset & src,Cloner cloner,Disposer disposer)979    BOOST_INTRUSIVE_FORCEINLINE void clone_from(const unordered_multiset &src, Cloner cloner, Disposer disposer)
980    {  Base::clone_from(src, cloner, disposer);  }
981 
982    template <class Cloner, class Disposer>
clone_from(BOOST_RV_REF (unordered_multiset)src,Cloner cloner,Disposer disposer)983    BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_multiset) src, Cloner cloner, Disposer disposer)
984    {  Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer);  }
985 };
986 
987 #endif
988 
989 } //namespace intrusive
990 } //namespace boost
991 
992 #include <boost/intrusive/detail/config_end.hpp>
993 
994 #endif //BOOST_INTRUSIVE_UNORDERED_SET_HPP
995