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