Line data Source code
1 :
2 : // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
3 : // Copyright (C) 2005-2011 Daniel James.
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 :
7 : // See http://www.boost.org/libs/unordered for documentation
8 :
9 : #ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
10 : #define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
11 :
12 : #include <boost/config.hpp>
13 : #if defined(BOOST_HAS_PRAGMA_ONCE)
14 : #pragma once
15 : #endif
16 :
17 : #include <boost/core/explicit_operator_bool.hpp>
18 : #include <boost/functional/hash.hpp>
19 : #include <boost/move/move.hpp>
20 : #include <boost/unordered/detail/set.hpp>
21 :
22 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
23 : #include <initializer_list>
24 : #endif
25 :
26 : #if defined(BOOST_MSVC)
27 : #pragma warning(push)
28 : // conditional expression is constant
29 : #pragma warning(disable : 4127)
30 : #if BOOST_MSVC >= 1400
31 : // the inline specifier cannot be used when a friend declaration refers to a
32 : // specialization of a function template
33 : #pragma warning(disable : 4396)
34 : #endif
35 : #endif
36 :
37 : namespace boost {
38 : namespace unordered {
39 : template <class T, class H, class P, class A> class unordered_set
40 : {
41 : #if defined(BOOST_UNORDERED_USE_MOVE)
42 : BOOST_COPYABLE_AND_MOVABLE(unordered_set)
43 : #endif
44 : template <typename, typename, typename, typename>
45 : friend class unordered_multiset;
46 :
47 : public:
48 : typedef T key_type;
49 : typedef T value_type;
50 : typedef H hasher;
51 : typedef P key_equal;
52 : typedef A allocator_type;
53 :
54 : private:
55 : typedef boost::unordered::detail::set<A, T, H, P> types;
56 : typedef typename types::value_allocator_traits value_allocator_traits;
57 : typedef typename types::table table;
58 : typedef typename table::node_pointer node_pointer;
59 : typedef typename table::link_pointer link_pointer;
60 :
61 : public:
62 : typedef typename value_allocator_traits::pointer pointer;
63 : typedef typename value_allocator_traits::const_pointer const_pointer;
64 :
65 : typedef value_type& reference;
66 : typedef value_type const& const_reference;
67 :
68 : typedef std::size_t size_type;
69 : typedef std::ptrdiff_t difference_type;
70 :
71 : typedef typename table::iterator iterator;
72 : typedef typename table::c_iterator const_iterator;
73 : typedef typename table::l_iterator local_iterator;
74 : typedef typename table::cl_iterator const_local_iterator;
75 : typedef typename types::node_type node_type;
76 : typedef typename types::insert_return_type insert_return_type;
77 :
78 : private:
79 : table table_;
80 :
81 : public:
82 : // constructors
83 :
84 : unordered_set();
85 :
86 : explicit unordered_set(size_type, const hasher& = hasher(),
87 : const key_equal& = key_equal(),
88 : const allocator_type& = allocator_type());
89 :
90 : template <class InputIt>
91 : unordered_set(InputIt, InputIt,
92 : size_type = boost::unordered::detail::default_bucket_count,
93 : const hasher& = hasher(), const key_equal& = key_equal(),
94 : const allocator_type& = allocator_type());
95 :
96 : unordered_set(unordered_set const&);
97 :
98 : #if defined(BOOST_UNORDERED_USE_MOVE) || \
99 : !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
100 : unordered_set(BOOST_RV_REF(unordered_set) other)
101 : BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
102 : : table_(other.table_, boost::unordered::detail::move_tag())
103 : {
104 : // The move is done in table_
105 : }
106 : #endif
107 :
108 : explicit unordered_set(allocator_type const&);
109 :
110 : unordered_set(unordered_set const&, allocator_type const&);
111 :
112 : unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
113 :
114 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
115 : unordered_set(std::initializer_list<value_type>,
116 : size_type = boost::unordered::detail::default_bucket_count,
117 : const hasher& = hasher(), const key_equal& l = key_equal(),
118 : const allocator_type& = allocator_type());
119 : #endif
120 :
121 : explicit unordered_set(size_type, const allocator_type&);
122 :
123 : explicit unordered_set(size_type, const hasher&, const allocator_type&);
124 :
125 : template <class InputIt>
126 : unordered_set(InputIt, InputIt, size_type, const allocator_type&);
127 :
128 : template <class InputIt>
129 : unordered_set(
130 : InputIt, InputIt, size_type, const hasher&, const allocator_type&);
131 :
132 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
133 : unordered_set(
134 : std::initializer_list<value_type>, size_type, const allocator_type&);
135 :
136 : unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
137 : const allocator_type&);
138 : #endif
139 :
140 : // Destructor
141 :
142 : ~unordered_set() BOOST_NOEXCEPT;
143 :
144 : // Assign
145 :
146 : #if defined(BOOST_UNORDERED_USE_MOVE)
147 : unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
148 : {
149 : table_.assign(x.table_, boost::unordered::detail::true_type());
150 : return *this;
151 : }
152 :
153 : unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
154 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
155 : boost::is_nothrow_move_assignable<H>::value&&
156 : boost::is_nothrow_move_assignable<P>::value)
157 : {
158 : table_.move_assign(x.table_, boost::unordered::detail::true_type());
159 : return *this;
160 : }
161 : #else
162 : unordered_set& operator=(unordered_set const& x)
163 : {
164 : table_.assign(x.table_, boost::unordered::detail::true_type());
165 : return *this;
166 : }
167 :
168 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
169 : unordered_set& operator=(unordered_set&& x)
170 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
171 : boost::is_nothrow_move_assignable<H>::value&&
172 : boost::is_nothrow_move_assignable<P>::value)
173 : {
174 : table_.move_assign(x.table_, boost::unordered::detail::true_type());
175 : return *this;
176 : }
177 : #endif
178 : #endif
179 :
180 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
181 : unordered_set& operator=(std::initializer_list<value_type>);
182 : #endif
183 :
184 : allocator_type get_allocator() const BOOST_NOEXCEPT
185 : {
186 : return table_.node_alloc();
187 : }
188 :
189 : // iterators
190 :
191 0 : iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
192 :
193 0 : const_iterator begin() const BOOST_NOEXCEPT
194 : {
195 0 : return const_iterator(table_.begin());
196 : }
197 :
198 0 : iterator end() BOOST_NOEXCEPT { return iterator(); }
199 :
200 0 : const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); }
201 :
202 : const_iterator cbegin() const BOOST_NOEXCEPT
203 : {
204 : return const_iterator(table_.begin());
205 : }
206 :
207 : const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
208 :
209 : // size and capacity
210 :
211 : bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
212 :
213 : size_type size() const BOOST_NOEXCEPT { return table_.size_; }
214 :
215 : size_type max_size() const BOOST_NOEXCEPT;
216 :
217 : // emplace
218 :
219 : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
220 :
221 : template <class... Args>
222 0 : std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
223 : {
224 : return table_.emplace_unique(
225 0 : table::extractor::extract(boost::forward<Args>(args)...),
226 0 : boost::forward<Args>(args)...);
227 : }
228 :
229 : #else
230 :
231 : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
232 :
233 : // 0 argument emplace requires special treatment in case
234 : // the container is instantiated with a value type that
235 : // doesn't have a default constructor.
236 :
237 : std::pair<iterator, bool> emplace(
238 : boost::unordered::detail::empty_emplace =
239 : boost::unordered::detail::empty_emplace(),
240 : value_type v = value_type())
241 : {
242 : return this->emplace(boost::move(v));
243 : }
244 :
245 : #endif
246 :
247 : template <typename A0>
248 : std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
249 : {
250 : return table_.emplace_unique(
251 : table::extractor::extract(boost::forward<A0>(a0)),
252 : boost::unordered::detail::create_emplace_args(
253 : boost::forward<A0>(a0)));
254 : }
255 :
256 : template <typename A0, typename A1>
257 : std::pair<iterator, bool> emplace(
258 : BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
259 : {
260 : return table_.emplace_unique(
261 : table::extractor::extract(
262 : boost::forward<A0>(a0), boost::forward<A1>(a1)),
263 : boost::unordered::detail::create_emplace_args(
264 : boost::forward<A0>(a0), boost::forward<A1>(a1)));
265 : }
266 :
267 : template <typename A0, typename A1, typename A2>
268 : std::pair<iterator, bool> emplace(
269 : BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
270 : {
271 : return table_.emplace_unique(
272 : table::extractor::extract(
273 : boost::forward<A0>(a0), boost::forward<A1>(a1)),
274 : boost::unordered::detail::create_emplace_args(boost::forward<A0>(a0),
275 : boost::forward<A1>(a1), boost::forward<A2>(a2)));
276 : }
277 :
278 : #endif
279 :
280 : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
281 :
282 : template <class... Args>
283 : iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
284 : {
285 : return table_.emplace_hint_unique(hint,
286 : table::extractor::extract(boost::forward<Args>(args)...),
287 : boost::forward<Args>(args)...);
288 : }
289 :
290 : #else
291 :
292 : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
293 :
294 : iterator emplace_hint(const_iterator hint,
295 : boost::unordered::detail::empty_emplace =
296 : boost::unordered::detail::empty_emplace(),
297 : value_type v = value_type())
298 : {
299 : return this->emplace_hint(hint, boost::move(v));
300 : }
301 :
302 : #endif
303 :
304 : template <typename A0>
305 : iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
306 : {
307 : return table_.emplace_hint_unique(hint,
308 : table::extractor::extract(boost::forward<A0>(a0)),
309 : boost::unordered::detail::create_emplace_args(
310 : boost::forward<A0>(a0)));
311 : }
312 :
313 : template <typename A0, typename A1>
314 : iterator emplace_hint(
315 : const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
316 : {
317 : return table_.emplace_hint_unique(hint,
318 : table::extractor::extract(
319 : boost::forward<A0>(a0), boost::forward<A1>(a1)),
320 : boost::unordered::detail::create_emplace_args(
321 : boost::forward<A0>(a0), boost::forward<A1>(a1)));
322 : }
323 :
324 : template <typename A0, typename A1, typename A2>
325 : iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
326 : BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
327 : {
328 : return table_.emplace_hint_unique(hint,
329 : table::extractor::extract(
330 : boost::forward<A0>(a0), boost::forward<A1>(a1)),
331 : boost::unordered::detail::create_emplace_args(boost::forward<A0>(a0),
332 : boost::forward<A1>(a1), boost::forward<A2>(a2)));
333 : }
334 :
335 : #endif
336 :
337 : #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
338 :
339 : #define BOOST_UNORDERED_EMPLACE(z, n, _) \
340 : template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
341 : std::pair<iterator, bool> emplace( \
342 : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
343 : { \
344 : return table_.emplace_unique( \
345 : table::extractor::extract( \
346 : boost::forward<A0>(a0), boost::forward<A1>(a1)), \
347 : boost::unordered::detail::create_emplace_args( \
348 : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
349 : } \
350 : \
351 : template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
352 : iterator emplace_hint( \
353 : const_iterator hint, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
354 : { \
355 : return table_.emplace_hint_unique(hint, \
356 : table::extractor::extract( \
357 : boost::forward<A0>(a0), boost::forward<A1>(a1)), \
358 : boost::unordered::detail::create_emplace_args( \
359 : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
360 : }
361 :
362 : BOOST_UNORDERED_EMPLACE(1, 4, _)
363 : BOOST_UNORDERED_EMPLACE(1, 5, _)
364 : BOOST_UNORDERED_EMPLACE(1, 6, _)
365 : BOOST_UNORDERED_EMPLACE(1, 7, _)
366 : BOOST_UNORDERED_EMPLACE(1, 8, _)
367 : BOOST_UNORDERED_EMPLACE(1, 9, _)
368 : BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
369 : BOOST_UNORDERED_EMPLACE, _)
370 :
371 : #undef BOOST_UNORDERED_EMPLACE
372 :
373 : #endif
374 :
375 0 : std::pair<iterator, bool> insert(value_type const& x)
376 : {
377 0 : return this->emplace(x);
378 : }
379 :
380 0 : std::pair<iterator, bool> insert(BOOST_UNORDERED_RV_REF(value_type) x)
381 : {
382 0 : return this->emplace(boost::move(x));
383 : }
384 :
385 : iterator insert(const_iterator hint, value_type const& x)
386 : {
387 : return this->emplace_hint(hint, x);
388 : }
389 :
390 : iterator insert(const_iterator hint, BOOST_UNORDERED_RV_REF(value_type) x)
391 : {
392 : return this->emplace_hint(hint, boost::move(x));
393 : }
394 :
395 : template <class InputIt> void insert(InputIt, InputIt);
396 :
397 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
398 : void insert(std::initializer_list<value_type>);
399 : #endif
400 :
401 : // extract
402 :
403 : node_type extract(const_iterator position)
404 : {
405 : return node_type(
406 : table_.extract_by_iterator_unique(position), table_.node_alloc());
407 : }
408 :
409 : node_type extract(const key_type& k)
410 : {
411 : return node_type(table_.extract_by_key(k), table_.node_alloc());
412 : }
413 :
414 : insert_return_type insert(BOOST_RV_REF(node_type) np)
415 : {
416 : insert_return_type result;
417 : table_.move_insert_node_type_unique(np, result);
418 : return boost::move(result);
419 : }
420 :
421 : iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
422 : {
423 : return table_.move_insert_node_type_with_hint_unique(hint, np);
424 : }
425 :
426 : #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
427 : (BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 6, 0))
428 : private:
429 : // Note: Use r-value node_type to insert.
430 : insert_return_type insert(node_type&);
431 : iterator insert(const_iterator, node_type& np);
432 :
433 : public:
434 : #endif
435 :
436 : iterator erase(const_iterator);
437 : size_type erase(const key_type&);
438 : iterator erase(const_iterator, const_iterator);
439 : BOOST_UNORDERED_DEPRECATED("Use erase instead")
440 : void quick_erase(const_iterator it) { erase(it); }
441 : BOOST_UNORDERED_DEPRECATED("Use erase instead")
442 : void erase_return_void(const_iterator it) { erase(it); }
443 :
444 : void swap(unordered_set&)
445 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
446 : boost::is_nothrow_swappable<H>::value&&
447 : boost::is_nothrow_swappable<P>::value);
448 0 : void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
449 :
450 : template <typename H2, typename P2>
451 : void merge(boost::unordered_set<T, H2, P2, A>& source);
452 :
453 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
454 : template <typename H2, typename P2>
455 : void merge(boost::unordered_set<T, H2, P2, A>&& source);
456 : #endif
457 :
458 : template <typename H2, typename P2>
459 : void merge(boost::unordered_multiset<T, H2, P2, A>& source);
460 :
461 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
462 : template <typename H2, typename P2>
463 : void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
464 : #endif
465 :
466 : // observers
467 :
468 : hasher hash_function() const;
469 : key_equal key_eq() const;
470 :
471 : // lookup
472 :
473 : const_iterator find(const key_type&) const;
474 :
475 : template <class CompatibleKey, class CompatibleHash,
476 : class CompatiblePredicate>
477 : const_iterator find(CompatibleKey const&, CompatibleHash const&,
478 : CompatiblePredicate const&) const;
479 :
480 : size_type count(const key_type&) const;
481 :
482 : std::pair<const_iterator, const_iterator> equal_range(
483 : const key_type&) const;
484 :
485 : // bucket interface
486 :
487 : size_type bucket_count() const BOOST_NOEXCEPT
488 : {
489 : return table_.bucket_count_;
490 : }
491 :
492 : size_type max_bucket_count() const BOOST_NOEXCEPT
493 : {
494 : return table_.max_bucket_count();
495 : }
496 :
497 : size_type bucket_size(size_type) const;
498 :
499 : size_type bucket(const key_type& k) const
500 : {
501 : return table_.hash_to_bucket(table_.hash(k));
502 : }
503 :
504 : local_iterator begin(size_type n)
505 : {
506 : return local_iterator(table_.begin(n), n, table_.bucket_count_);
507 : }
508 :
509 : const_local_iterator begin(size_type n) const
510 : {
511 : return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
512 : }
513 :
514 : local_iterator end(size_type) { return local_iterator(); }
515 :
516 : const_local_iterator end(size_type) const
517 : {
518 : return const_local_iterator();
519 : }
520 :
521 : const_local_iterator cbegin(size_type n) const
522 : {
523 : return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
524 : }
525 :
526 : const_local_iterator cend(size_type) const
527 : {
528 : return const_local_iterator();
529 : }
530 :
531 : // hash policy
532 :
533 : float load_factor() const BOOST_NOEXCEPT;
534 : float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
535 : void max_load_factor(float) BOOST_NOEXCEPT;
536 : void rehash(size_type);
537 : void reserve(size_type);
538 :
539 : #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
540 : friend bool operator==
541 : <T, H, P, A>(unordered_set const&, unordered_set const&);
542 : friend bool operator!=
543 : <T, H, P, A>(unordered_set const&, unordered_set const&);
544 : #endif
545 : }; // class template unordered_set
546 :
547 : #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
548 :
549 : template <class InputIterator,
550 : class Hash =
551 : boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
552 : class Pred =
553 : std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
554 : class Allocator = std::allocator<
555 : typename std::iterator_traits<InputIterator>::value_type> >
556 : unordered_set(InputIterator, InputIterator,
557 : std::size_t = boost::unordered::detail::default_bucket_count,
558 : Hash = Hash(), Pred = Pred(), Allocator = Allocator())
559 : ->unordered_set<typename std::iterator_traits<InputIterator>::value_type,
560 : Hash, Pred, Allocator>;
561 :
562 : template <class T, class Hash = boost::hash<T>,
563 : class Pred = std::equal_to<T>, class Allocator = std::allocator<T> >
564 : unordered_set(std::initializer_list<T>,
565 : std::size_t = boost::unordered::detail::default_bucket_count,
566 : Hash = Hash(), Pred = Pred(), Allocator = Allocator())
567 : ->unordered_set<T, Hash, Pred, Allocator>;
568 :
569 : template <class InputIterator, class Allocator>
570 : unordered_set(InputIterator, InputIterator, std::size_t, Allocator)
571 : ->unordered_set<typename std::iterator_traits<InputIterator>::value_type,
572 : boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
573 : std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
574 : Allocator>;
575 :
576 : template <class InputIterator, class Hash, class Allocator>
577 : unordered_set(InputIterator, InputIterator, std::size_t, Hash, Allocator)
578 : ->unordered_set<typename std::iterator_traits<InputIterator>::value_type,
579 : Hash,
580 : std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
581 : Allocator>;
582 :
583 : template <class T, class Allocator>
584 : unordered_set(std::initializer_list<T>, std::size_t, Allocator)
585 : ->unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
586 :
587 : template <class T, class Hash, class Allocator>
588 : unordered_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
589 : ->unordered_set<T, Hash, std::equal_to<T>, Allocator>;
590 :
591 : #endif
592 :
593 : template <class T, class H, class P, class A> class unordered_multiset
594 : {
595 : #if defined(BOOST_UNORDERED_USE_MOVE)
596 : BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
597 : #endif
598 : template <typename, typename, typename, typename>
599 : friend class unordered_set;
600 :
601 : public:
602 : typedef T key_type;
603 : typedef T value_type;
604 : typedef H hasher;
605 : typedef P key_equal;
606 : typedef A allocator_type;
607 :
608 : private:
609 : typedef boost::unordered::detail::set<A, T, H, P> types;
610 : typedef typename types::value_allocator_traits value_allocator_traits;
611 : typedef typename types::table table;
612 : typedef typename table::node_pointer node_pointer;
613 : typedef typename table::link_pointer link_pointer;
614 :
615 : public:
616 : typedef typename value_allocator_traits::pointer pointer;
617 : typedef typename value_allocator_traits::const_pointer const_pointer;
618 :
619 : typedef value_type& reference;
620 : typedef value_type const& const_reference;
621 :
622 : typedef std::size_t size_type;
623 : typedef std::ptrdiff_t difference_type;
624 :
625 : typedef typename table::iterator iterator;
626 : typedef typename table::c_iterator const_iterator;
627 : typedef typename table::l_iterator local_iterator;
628 : typedef typename table::cl_iterator const_local_iterator;
629 : typedef typename types::node_type node_type;
630 :
631 : private:
632 : table table_;
633 :
634 : public:
635 : // constructors
636 :
637 : unordered_multiset();
638 :
639 : explicit unordered_multiset(size_type, const hasher& = hasher(),
640 : const key_equal& = key_equal(),
641 : const allocator_type& = allocator_type());
642 :
643 : template <class InputIt>
644 : unordered_multiset(InputIt, InputIt,
645 : size_type = boost::unordered::detail::default_bucket_count,
646 : const hasher& = hasher(), const key_equal& = key_equal(),
647 : const allocator_type& = allocator_type());
648 :
649 : unordered_multiset(unordered_multiset const&);
650 :
651 : #if defined(BOOST_UNORDERED_USE_MOVE) || \
652 : !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
653 : unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
654 : BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
655 : : table_(other.table_, boost::unordered::detail::move_tag())
656 : {
657 : // The move is done in table_
658 : }
659 : #endif
660 :
661 : explicit unordered_multiset(allocator_type const&);
662 :
663 : unordered_multiset(unordered_multiset const&, allocator_type const&);
664 :
665 : unordered_multiset(
666 : BOOST_RV_REF(unordered_multiset), allocator_type const&);
667 :
668 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
669 : unordered_multiset(std::initializer_list<value_type>,
670 : size_type = boost::unordered::detail::default_bucket_count,
671 : const hasher& = hasher(), const key_equal& l = key_equal(),
672 : const allocator_type& = allocator_type());
673 : #endif
674 :
675 : explicit unordered_multiset(size_type, const allocator_type&);
676 :
677 : explicit unordered_multiset(
678 : size_type, const hasher&, const allocator_type&);
679 :
680 : template <class InputIt>
681 : unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
682 :
683 : template <class InputIt>
684 : unordered_multiset(
685 : InputIt, InputIt, size_type, const hasher&, const allocator_type&);
686 :
687 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
688 : unordered_multiset(
689 : std::initializer_list<value_type>, size_type, const allocator_type&);
690 :
691 : unordered_multiset(std::initializer_list<value_type>, size_type,
692 : const hasher&, const allocator_type&);
693 : #endif
694 :
695 : // Destructor
696 :
697 : ~unordered_multiset() BOOST_NOEXCEPT;
698 :
699 : // Assign
700 :
701 : #if defined(BOOST_UNORDERED_USE_MOVE)
702 : unordered_multiset& operator=(BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
703 : {
704 : table_.assign(x.table_, boost::unordered::detail::false_type());
705 : return *this;
706 : }
707 :
708 : unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
709 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
710 : boost::is_nothrow_move_assignable<H>::value&&
711 : boost::is_nothrow_move_assignable<P>::value)
712 : {
713 : table_.move_assign(x.table_, boost::unordered::detail::false_type());
714 : return *this;
715 : }
716 : #else
717 : unordered_multiset& operator=(unordered_multiset const& x)
718 : {
719 : table_.assign(x.table_, boost::unordered::detail::false_type());
720 : return *this;
721 : }
722 :
723 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
724 : unordered_multiset& operator=(unordered_multiset&& x)
725 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
726 : boost::is_nothrow_move_assignable<H>::value&&
727 : boost::is_nothrow_move_assignable<P>::value)
728 : {
729 : table_.move_assign(x.table_, boost::unordered::detail::false_type());
730 : return *this;
731 : }
732 : #endif
733 : #endif
734 :
735 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
736 : unordered_multiset& operator=(std::initializer_list<value_type>);
737 : #endif
738 :
739 : allocator_type get_allocator() const BOOST_NOEXCEPT
740 : {
741 : return table_.node_alloc();
742 : }
743 :
744 : // iterators
745 :
746 : iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
747 :
748 : const_iterator begin() const BOOST_NOEXCEPT
749 : {
750 : return const_iterator(table_.begin());
751 : }
752 :
753 : iterator end() BOOST_NOEXCEPT { return iterator(); }
754 :
755 : const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); }
756 :
757 : const_iterator cbegin() const BOOST_NOEXCEPT
758 : {
759 : return const_iterator(table_.begin());
760 : }
761 :
762 : const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
763 :
764 : // size and capacity
765 :
766 : bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
767 :
768 : size_type size() const BOOST_NOEXCEPT { return table_.size_; }
769 :
770 : size_type max_size() const BOOST_NOEXCEPT;
771 :
772 : // emplace
773 :
774 : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
775 :
776 : template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
777 : {
778 : return iterator(table_.emplace_equiv(
779 : boost::unordered::detail::func::construct_node_from_args(
780 : table_.node_alloc(), boost::forward<Args>(args)...)));
781 : }
782 :
783 : #else
784 :
785 : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
786 :
787 : // 0 argument emplace requires special treatment in case
788 : // the container is instantiated with a value type that
789 : // doesn't have a default constructor.
790 :
791 : iterator emplace(boost::unordered::detail::empty_emplace =
792 : boost::unordered::detail::empty_emplace(),
793 : value_type v = value_type())
794 : {
795 : return this->emplace(boost::move(v));
796 : }
797 :
798 : #endif
799 :
800 : template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
801 : {
802 : return iterator(table_.emplace_equiv(
803 : boost::unordered::detail::func::construct_node_from_args(
804 : table_.node_alloc(), boost::unordered::detail::create_emplace_args(
805 : boost::forward<A0>(a0)))));
806 : }
807 :
808 : template <typename A0, typename A1>
809 : iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
810 : {
811 : return iterator(table_.emplace_equiv(
812 : boost::unordered::detail::func::construct_node_from_args(
813 : table_.node_alloc(),
814 : boost::unordered::detail::create_emplace_args(
815 : boost::forward<A0>(a0), boost::forward<A1>(a1)))));
816 : }
817 :
818 : template <typename A0, typename A1, typename A2>
819 : iterator emplace(
820 : BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
821 : {
822 : return iterator(table_.emplace_equiv(
823 : boost::unordered::detail::func::construct_node_from_args(
824 : table_.node_alloc(),
825 : boost::unordered::detail::create_emplace_args(
826 : boost::forward<A0>(a0), boost::forward<A1>(a1),
827 : boost::forward<A2>(a2)))));
828 : }
829 :
830 : #endif
831 :
832 : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
833 :
834 : template <class... Args>
835 : iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
836 : {
837 : return iterator(table_.emplace_hint_equiv(
838 : hint, boost::unordered::detail::func::construct_node_from_args(
839 : table_.node_alloc(), boost::forward<Args>(args)...)));
840 : }
841 :
842 : #else
843 :
844 : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
845 :
846 : iterator emplace_hint(const_iterator hint,
847 : boost::unordered::detail::empty_emplace =
848 : boost::unordered::detail::empty_emplace(),
849 : value_type v = value_type())
850 : {
851 : return this->emplace_hint(hint, boost::move(v));
852 : }
853 :
854 : #endif
855 :
856 : template <typename A0>
857 : iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
858 : {
859 : return iterator(table_.emplace_hint_equiv(hint,
860 : boost::unordered::detail::func::construct_node_from_args(
861 : table_.node_alloc(), boost::unordered::detail::create_emplace_args(
862 : boost::forward<A0>(a0)))));
863 : }
864 :
865 : template <typename A0, typename A1>
866 : iterator emplace_hint(
867 : const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
868 : {
869 : return iterator(table_.emplace_hint_equiv(
870 : hint, boost::unordered::detail::func::construct_node_from_args(
871 : table_.node_alloc(),
872 : boost::unordered::detail::create_emplace_args(
873 : boost::forward<A0>(a0), boost::forward<A1>(a1)))));
874 : }
875 :
876 : template <typename A0, typename A1, typename A2>
877 : iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
878 : BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
879 : {
880 : return iterator(table_.emplace_hint_equiv(
881 : hint, boost::unordered::detail::func::construct_node_from_args(
882 : table_.node_alloc(),
883 : boost::unordered::detail::create_emplace_args(
884 : boost::forward<A0>(a0), boost::forward<A1>(a1),
885 : boost::forward<A2>(a2)))));
886 : }
887 :
888 : #endif
889 :
890 : #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
891 :
892 : #define BOOST_UNORDERED_EMPLACE(z, n, _) \
893 : template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
894 : iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
895 : { \
896 : return iterator(table_.emplace_equiv( \
897 : boost::unordered::detail::func::construct_node_from_args( \
898 : table_.node_alloc(), \
899 : boost::unordered::detail::create_emplace_args( \
900 : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
901 : } \
902 : \
903 : template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
904 : iterator emplace_hint( \
905 : const_iterator hint, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
906 : { \
907 : return iterator(table_.emplace_hint_equiv( \
908 : hint, boost::unordered::detail::func::construct_node_from_args( \
909 : table_.node_alloc(), \
910 : boost::unordered::detail::create_emplace_args( \
911 : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
912 : }
913 :
914 : BOOST_UNORDERED_EMPLACE(1, 4, _)
915 : BOOST_UNORDERED_EMPLACE(1, 5, _)
916 : BOOST_UNORDERED_EMPLACE(1, 6, _)
917 : BOOST_UNORDERED_EMPLACE(1, 7, _)
918 : BOOST_UNORDERED_EMPLACE(1, 8, _)
919 : BOOST_UNORDERED_EMPLACE(1, 9, _)
920 : BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
921 : BOOST_UNORDERED_EMPLACE, _)
922 :
923 : #undef BOOST_UNORDERED_EMPLACE
924 :
925 : #endif
926 :
927 : iterator insert(value_type const& x) { return this->emplace(x); }
928 :
929 : iterator insert(BOOST_UNORDERED_RV_REF(value_type) x)
930 : {
931 : return this->emplace(boost::move(x));
932 : }
933 :
934 : iterator insert(const_iterator hint, value_type const& x)
935 : {
936 : return this->emplace_hint(hint, x);
937 : }
938 :
939 : iterator insert(const_iterator hint, BOOST_UNORDERED_RV_REF(value_type) x)
940 : {
941 : return this->emplace_hint(hint, boost::move(x));
942 : }
943 :
944 : template <class InputIt> void insert(InputIt, InputIt);
945 :
946 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
947 : void insert(std::initializer_list<value_type>);
948 : #endif
949 :
950 : // extract
951 :
952 : node_type extract(const_iterator position)
953 : {
954 : return node_type(
955 : table_.extract_by_iterator_equiv(position), table_.node_alloc());
956 : }
957 :
958 : node_type extract(const key_type& k)
959 : {
960 : return node_type(table_.extract_by_key(k), table_.node_alloc());
961 : }
962 :
963 : iterator insert(BOOST_RV_REF(node_type) np)
964 : {
965 : return table_.move_insert_node_type_equiv(np);
966 : }
967 :
968 : iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
969 : {
970 : return table_.move_insert_node_type_with_hint_equiv(hint, np);
971 : }
972 :
973 : #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
974 : (BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 6, 0))
975 : private:
976 : // Note: Use r-value node_type to insert.
977 : iterator insert(node_type&);
978 : iterator insert(const_iterator, node_type& np);
979 :
980 : public:
981 : #endif
982 :
983 : iterator erase(const_iterator);
984 : size_type erase(const key_type&);
985 : iterator erase(const_iterator, const_iterator);
986 : BOOST_UNORDERED_DEPRECATED("Use erase instead")
987 : void quick_erase(const_iterator it) { erase(it); }
988 : BOOST_UNORDERED_DEPRECATED("Use erase instead")
989 : void erase_return_void(const_iterator it) { erase(it); }
990 :
991 : void swap(unordered_multiset&)
992 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
993 : boost::is_nothrow_swappable<H>::value&&
994 : boost::is_nothrow_swappable<P>::value);
995 : void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
996 :
997 : template <typename H2, typename P2>
998 : void merge(boost::unordered_multiset<T, H2, P2, A>& source);
999 :
1000 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1001 : template <typename H2, typename P2>
1002 : void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
1003 : #endif
1004 :
1005 : template <typename H2, typename P2>
1006 : void merge(boost::unordered_set<T, H2, P2, A>& source);
1007 :
1008 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1009 : template <typename H2, typename P2>
1010 : void merge(boost::unordered_set<T, H2, P2, A>&& source);
1011 : #endif
1012 :
1013 : // observers
1014 :
1015 : hasher hash_function() const;
1016 : key_equal key_eq() const;
1017 :
1018 : // lookup
1019 :
1020 : const_iterator find(const key_type&) const;
1021 :
1022 : template <class CompatibleKey, class CompatibleHash,
1023 : class CompatiblePredicate>
1024 : const_iterator find(CompatibleKey const&, CompatibleHash const&,
1025 : CompatiblePredicate const&) const;
1026 :
1027 : size_type count(const key_type&) const;
1028 :
1029 : std::pair<const_iterator, const_iterator> equal_range(
1030 : const key_type&) const;
1031 :
1032 : // bucket interface
1033 :
1034 : size_type bucket_count() const BOOST_NOEXCEPT
1035 : {
1036 : return table_.bucket_count_;
1037 : }
1038 :
1039 : size_type max_bucket_count() const BOOST_NOEXCEPT
1040 : {
1041 : return table_.max_bucket_count();
1042 : }
1043 :
1044 : size_type bucket_size(size_type) const;
1045 :
1046 : size_type bucket(const key_type& k) const
1047 : {
1048 : return table_.hash_to_bucket(table_.hash(k));
1049 : }
1050 :
1051 : local_iterator begin(size_type n)
1052 : {
1053 : return local_iterator(table_.begin(n), n, table_.bucket_count_);
1054 : }
1055 :
1056 : const_local_iterator begin(size_type n) const
1057 : {
1058 : return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
1059 : }
1060 :
1061 : local_iterator end(size_type) { return local_iterator(); }
1062 :
1063 : const_local_iterator end(size_type) const
1064 : {
1065 : return const_local_iterator();
1066 : }
1067 :
1068 : const_local_iterator cbegin(size_type n) const
1069 : {
1070 : return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
1071 : }
1072 :
1073 : const_local_iterator cend(size_type) const
1074 : {
1075 : return const_local_iterator();
1076 : }
1077 :
1078 : // hash policy
1079 :
1080 : float load_factor() const BOOST_NOEXCEPT;
1081 : float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
1082 : void max_load_factor(float) BOOST_NOEXCEPT;
1083 : void rehash(size_type);
1084 : void reserve(size_type);
1085 :
1086 : #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
1087 : friend bool operator==
1088 : <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
1089 : friend bool operator!=
1090 : <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
1091 : #endif
1092 : }; // class template unordered_multiset
1093 :
1094 : #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
1095 :
1096 : template <class InputIterator,
1097 : class Hash =
1098 : boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
1099 : class Pred =
1100 : std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
1101 : class Allocator = std::allocator<
1102 : typename std::iterator_traits<InputIterator>::value_type> >
1103 : unordered_multiset(InputIterator, InputIterator,
1104 : std::size_t = boost::unordered::detail::default_bucket_count,
1105 : Hash = Hash(), Pred = Pred(), Allocator = Allocator())
1106 : ->unordered_multiset<
1107 : typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
1108 : Allocator>;
1109 :
1110 : template <class T, class Hash = boost::hash<T>,
1111 : class Pred = std::equal_to<T>, class Allocator = std::allocator<T> >
1112 : unordered_multiset(std::initializer_list<T>,
1113 : std::size_t = boost::unordered::detail::default_bucket_count,
1114 : Hash = Hash(), Pred = Pred(), Allocator = Allocator())
1115 : ->unordered_multiset<T, Hash, Pred, Allocator>;
1116 :
1117 : template <class InputIterator, class Allocator>
1118 : unordered_multiset(InputIterator, InputIterator, std::size_t, Allocator)
1119 : ->unordered_multiset<
1120 : typename std::iterator_traits<InputIterator>::value_type,
1121 : boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
1122 : std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
1123 : Allocator>;
1124 :
1125 : template <class InputIterator, class Hash, class Allocator>
1126 : unordered_multiset(
1127 : InputIterator, InputIterator, std::size_t, Hash, Allocator)
1128 : ->unordered_multiset<
1129 : typename std::iterator_traits<InputIterator>::value_type, Hash,
1130 : std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
1131 : Allocator>;
1132 :
1133 : template <class T, class Allocator>
1134 : unordered_multiset(std::initializer_list<T>, std::size_t, Allocator)
1135 : ->unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
1136 :
1137 : template <class T, class Hash, class Allocator>
1138 : unordered_multiset(std::initializer_list<T>, std::size_t, Hash, Allocator)
1139 : ->unordered_multiset<T, Hash, std::equal_to<T>, Allocator>;
1140 :
1141 : #endif
1142 :
1143 : ////////////////////////////////////////////////////////////////////////////
1144 : template <class T, class H, class P, class A>
1145 0 : unordered_set<T, H, P, A>::unordered_set()
1146 : : table_(boost::unordered::detail::default_bucket_count, hasher(),
1147 0 : key_equal(), allocator_type())
1148 : {
1149 : }
1150 :
1151 : template <class T, class H, class P, class A>
1152 : unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
1153 : const key_equal& eql, const allocator_type& a)
1154 : : table_(n, hf, eql, a)
1155 : {
1156 : }
1157 :
1158 : template <class T, class H, class P, class A>
1159 : template <class InputIt>
1160 : unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
1161 : const hasher& hf, const key_equal& eql, const allocator_type& a)
1162 : : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1163 : {
1164 : this->insert(f, l);
1165 : }
1166 :
1167 : template <class T, class H, class P, class A>
1168 : unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
1169 : : table_(other.table_,
1170 : unordered_set::value_allocator_traits::
1171 : select_on_container_copy_construction(other.get_allocator()))
1172 : {
1173 : if (other.table_.size_) {
1174 : table_.copy_buckets(
1175 : other.table_, boost::unordered::detail::true_type());
1176 : }
1177 : }
1178 :
1179 : template <class T, class H, class P, class A>
1180 : unordered_set<T, H, P, A>::unordered_set(allocator_type const& a)
1181 : : table_(boost::unordered::detail::default_bucket_count, hasher(),
1182 : key_equal(), a)
1183 : {
1184 : }
1185 :
1186 : template <class T, class H, class P, class A>
1187 : unordered_set<T, H, P, A>::unordered_set(
1188 : unordered_set const& other, allocator_type const& a)
1189 : : table_(other.table_, a)
1190 : {
1191 : if (other.table_.size_) {
1192 : table_.copy_buckets(
1193 : other.table_, boost::unordered::detail::true_type());
1194 : }
1195 : }
1196 :
1197 : template <class T, class H, class P, class A>
1198 : unordered_set<T, H, P, A>::unordered_set(
1199 : BOOST_RV_REF(unordered_set) other, allocator_type const& a)
1200 : : table_(other.table_, a, boost::unordered::detail::move_tag())
1201 : {
1202 : table_.move_construct_buckets(other.table_);
1203 : }
1204 :
1205 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1206 :
1207 : template <class T, class H, class P, class A>
1208 : unordered_set<T, H, P, A>::unordered_set(
1209 : std::initializer_list<value_type> list, size_type n, const hasher& hf,
1210 : const key_equal& eql, const allocator_type& a)
1211 : : table_(
1212 : boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1213 : hf, eql, a)
1214 : {
1215 : this->insert(list.begin(), list.end());
1216 : }
1217 :
1218 : #endif
1219 :
1220 : template <class T, class H, class P, class A>
1221 : unordered_set<T, H, P, A>::unordered_set(
1222 : size_type n, const allocator_type& a)
1223 : : table_(n, hasher(), key_equal(), a)
1224 : {
1225 : }
1226 :
1227 : template <class T, class H, class P, class A>
1228 : unordered_set<T, H, P, A>::unordered_set(
1229 : size_type n, const hasher& hf, const allocator_type& a)
1230 : : table_(n, hf, key_equal(), a)
1231 : {
1232 : }
1233 :
1234 : template <class T, class H, class P, class A>
1235 : template <class InputIt>
1236 : unordered_set<T, H, P, A>::unordered_set(
1237 : InputIt f, InputIt l, size_type n, const allocator_type& a)
1238 : : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1239 : key_equal(), a)
1240 : {
1241 : this->insert(f, l);
1242 : }
1243 :
1244 : template <class T, class H, class P, class A>
1245 : template <class InputIt>
1246 : unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
1247 : const hasher& hf, const allocator_type& a)
1248 : : table_(
1249 : boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1250 : {
1251 : this->insert(f, l);
1252 : }
1253 :
1254 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1255 :
1256 : template <class T, class H, class P, class A>
1257 : unordered_set<T, H, P, A>::unordered_set(
1258 : std::initializer_list<value_type> list, size_type n,
1259 : const allocator_type& a)
1260 : : table_(
1261 : boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1262 : hasher(), key_equal(), a)
1263 : {
1264 : this->insert(list.begin(), list.end());
1265 : }
1266 :
1267 : template <class T, class H, class P, class A>
1268 : unordered_set<T, H, P, A>::unordered_set(
1269 : std::initializer_list<value_type> list, size_type n, const hasher& hf,
1270 : const allocator_type& a)
1271 : : table_(
1272 : boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1273 : hf, key_equal(), a)
1274 : {
1275 : this->insert(list.begin(), list.end());
1276 : }
1277 :
1278 : #endif
1279 :
1280 : template <class T, class H, class P, class A>
1281 356 : unordered_set<T, H, P, A>::~unordered_set() BOOST_NOEXCEPT
1282 : {
1283 356 : }
1284 :
1285 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1286 :
1287 : template <class T, class H, class P, class A>
1288 : unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
1289 : std::initializer_list<value_type> list)
1290 : {
1291 : this->clear();
1292 : this->insert(list.begin(), list.end());
1293 : return *this;
1294 : }
1295 :
1296 : #endif
1297 :
1298 : // size and capacity
1299 :
1300 : template <class T, class H, class P, class A>
1301 : std::size_t unordered_set<T, H, P, A>::max_size() const BOOST_NOEXCEPT
1302 : {
1303 : using namespace std;
1304 :
1305 : // size < mlf_ * count
1306 : return boost::unordered::detail::double_to_size(
1307 : ceil(static_cast<double>(table_.mlf_) *
1308 : static_cast<double>(table_.max_bucket_count()))) -
1309 : 1;
1310 : }
1311 :
1312 : // modifiers
1313 :
1314 : template <class T, class H, class P, class A>
1315 : template <class InputIt>
1316 0 : void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last)
1317 : {
1318 0 : if (first != last) {
1319 0 : table_.insert_range_unique(
1320 0 : table::extractor::extract(*first), first, last);
1321 : }
1322 : }
1323 :
1324 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1325 : template <class T, class H, class P, class A>
1326 : void unordered_set<T, H, P, A>::insert(
1327 : std::initializer_list<value_type> list)
1328 : {
1329 : this->insert(list.begin(), list.end());
1330 : }
1331 : #endif
1332 :
1333 : template <class T, class H, class P, class A>
1334 : typename unordered_set<T, H, P, A>::iterator
1335 : unordered_set<T, H, P, A>::erase(const_iterator position)
1336 : {
1337 : node_pointer node = table::get_node(position);
1338 : BOOST_ASSERT(node);
1339 : node_pointer next = table::next_node(node);
1340 : table_.erase_nodes_unique(node, next);
1341 : return iterator(next);
1342 : }
1343 :
1344 : template <class T, class H, class P, class A>
1345 : typename unordered_set<T, H, P, A>::size_type
1346 0 : unordered_set<T, H, P, A>::erase(const key_type& k)
1347 : {
1348 0 : return table_.erase_key_unique(k);
1349 : }
1350 :
1351 : template <class T, class H, class P, class A>
1352 : typename unordered_set<T, H, P, A>::iterator
1353 : unordered_set<T, H, P, A>::erase(const_iterator first, const_iterator last)
1354 : {
1355 : node_pointer last_node = table::get_node(last);
1356 : if (first == last)
1357 : return iterator(last_node);
1358 : table_.erase_nodes_unique(table::get_node(first), last_node);
1359 : return iterator(last_node);
1360 : }
1361 :
1362 : template <class T, class H, class P, class A>
1363 : void unordered_set<T, H, P, A>::swap(unordered_set& other)
1364 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
1365 : boost::is_nothrow_swappable<H>::value&&
1366 : boost::is_nothrow_swappable<P>::value)
1367 : {
1368 : table_.swap(other.table_);
1369 : }
1370 :
1371 : // observers
1372 :
1373 : template <class T, class H, class P, class A>
1374 : typename unordered_set<T, H, P, A>::hasher
1375 : unordered_set<T, H, P, A>::hash_function() const
1376 : {
1377 : return table_.hash_function();
1378 : }
1379 :
1380 : template <class T, class H, class P, class A>
1381 : typename unordered_set<T, H, P, A>::key_equal
1382 : unordered_set<T, H, P, A>::key_eq() const
1383 : {
1384 : return table_.key_eq();
1385 : }
1386 :
1387 : template <class T, class H, class P, class A>
1388 : template <typename H2, typename P2>
1389 : void unordered_set<T, H, P, A>::merge(
1390 : boost::unordered_set<T, H2, P2, A>& source)
1391 : {
1392 : table_.merge_unique(source.table_);
1393 : }
1394 :
1395 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1396 : template <class T, class H, class P, class A>
1397 : template <typename H2, typename P2>
1398 : void unordered_set<T, H, P, A>::merge(
1399 : boost::unordered_set<T, H2, P2, A>&& source)
1400 : {
1401 : table_.merge_unique(source.table_);
1402 : }
1403 : #endif
1404 :
1405 : template <class T, class H, class P, class A>
1406 : template <typename H2, typename P2>
1407 : void unordered_set<T, H, P, A>::merge(
1408 : boost::unordered_multiset<T, H2, P2, A>& source)
1409 : {
1410 : table_.merge_unique(source.table_);
1411 : }
1412 :
1413 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1414 : template <class T, class H, class P, class A>
1415 : template <typename H2, typename P2>
1416 : void unordered_set<T, H, P, A>::merge(
1417 : boost::unordered_multiset<T, H2, P2, A>&& source)
1418 : {
1419 : table_.merge_unique(source.table_);
1420 : }
1421 : #endif
1422 :
1423 : // lookup
1424 :
1425 : template <class T, class H, class P, class A>
1426 : typename unordered_set<T, H, P, A>::const_iterator
1427 0 : unordered_set<T, H, P, A>::find(const key_type& k) const
1428 : {
1429 0 : return const_iterator(table_.find_node(k));
1430 : }
1431 :
1432 : template <class T, class H, class P, class A>
1433 : template <class CompatibleKey, class CompatibleHash,
1434 : class CompatiblePredicate>
1435 : typename unordered_set<T, H, P, A>::const_iterator
1436 : unordered_set<T, H, P, A>::find(CompatibleKey const& k,
1437 : CompatibleHash const& hash, CompatiblePredicate const& eq) const
1438 : {
1439 : return const_iterator(
1440 : table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
1441 : }
1442 :
1443 : template <class T, class H, class P, class A>
1444 : typename unordered_set<T, H, P, A>::size_type
1445 0 : unordered_set<T, H, P, A>::count(const key_type& k) const
1446 : {
1447 0 : return table_.find_node(k) ? 1 : 0;
1448 : }
1449 :
1450 : template <class T, class H, class P, class A>
1451 : std::pair<typename unordered_set<T, H, P, A>::const_iterator,
1452 : typename unordered_set<T, H, P, A>::const_iterator>
1453 : unordered_set<T, H, P, A>::equal_range(const key_type& k) const
1454 : {
1455 : node_pointer n = table_.find_node(k);
1456 : return std::make_pair(
1457 : const_iterator(n), const_iterator(n ? table::next_node(n) : n));
1458 : }
1459 :
1460 : template <class T, class H, class P, class A>
1461 : typename unordered_set<T, H, P, A>::size_type
1462 : unordered_set<T, H, P, A>::bucket_size(size_type n) const
1463 : {
1464 : return table_.bucket_size(n);
1465 : }
1466 :
1467 : // hash policy
1468 :
1469 : template <class T, class H, class P, class A>
1470 : float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
1471 : {
1472 : BOOST_ASSERT(table_.bucket_count_ != 0);
1473 : return static_cast<float>(table_.size_) /
1474 : static_cast<float>(table_.bucket_count_);
1475 : }
1476 :
1477 : template <class T, class H, class P, class A>
1478 : void unordered_set<T, H, P, A>::max_load_factor(float m) BOOST_NOEXCEPT
1479 : {
1480 : table_.max_load_factor(m);
1481 : }
1482 :
1483 : template <class T, class H, class P, class A>
1484 : void unordered_set<T, H, P, A>::rehash(size_type n)
1485 : {
1486 : table_.rehash(n);
1487 : }
1488 :
1489 : template <class T, class H, class P, class A>
1490 : void unordered_set<T, H, P, A>::reserve(size_type n)
1491 : {
1492 : table_.rehash(static_cast<std::size_t>(
1493 : std::ceil(static_cast<double>(n) / table_.mlf_)));
1494 : }
1495 :
1496 : template <class T, class H, class P, class A>
1497 : inline bool operator==(
1498 : unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
1499 : {
1500 : #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
1501 : struct dummy
1502 : {
1503 : unordered_set<T, H, P, A> x;
1504 : };
1505 : #endif
1506 : return m1.table_.equals_unique(m2.table_);
1507 : }
1508 :
1509 : template <class T, class H, class P, class A>
1510 : inline bool operator!=(
1511 : unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
1512 : {
1513 : #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
1514 : struct dummy
1515 : {
1516 : unordered_set<T, H, P, A> x;
1517 : };
1518 : #endif
1519 : return !m1.table_.equals_unique(m2.table_);
1520 : }
1521 :
1522 : template <class T, class H, class P, class A>
1523 : inline void swap(
1524 : unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
1525 : BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)))
1526 : {
1527 : #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
1528 : struct dummy
1529 : {
1530 : unordered_set<T, H, P, A> x;
1531 : };
1532 : #endif
1533 : m1.swap(m2);
1534 : }
1535 :
1536 : ////////////////////////////////////////////////////////////////////////////
1537 :
1538 : template <class T, class H, class P, class A>
1539 : unordered_multiset<T, H, P, A>::unordered_multiset()
1540 : : table_(boost::unordered::detail::default_bucket_count, hasher(),
1541 : key_equal(), allocator_type())
1542 : {
1543 : }
1544 :
1545 : template <class T, class H, class P, class A>
1546 : unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
1547 : const hasher& hf, const key_equal& eql, const allocator_type& a)
1548 : : table_(n, hf, eql, a)
1549 : {
1550 : }
1551 :
1552 : template <class T, class H, class P, class A>
1553 : template <class InputIt>
1554 : unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
1555 : size_type n, const hasher& hf, const key_equal& eql,
1556 : const allocator_type& a)
1557 : : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1558 : {
1559 : this->insert(f, l);
1560 : }
1561 :
1562 : template <class T, class H, class P, class A>
1563 : unordered_multiset<T, H, P, A>::unordered_multiset(
1564 : unordered_multiset const& other)
1565 : : table_(other.table_,
1566 : unordered_multiset::value_allocator_traits::
1567 : select_on_container_copy_construction(other.get_allocator()))
1568 : {
1569 : if (other.table_.size_) {
1570 : table_.copy_buckets(
1571 : other.table_, boost::unordered::detail::false_type());
1572 : }
1573 : }
1574 :
1575 : template <class T, class H, class P, class A>
1576 : unordered_multiset<T, H, P, A>::unordered_multiset(allocator_type const& a)
1577 : : table_(boost::unordered::detail::default_bucket_count, hasher(),
1578 : key_equal(), a)
1579 : {
1580 : }
1581 :
1582 : template <class T, class H, class P, class A>
1583 : unordered_multiset<T, H, P, A>::unordered_multiset(
1584 : unordered_multiset const& other, allocator_type const& a)
1585 : : table_(other.table_, a)
1586 : {
1587 : if (other.table_.size_) {
1588 : table_.copy_buckets(
1589 : other.table_, boost::unordered::detail::false_type());
1590 : }
1591 : }
1592 :
1593 : template <class T, class H, class P, class A>
1594 : unordered_multiset<T, H, P, A>::unordered_multiset(
1595 : BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
1596 : : table_(other.table_, a, boost::unordered::detail::move_tag())
1597 : {
1598 : table_.move_construct_buckets(other.table_);
1599 : }
1600 :
1601 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1602 :
1603 : template <class T, class H, class P, class A>
1604 : unordered_multiset<T, H, P, A>::unordered_multiset(
1605 : std::initializer_list<value_type> list, size_type n, const hasher& hf,
1606 : const key_equal& eql, const allocator_type& a)
1607 : : table_(
1608 : boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1609 : hf, eql, a)
1610 : {
1611 : this->insert(list.begin(), list.end());
1612 : }
1613 :
1614 : #endif
1615 :
1616 : template <class T, class H, class P, class A>
1617 : unordered_multiset<T, H, P, A>::unordered_multiset(
1618 : size_type n, const allocator_type& a)
1619 : : table_(n, hasher(), key_equal(), a)
1620 : {
1621 : }
1622 :
1623 : template <class T, class H, class P, class A>
1624 : unordered_multiset<T, H, P, A>::unordered_multiset(
1625 : size_type n, const hasher& hf, const allocator_type& a)
1626 : : table_(n, hf, key_equal(), a)
1627 : {
1628 : }
1629 :
1630 : template <class T, class H, class P, class A>
1631 : template <class InputIt>
1632 : unordered_multiset<T, H, P, A>::unordered_multiset(
1633 : InputIt f, InputIt l, size_type n, const allocator_type& a)
1634 : : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1635 : key_equal(), a)
1636 : {
1637 : this->insert(f, l);
1638 : }
1639 :
1640 : template <class T, class H, class P, class A>
1641 : template <class InputIt>
1642 : unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
1643 : size_type n, const hasher& hf, const allocator_type& a)
1644 : : table_(
1645 : boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1646 : {
1647 : this->insert(f, l);
1648 : }
1649 :
1650 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1651 :
1652 : template <class T, class H, class P, class A>
1653 : unordered_multiset<T, H, P, A>::unordered_multiset(
1654 : std::initializer_list<value_type> list, size_type n,
1655 : const allocator_type& a)
1656 : : table_(
1657 : boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1658 : hasher(), key_equal(), a)
1659 : {
1660 : this->insert(list.begin(), list.end());
1661 : }
1662 :
1663 : template <class T, class H, class P, class A>
1664 : unordered_multiset<T, H, P, A>::unordered_multiset(
1665 : std::initializer_list<value_type> list, size_type n, const hasher& hf,
1666 : const allocator_type& a)
1667 : : table_(
1668 : boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1669 : hf, key_equal(), a)
1670 : {
1671 : this->insert(list.begin(), list.end());
1672 : }
1673 :
1674 : #endif
1675 :
1676 : template <class T, class H, class P, class A>
1677 : unordered_multiset<T, H, P, A>::~unordered_multiset() BOOST_NOEXCEPT
1678 : {
1679 : }
1680 :
1681 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1682 :
1683 : template <class T, class H, class P, class A>
1684 : unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
1685 : std::initializer_list<value_type> list)
1686 : {
1687 : this->clear();
1688 : this->insert(list.begin(), list.end());
1689 : return *this;
1690 : }
1691 :
1692 : #endif
1693 :
1694 : // size and capacity
1695 :
1696 : template <class T, class H, class P, class A>
1697 : std::size_t unordered_multiset<T, H, P, A>::max_size() const BOOST_NOEXCEPT
1698 : {
1699 : using namespace std;
1700 :
1701 : // size < mlf_ * count
1702 : return boost::unordered::detail::double_to_size(
1703 : ceil(static_cast<double>(table_.mlf_) *
1704 : static_cast<double>(table_.max_bucket_count()))) -
1705 : 1;
1706 : }
1707 :
1708 : // modifiers
1709 :
1710 : template <class T, class H, class P, class A>
1711 : template <class InputIt>
1712 : void unordered_multiset<T, H, P, A>::insert(InputIt first, InputIt last)
1713 : {
1714 : table_.insert_range_equiv(first, last);
1715 : }
1716 :
1717 : #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1718 : template <class T, class H, class P, class A>
1719 : void unordered_multiset<T, H, P, A>::insert(
1720 : std::initializer_list<value_type> list)
1721 : {
1722 : this->insert(list.begin(), list.end());
1723 : }
1724 : #endif
1725 :
1726 : template <class T, class H, class P, class A>
1727 : typename unordered_multiset<T, H, P, A>::iterator
1728 : unordered_multiset<T, H, P, A>::erase(const_iterator position)
1729 : {
1730 : node_pointer node = table::get_node(position);
1731 : BOOST_ASSERT(node);
1732 : node_pointer next = table::next_node(node);
1733 : table_.erase_nodes_equiv(node, next);
1734 : return iterator(next);
1735 : }
1736 :
1737 : template <class T, class H, class P, class A>
1738 : typename unordered_multiset<T, H, P, A>::size_type
1739 : unordered_multiset<T, H, P, A>::erase(const key_type& k)
1740 : {
1741 : return table_.erase_key_equiv(k);
1742 : }
1743 :
1744 : template <class T, class H, class P, class A>
1745 : typename unordered_multiset<T, H, P, A>::iterator
1746 : unordered_multiset<T, H, P, A>::erase(
1747 : const_iterator first, const_iterator last)
1748 : {
1749 : node_pointer last_node = table::get_node(last);
1750 : if (first == last)
1751 : return iterator(last_node);
1752 : table_.erase_nodes_equiv(table::get_node(first), last_node);
1753 : return iterator(last_node);
1754 : }
1755 :
1756 : template <class T, class H, class P, class A>
1757 : void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
1758 : BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
1759 : boost::is_nothrow_swappable<H>::value&&
1760 : boost::is_nothrow_swappable<P>::value)
1761 : {
1762 : table_.swap(other.table_);
1763 : }
1764 :
1765 : // observers
1766 :
1767 : template <class T, class H, class P, class A>
1768 : typename unordered_multiset<T, H, P, A>::hasher
1769 : unordered_multiset<T, H, P, A>::hash_function() const
1770 : {
1771 : return table_.hash_function();
1772 : }
1773 :
1774 : template <class T, class H, class P, class A>
1775 : typename unordered_multiset<T, H, P, A>::key_equal
1776 : unordered_multiset<T, H, P, A>::key_eq() const
1777 : {
1778 : return table_.key_eq();
1779 : }
1780 :
1781 : template <class T, class H, class P, class A>
1782 : template <typename H2, typename P2>
1783 : void unordered_multiset<T, H, P, A>::merge(
1784 : boost::unordered_multiset<T, H2, P2, A>& source)
1785 : {
1786 : while (!source.empty()) {
1787 : insert(source.extract(source.begin()));
1788 : }
1789 : }
1790 :
1791 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1792 : template <class T, class H, class P, class A>
1793 : template <typename H2, typename P2>
1794 : void unordered_multiset<T, H, P, A>::merge(
1795 : boost::unordered_multiset<T, H2, P2, A>&& source)
1796 : {
1797 : while (!source.empty()) {
1798 : insert(source.extract(source.begin()));
1799 : }
1800 : }
1801 : #endif
1802 :
1803 : template <class T, class H, class P, class A>
1804 : template <typename H2, typename P2>
1805 : void unordered_multiset<T, H, P, A>::merge(
1806 : boost::unordered_set<T, H2, P2, A>& source)
1807 : {
1808 : while (!source.empty()) {
1809 : insert(source.extract(source.begin()));
1810 : }
1811 : }
1812 :
1813 : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
1814 : template <class T, class H, class P, class A>
1815 : template <typename H2, typename P2>
1816 : void unordered_multiset<T, H, P, A>::merge(
1817 : boost::unordered_set<T, H2, P2, A>&& source)
1818 : {
1819 : while (!source.empty()) {
1820 : insert(source.extract(source.begin()));
1821 : }
1822 : }
1823 : #endif
1824 :
1825 : // lookup
1826 :
1827 : template <class T, class H, class P, class A>
1828 : typename unordered_multiset<T, H, P, A>::const_iterator
1829 : unordered_multiset<T, H, P, A>::find(const key_type& k) const
1830 : {
1831 : return const_iterator(table_.find_node(k));
1832 : }
1833 :
1834 : template <class T, class H, class P, class A>
1835 : template <class CompatibleKey, class CompatibleHash,
1836 : class CompatiblePredicate>
1837 : typename unordered_multiset<T, H, P, A>::const_iterator
1838 : unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
1839 : CompatibleHash const& hash, CompatiblePredicate const& eq) const
1840 : {
1841 : return const_iterator(
1842 : table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
1843 : }
1844 :
1845 : template <class T, class H, class P, class A>
1846 : typename unordered_multiset<T, H, P, A>::size_type
1847 : unordered_multiset<T, H, P, A>::count(const key_type& k) const
1848 : {
1849 : node_pointer n = table_.find_node(k);
1850 : return n ? table_.group_count(n) : 0;
1851 : }
1852 :
1853 : template <class T, class H, class P, class A>
1854 : std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
1855 : typename unordered_multiset<T, H, P, A>::const_iterator>
1856 : unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
1857 : {
1858 : node_pointer n = table_.find_node(k);
1859 : return std::make_pair(
1860 : const_iterator(n), const_iterator(n ? table_.next_group(n) : n));
1861 : }
1862 :
1863 : template <class T, class H, class P, class A>
1864 : typename unordered_multiset<T, H, P, A>::size_type
1865 : unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
1866 : {
1867 : return table_.bucket_size(n);
1868 : }
1869 :
1870 : // hash policy
1871 :
1872 : template <class T, class H, class P, class A>
1873 : float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
1874 : {
1875 : BOOST_ASSERT(table_.bucket_count_ != 0);
1876 : return static_cast<float>(table_.size_) /
1877 : static_cast<float>(table_.bucket_count_);
1878 : }
1879 :
1880 : template <class T, class H, class P, class A>
1881 : void unordered_multiset<T, H, P, A>::max_load_factor(float m) BOOST_NOEXCEPT
1882 : {
1883 : table_.max_load_factor(m);
1884 : }
1885 :
1886 : template <class T, class H, class P, class A>
1887 : void unordered_multiset<T, H, P, A>::rehash(size_type n)
1888 : {
1889 : table_.rehash(n);
1890 : }
1891 :
1892 : template <class T, class H, class P, class A>
1893 : void unordered_multiset<T, H, P, A>::reserve(size_type n)
1894 : {
1895 : table_.rehash(static_cast<std::size_t>(
1896 : std::ceil(static_cast<double>(n) / table_.mlf_)));
1897 : }
1898 :
1899 : template <class T, class H, class P, class A>
1900 : inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
1901 : unordered_multiset<T, H, P, A> const& m2)
1902 : {
1903 : #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
1904 : struct dummy
1905 : {
1906 : unordered_multiset<T, H, P, A> x;
1907 : };
1908 : #endif
1909 : return m1.table_.equals_equiv(m2.table_);
1910 : }
1911 :
1912 : template <class T, class H, class P, class A>
1913 : inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
1914 : unordered_multiset<T, H, P, A> const& m2)
1915 : {
1916 : #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
1917 : struct dummy
1918 : {
1919 : unordered_multiset<T, H, P, A> x;
1920 : };
1921 : #endif
1922 : return !m1.table_.equals_equiv(m2.table_);
1923 : }
1924 :
1925 : template <class T, class H, class P, class A>
1926 : inline void swap(
1927 : unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
1928 : BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)))
1929 : {
1930 : #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
1931 : struct dummy
1932 : {
1933 : unordered_multiset<T, H, P, A> x;
1934 : };
1935 : #endif
1936 : m1.swap(m2);
1937 : }
1938 :
1939 : template <typename N, typename T, typename A> class node_handle_set
1940 : {
1941 : BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set)
1942 :
1943 : template <typename Types> friend struct ::boost::unordered::detail::table;
1944 : template <class T2, class H2, class P2, class A2>
1945 : friend class unordered_set;
1946 : template <class T2, class H2, class P2, class A2>
1947 : friend class unordered_multiset;
1948 :
1949 : typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
1950 : value_allocator;
1951 : typedef boost::unordered::detail::allocator_traits<value_allocator>
1952 : value_allocator_traits;
1953 : typedef N node;
1954 : typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
1955 : node_allocator;
1956 : typedef boost::unordered::detail::allocator_traits<node_allocator>
1957 : node_allocator_traits;
1958 : typedef typename node_allocator_traits::pointer node_pointer;
1959 :
1960 : public:
1961 : typedef T value_type;
1962 : typedef A allocator_type;
1963 :
1964 : private:
1965 : node_pointer ptr_;
1966 : bool has_alloc_;
1967 : boost::unordered::detail::optional<value_allocator> alloc_;
1968 :
1969 : node_handle_set(node_pointer ptr, allocator_type const& a)
1970 : : ptr_(ptr), alloc_(a)
1971 : {
1972 : }
1973 :
1974 : public:
1975 : BOOST_CONSTEXPR node_handle_set() BOOST_NOEXCEPT : ptr_(),
1976 : has_alloc_(false)
1977 : {
1978 : }
1979 :
1980 : ~node_handle_set()
1981 : {
1982 : if (ptr_) {
1983 : node_allocator node_alloc(*alloc_);
1984 : boost::unordered::detail::node_tmp<node_allocator> tmp(
1985 : ptr_, node_alloc);
1986 : }
1987 : }
1988 :
1989 : node_handle_set(BOOST_RV_REF(node_handle_set) n) BOOST_NOEXCEPT
1990 : : ptr_(n.ptr_),
1991 : alloc_(boost::move(n.alloc_))
1992 : {
1993 : n.ptr_ = node_pointer();
1994 : }
1995 :
1996 : node_handle_set& operator=(BOOST_RV_REF(node_handle_set) n)
1997 : {
1998 : BOOST_ASSERT(!alloc_.has_value() ||
1999 : value_allocator_traits::
2000 : propagate_on_container_move_assignment::value ||
2001 : (n.alloc_.has_value() && alloc_ == n.alloc_));
2002 :
2003 : if (ptr_) {
2004 : node_allocator node_alloc(*alloc_);
2005 : boost::unordered::detail::node_tmp<node_allocator> tmp(
2006 : ptr_, node_alloc);
2007 : ptr_ = node_pointer();
2008 : }
2009 :
2010 : if (!alloc_.has_value() ||
2011 : value_allocator_traits::propagate_on_container_move_assignment::
2012 : value) {
2013 : alloc_ = boost::move(n.alloc_);
2014 : }
2015 : ptr_ = n.ptr_;
2016 : n.ptr_ = node_pointer();
2017 :
2018 : return *this;
2019 : }
2020 :
2021 : value_type& value() const { return ptr_->value(); }
2022 :
2023 : allocator_type get_allocator() const { return *alloc_; }
2024 :
2025 : BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
2026 :
2027 : bool operator!() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
2028 :
2029 : bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
2030 :
2031 : void swap(node_handle_set& n) BOOST_NOEXCEPT_IF(
2032 : value_allocator_traits::propagate_on_container_swap::value ||
2033 : value_allocator_traits::is_always_equal::value)
2034 : {
2035 : BOOST_ASSERT(
2036 : !alloc_.has_value() || !n.alloc_.has_value() ||
2037 : value_allocator_traits::propagate_on_container_swap::value ||
2038 : alloc_ == n.alloc_);
2039 : if (value_allocator_traits::propagate_on_container_swap::value ||
2040 : !alloc_.has_value() || !n.alloc_.has_value()) {
2041 : boost::swap(alloc_, n.alloc_);
2042 : }
2043 : boost::swap(ptr_, n.ptr_);
2044 : }
2045 : };
2046 :
2047 : template <typename N, typename T, typename A>
2048 : void swap(node_handle_set<N, T, A>& x, node_handle_set<N, T, A>& y)
2049 : BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(x.swap(y)))
2050 : {
2051 : x.swap(y);
2052 : }
2053 :
2054 : template <typename N, typename T, typename A> struct insert_return_type_set
2055 : {
2056 : private:
2057 : BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_set)
2058 :
2059 : typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
2060 : value_allocator;
2061 : typedef N node_;
2062 :
2063 : public:
2064 : bool inserted;
2065 : boost::unordered::iterator_detail::c_iterator<node_> position;
2066 : boost::unordered::node_handle_set<N, T, A> node;
2067 :
2068 : insert_return_type_set() : inserted(false), position(), node() {}
2069 :
2070 : insert_return_type_set(BOOST_RV_REF(insert_return_type_set)
2071 : x) BOOST_NOEXCEPT : inserted(x.inserted),
2072 : position(x.position),
2073 : node(boost::move(x.node))
2074 : {
2075 : }
2076 :
2077 : insert_return_type_set& operator=(BOOST_RV_REF(insert_return_type_set) x)
2078 : {
2079 : inserted = x.inserted;
2080 : position = x.position;
2081 : node = boost::move(x.node);
2082 : return *this;
2083 : }
2084 : };
2085 :
2086 : template <typename N, typename T, typename A>
2087 : void swap(
2088 : insert_return_type_set<N, T, A>& x, insert_return_type_set<N, T, A>& y)
2089 : {
2090 : boost::swap(x.node, y.node);
2091 : boost::swap(x.inserted, y.inserted);
2092 : boost::swap(x.position, y.position);
2093 : }
2094 : } // namespace unordered
2095 : } // namespace boost
2096 :
2097 : #if defined(BOOST_MSVC)
2098 : #pragma warning(pop)
2099 : #endif
2100 :
2101 : #endif // BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|