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

source code of boost/libs/intrusive/include/boost/intrusive/unordered_set.hpp