File indexing completed on 2025-07-12 08:31:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
0011 #define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
0012
0013 #include <boost/config.hpp>
0014 #if defined(BOOST_HAS_PRAGMA_ONCE)
0015 #pragma once
0016 #endif
0017
0018 #include <boost/unordered/detail/serialize_fca_container.hpp>
0019 #include <boost/unordered/detail/set.hpp>
0020 #include <boost/unordered/detail/type_traits.hpp>
0021
0022 #include <boost/container_hash/hash.hpp>
0023
0024 #include <initializer_list>
0025
0026 #if defined(BOOST_MSVC)
0027 #pragma warning(push)
0028
0029 #pragma warning(disable : 4127)
0030 #if BOOST_MSVC >= 1400
0031
0032
0033 #pragma warning(disable : 4396)
0034 #endif
0035 #endif
0036
0037 namespace boost {
0038 namespace unordered {
0039 template <class T, class H, class P, class A> class unordered_set
0040 {
0041 template <typename, typename, typename, typename>
0042 friend class unordered_multiset;
0043
0044 public:
0045 typedef T key_type;
0046 typedef T value_type;
0047 typedef H hasher;
0048 typedef P key_equal;
0049 typedef A allocator_type;
0050
0051 private:
0052 typedef boost::unordered::detail::set<A, T, H, P> types;
0053 typedef typename types::value_allocator_traits value_allocator_traits;
0054 typedef typename types::table table;
0055
0056 public:
0057 typedef typename value_allocator_traits::pointer pointer;
0058 typedef typename value_allocator_traits::const_pointer const_pointer;
0059
0060 typedef value_type& reference;
0061 typedef value_type const& const_reference;
0062
0063 typedef std::size_t size_type;
0064 typedef std::ptrdiff_t difference_type;
0065
0066 typedef typename table::c_iterator iterator;
0067 typedef typename table::c_iterator const_iterator;
0068 typedef typename table::cl_iterator local_iterator;
0069 typedef typename table::cl_iterator const_local_iterator;
0070 typedef typename types::node_type node_type;
0071 typedef typename types::insert_return_type insert_return_type;
0072
0073 private:
0074 table table_;
0075
0076 public:
0077
0078
0079 unordered_set();
0080
0081 explicit unordered_set(size_type, const hasher& = hasher(),
0082 const key_equal& = key_equal(),
0083 const allocator_type& = allocator_type());
0084
0085 template <class InputIt>
0086 unordered_set(InputIt, InputIt,
0087 size_type = boost::unordered::detail::default_bucket_count,
0088 const hasher& = hasher(), const key_equal& = key_equal(),
0089 const allocator_type& = allocator_type());
0090
0091 unordered_set(unordered_set const&);
0092
0093 unordered_set(unordered_set&& other)
0094 noexcept(table::nothrow_move_constructible)
0095 : table_(other.table_, boost::unordered::detail::move_tag())
0096 {
0097
0098 }
0099
0100 explicit unordered_set(allocator_type const&);
0101
0102 unordered_set(unordered_set const&, allocator_type const&);
0103
0104 unordered_set(unordered_set&&, allocator_type const&);
0105
0106 unordered_set(std::initializer_list<value_type>,
0107 size_type = boost::unordered::detail::default_bucket_count,
0108 const hasher& = hasher(), const key_equal& l = key_equal(),
0109 const allocator_type& = allocator_type());
0110
0111 explicit unordered_set(size_type, const allocator_type&);
0112
0113 explicit unordered_set(size_type, const hasher&, const allocator_type&);
0114
0115 template <class InputIterator>
0116 unordered_set(InputIterator, InputIterator, const allocator_type&);
0117
0118 template <class InputIt>
0119 unordered_set(InputIt, InputIt, size_type, const allocator_type&);
0120
0121 template <class InputIt>
0122 unordered_set(
0123 InputIt, InputIt, size_type, const hasher&, const allocator_type&);
0124
0125 unordered_set(std::initializer_list<value_type>, const allocator_type&);
0126
0127 unordered_set(
0128 std::initializer_list<value_type>, size_type, const allocator_type&);
0129
0130 unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
0131 const allocator_type&);
0132
0133
0134
0135 ~unordered_set() noexcept;
0136
0137
0138
0139 unordered_set& operator=(unordered_set const& x)
0140 {
0141 table_.assign(x.table_, std::true_type());
0142 return *this;
0143 }
0144
0145 unordered_set& operator=(unordered_set&& x)
0146 noexcept(value_allocator_traits::is_always_equal::value&&
0147 std::is_nothrow_move_assignable<H>::value&&
0148 std::is_nothrow_move_assignable<P>::value)
0149 {
0150 table_.move_assign(x.table_, std::true_type());
0151 return *this;
0152 }
0153
0154 unordered_set& operator=(std::initializer_list<value_type>);
0155
0156 allocator_type get_allocator() const noexcept
0157 {
0158 return allocator_type(table_.node_alloc());
0159 }
0160
0161
0162
0163 iterator begin() noexcept { return iterator(table_.begin()); }
0164
0165 const_iterator begin() const noexcept
0166 {
0167 return const_iterator(table_.begin());
0168 }
0169
0170 iterator end() noexcept { return iterator(); }
0171
0172 const_iterator end() const noexcept { return const_iterator(); }
0173
0174 const_iterator cbegin() const noexcept
0175 {
0176 return const_iterator(table_.begin());
0177 }
0178
0179 const_iterator cend() const noexcept { return const_iterator(); }
0180
0181
0182
0183 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0184 {
0185 return table_.size_ == 0;
0186 }
0187
0188 size_type size() const noexcept { return table_.size_; }
0189
0190 size_type max_size() const noexcept;
0191
0192
0193
0194 template <class... Args> std::pair<iterator, bool> emplace(Args&&... args)
0195 {
0196 return table_.emplace_unique(
0197 table::extractor::extract(std::forward<Args>(args)...),
0198 std::forward<Args>(args)...);
0199 }
0200
0201 template <class... Args>
0202 iterator emplace_hint(const_iterator hint, Args&&... args)
0203 {
0204 return table_.emplace_hint_unique(hint,
0205 table::extractor::extract(std::forward<Args>(args)...),
0206 std::forward<Args>(args)...);
0207 }
0208
0209 std::pair<iterator, bool> insert(value_type const& x)
0210 {
0211 return this->emplace(x);
0212 }
0213
0214 std::pair<iterator, bool> insert(value_type&& x)
0215 {
0216 return this->emplace(std::move(x));
0217 }
0218
0219 template <class Key>
0220 typename boost::enable_if_c<
0221 detail::transparent_non_iterable<Key, unordered_set>::value,
0222 std::pair<iterator, bool> >::type
0223 insert(Key&& k)
0224 {
0225 return table_.try_emplace_unique(std::forward<Key>(k));
0226 }
0227
0228 iterator insert(const_iterator hint, value_type const& x)
0229 {
0230 return this->emplace_hint(hint, x);
0231 }
0232
0233 iterator insert(const_iterator hint, value_type&& x)
0234 {
0235 return this->emplace_hint(hint, std::move(x));
0236 }
0237
0238 template <class Key>
0239 typename boost::enable_if_c<
0240 detail::transparent_non_iterable<Key, unordered_set>::value,
0241 iterator>::type
0242 insert(const_iterator hint, Key&& k)
0243 {
0244 return table_.try_emplace_hint_unique(hint, std::forward<Key>(k));
0245 }
0246
0247 template <class InputIt> void insert(InputIt, InputIt);
0248
0249 void insert(std::initializer_list<value_type>);
0250
0251
0252
0253 node_type extract(const_iterator position)
0254 {
0255 return node_type(
0256 table_.extract_by_iterator_unique(position),
0257 allocator_type(table_.node_alloc()));
0258 }
0259
0260 node_type extract(const key_type& k)
0261 {
0262 return node_type(
0263 table_.extract_by_key_impl(k),
0264 allocator_type(table_.node_alloc()));
0265 }
0266
0267 template <class Key>
0268 typename boost::enable_if_c<
0269 detail::transparent_non_iterable<Key, unordered_set>::value,
0270 node_type>::type
0271 extract(const Key& k)
0272 {
0273 return node_type(
0274 table_.extract_by_key_impl(k),
0275 allocator_type(table_.node_alloc()));
0276 }
0277
0278 insert_return_type insert(node_type&& np)
0279 {
0280 insert_return_type result;
0281 table_.move_insert_node_type_unique(np, result);
0282 return result;
0283 }
0284
0285 iterator insert(const_iterator hint, node_type&& np)
0286 {
0287 return table_.move_insert_node_type_with_hint_unique(hint, np);
0288 }
0289
0290 iterator erase(const_iterator);
0291 size_type erase(const key_type&);
0292 iterator erase(const_iterator, const_iterator);
0293
0294 template <class Key>
0295 typename boost::enable_if_c<
0296 detail::transparent_non_iterable<Key, unordered_set>::value,
0297 size_type>::type
0298 erase(Key&& k)
0299 {
0300 return table_.erase_key_unique_impl(std::forward<Key>(k));
0301 }
0302
0303 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0304 void quick_erase(const_iterator it) { erase(it); }
0305 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0306 void erase_return_void(const_iterator it) { erase(it); }
0307
0308 void swap(unordered_set&)
0309 noexcept(value_allocator_traits::is_always_equal::value&&
0310 boost::unordered::detail::is_nothrow_swappable<H>::value&&
0311 boost::unordered::detail::is_nothrow_swappable<P>::value);
0312 void clear() noexcept { table_.clear_impl(); }
0313
0314 template <typename H2, typename P2>
0315 void merge(boost::unordered_set<T, H2, P2, A>& source);
0316
0317 template <typename H2, typename P2>
0318 void merge(boost::unordered_set<T, H2, P2, A>&& source);
0319
0320 template <typename H2, typename P2>
0321 void merge(boost::unordered_multiset<T, H2, P2, A>& source);
0322
0323 template <typename H2, typename P2>
0324 void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
0325
0326
0327
0328 hasher hash_function() const;
0329 key_equal key_eq() const;
0330
0331
0332
0333 const_iterator find(const key_type&) const;
0334
0335 template <class Key>
0336 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0337 const_iterator>::type
0338 find(const Key& k) const
0339 {
0340 return const_iterator(table_.find(k));
0341 }
0342
0343 template <class CompatibleKey, class CompatibleHash,
0344 class CompatiblePredicate>
0345 const_iterator find(CompatibleKey const&, CompatibleHash const&,
0346 CompatiblePredicate const&) const;
0347
0348 bool contains(key_type const& k) const
0349 {
0350 return table_.find(k) != this->end();
0351 }
0352
0353 template <class Key>
0354 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0355 bool>::type
0356 contains(const Key& k) const
0357 {
0358 return table_.find(k) != this->end();
0359 }
0360
0361 size_type count(const key_type&) const;
0362
0363 template <class Key>
0364 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0365 size_type>::type
0366 count(const Key& k) const
0367 {
0368 return table_.find(k) != this->end() ? 1 : 0;
0369 }
0370
0371 std::pair<const_iterator, const_iterator> equal_range(
0372 const key_type&) const;
0373
0374 template <class Key>
0375 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0376 std::pair<const_iterator, const_iterator> >::type
0377 equal_range(Key const& k) const
0378 {
0379 iterator n = table_.find(k);
0380 iterator m = n;
0381 if (m != this->end()) {
0382 ++m;
0383 }
0384
0385 return std::make_pair(const_iterator(n), const_iterator(m));
0386 }
0387
0388
0389
0390 size_type bucket_count() const noexcept { return table_.bucket_count(); }
0391
0392 size_type max_bucket_count() const noexcept
0393 {
0394 return table_.max_bucket_count();
0395 }
0396
0397 size_type bucket_size(size_type) const;
0398
0399 size_type bucket(const key_type& k) const
0400 {
0401 return table_.hash_to_bucket(table_.hash(k));
0402 }
0403
0404 template <class Key>
0405 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0406 size_type>::type
0407 bucket(Key&& k) const
0408 {
0409 return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
0410 }
0411
0412 local_iterator begin(size_type n)
0413 {
0414 return local_iterator(table_.begin(n));
0415 }
0416
0417 const_local_iterator begin(size_type n) const
0418 {
0419 return const_local_iterator(table_.begin(n));
0420 }
0421
0422 local_iterator end(size_type) { return local_iterator(); }
0423
0424 const_local_iterator end(size_type) const
0425 {
0426 return const_local_iterator();
0427 }
0428
0429 const_local_iterator cbegin(size_type n) const
0430 {
0431 return const_local_iterator(table_.begin(n));
0432 }
0433
0434 const_local_iterator cend(size_type) const
0435 {
0436 return const_local_iterator();
0437 }
0438
0439
0440
0441 float load_factor() const noexcept;
0442 float max_load_factor() const noexcept { return table_.mlf_; }
0443 void max_load_factor(float) noexcept;
0444 void rehash(size_type);
0445 void reserve(size_type);
0446
0447 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
0448 friend bool operator==
0449 <T, H, P, A>(unordered_set const&, unordered_set const&);
0450 friend bool operator!=
0451 <T, H, P, A>(unordered_set const&, unordered_set const&);
0452 #endif
0453 };
0454
0455 template <class Archive, class K, class H, class P, class A>
0456 void serialize(
0457 Archive& ar, unordered_set<K, H, P, A>& c, unsigned int version)
0458 {
0459 detail::serialize_fca_container(ar, c, version);
0460 }
0461
0462 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0463
0464 template <class InputIterator,
0465 class Hash =
0466 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0467 class Pred =
0468 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0469 class Allocator = std::allocator<
0470 typename std::iterator_traits<InputIterator>::value_type>,
0471 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0472 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0473 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0474 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0475 unordered_set(InputIterator, InputIterator,
0476 std::size_t = boost::unordered::detail::default_bucket_count,
0477 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0478 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0479 Hash, Pred, Allocator>;
0480
0481 template <class T, class Hash = boost::hash<T>,
0482 class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0483 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0484 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0485 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0486 unordered_set(std::initializer_list<T>,
0487 std::size_t = boost::unordered::detail::default_bucket_count,
0488 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0489 -> unordered_set<T, Hash, Pred, Allocator>;
0490
0491 template <class InputIterator, class Allocator,
0492 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0493 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0494 unordered_set(InputIterator, InputIterator, std::size_t, Allocator)
0495 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0496 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0497 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0498 Allocator>;
0499
0500 template <class InputIterator, class Hash, class Allocator,
0501 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0502 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0503 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0504 unordered_set(InputIterator, InputIterator, std::size_t, Hash, Allocator)
0505 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0506 Hash,
0507 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0508 Allocator>;
0509
0510 template <class T, class Allocator,
0511 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0512 unordered_set(std::initializer_list<T>, std::size_t, Allocator)
0513 -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0514
0515 template <class T, class Hash, class Allocator,
0516 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0517 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0518 unordered_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
0519 -> unordered_set<T, Hash, std::equal_to<T>, Allocator>;
0520
0521 template <class InputIterator, class Allocator,
0522 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0523 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0524 unordered_set(InputIterator, InputIterator, Allocator)
0525 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0526 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0527 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0528 Allocator>;
0529
0530 template <class T, class Allocator,
0531 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0532 unordered_set(std::initializer_list<T>, Allocator)
0533 -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0534
0535 #endif
0536
0537 template <class T, class H, class P, class A> class unordered_multiset
0538 {
0539 template <typename, typename, typename, typename>
0540 friend class unordered_set;
0541
0542 public:
0543 typedef T key_type;
0544 typedef T value_type;
0545 typedef H hasher;
0546 typedef P key_equal;
0547 typedef A allocator_type;
0548
0549 private:
0550 typedef boost::unordered::detail::set<A, T, H, P> types;
0551 typedef typename types::value_allocator_traits value_allocator_traits;
0552 typedef typename types::table table;
0553
0554 public:
0555 typedef typename value_allocator_traits::pointer pointer;
0556 typedef typename value_allocator_traits::const_pointer const_pointer;
0557
0558 typedef value_type& reference;
0559 typedef value_type const& const_reference;
0560
0561 typedef std::size_t size_type;
0562 typedef std::ptrdiff_t difference_type;
0563
0564 typedef typename table::c_iterator iterator;
0565 typedef typename table::c_iterator const_iterator;
0566 typedef typename table::cl_iterator local_iterator;
0567 typedef typename table::cl_iterator const_local_iterator;
0568 typedef typename types::node_type node_type;
0569
0570 private:
0571 table table_;
0572
0573 public:
0574
0575
0576 unordered_multiset();
0577
0578 explicit unordered_multiset(size_type, const hasher& = hasher(),
0579 const key_equal& = key_equal(),
0580 const allocator_type& = allocator_type());
0581
0582 template <class InputIt>
0583 unordered_multiset(InputIt, InputIt,
0584 size_type = boost::unordered::detail::default_bucket_count,
0585 const hasher& = hasher(), const key_equal& = key_equal(),
0586 const allocator_type& = allocator_type());
0587
0588 unordered_multiset(unordered_multiset const&);
0589
0590 unordered_multiset(unordered_multiset&& other)
0591 noexcept(table::nothrow_move_constructible)
0592 : table_(other.table_, boost::unordered::detail::move_tag())
0593 {
0594
0595 }
0596
0597 explicit unordered_multiset(allocator_type const&);
0598
0599 unordered_multiset(unordered_multiset const&, allocator_type const&);
0600
0601 unordered_multiset(unordered_multiset&&, allocator_type const&);
0602
0603 unordered_multiset(std::initializer_list<value_type>,
0604 size_type = boost::unordered::detail::default_bucket_count,
0605 const hasher& = hasher(), const key_equal& l = key_equal(),
0606 const allocator_type& = allocator_type());
0607
0608 explicit unordered_multiset(size_type, const allocator_type&);
0609
0610 explicit unordered_multiset(
0611 size_type, const hasher&, const allocator_type&);
0612
0613 template <class InputIterator>
0614 unordered_multiset(InputIterator, InputIterator, const allocator_type&);
0615
0616 template <class InputIt>
0617 unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
0618
0619 template <class InputIt>
0620 unordered_multiset(
0621 InputIt, InputIt, size_type, const hasher&, const allocator_type&);
0622
0623 unordered_multiset(
0624 std::initializer_list<value_type>, const allocator_type&);
0625
0626 unordered_multiset(
0627 std::initializer_list<value_type>, size_type, const allocator_type&);
0628
0629 unordered_multiset(std::initializer_list<value_type>, size_type,
0630 const hasher&, const allocator_type&);
0631
0632
0633
0634 ~unordered_multiset() noexcept;
0635
0636
0637 unordered_multiset& operator=(unordered_multiset const& x)
0638 {
0639 table_.assign(x.table_, std::false_type());
0640 return *this;
0641 }
0642
0643 unordered_multiset& operator=(unordered_multiset&& x)
0644 noexcept(value_allocator_traits::is_always_equal::value&&
0645 std::is_nothrow_move_assignable<H>::value&&
0646 std::is_nothrow_move_assignable<P>::value)
0647 {
0648 table_.move_assign(x.table_, std::false_type());
0649 return *this;
0650 }
0651
0652 unordered_multiset& operator=(std::initializer_list<value_type>);
0653
0654 allocator_type get_allocator() const noexcept
0655 {
0656 return allocator_type(table_.node_alloc());
0657 }
0658
0659
0660
0661 iterator begin() noexcept { return iterator(table_.begin()); }
0662
0663 const_iterator begin() const noexcept
0664 {
0665 return const_iterator(table_.begin());
0666 }
0667
0668 iterator end() noexcept { return iterator(); }
0669
0670 const_iterator end() const noexcept { return const_iterator(); }
0671
0672 const_iterator cbegin() const noexcept
0673 {
0674 return const_iterator(table_.begin());
0675 }
0676
0677 const_iterator cend() const noexcept { return const_iterator(); }
0678
0679
0680
0681 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0682 {
0683 return table_.size_ == 0;
0684 }
0685
0686 size_type size() const noexcept { return table_.size_; }
0687
0688 size_type max_size() const noexcept;
0689
0690
0691
0692 template <class... Args> iterator emplace(Args&&... args)
0693 {
0694 return iterator(table_.emplace_equiv(
0695 boost::unordered::detail::func::construct_node_from_args(
0696 table_.node_alloc(), std::forward<Args>(args)...)));
0697 }
0698
0699 template <class... Args>
0700 iterator emplace_hint(const_iterator hint, Args&&... args)
0701 {
0702 return iterator(table_.emplace_hint_equiv(
0703 hint, boost::unordered::detail::func::construct_node_from_args(
0704 table_.node_alloc(), std::forward<Args>(args)...)));
0705 }
0706
0707 iterator insert(value_type const& x) { return this->emplace(x); }
0708
0709 iterator insert(value_type&& x) { return this->emplace(std::move(x)); }
0710
0711 iterator insert(const_iterator hint, value_type const& x)
0712 {
0713 return this->emplace_hint(hint, x);
0714 }
0715
0716 iterator insert(const_iterator hint, value_type&& x)
0717 {
0718 return this->emplace_hint(hint, std::move(x));
0719 }
0720
0721 template <class InputIt> void insert(InputIt, InputIt);
0722
0723 void insert(std::initializer_list<value_type>);
0724
0725
0726
0727 node_type extract(const_iterator position)
0728 {
0729 return node_type(
0730 table_.extract_by_iterator_equiv(position), table_.node_alloc());
0731 }
0732
0733 node_type extract(const key_type& k)
0734 {
0735 return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0736 }
0737
0738 template <class Key>
0739 typename boost::enable_if_c<
0740 detail::transparent_non_iterable<Key, unordered_multiset>::value,
0741 node_type>::type
0742 extract(const Key& k)
0743 {
0744 return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0745 }
0746
0747 iterator insert(node_type&& np)
0748 {
0749 return table_.move_insert_node_type_equiv(np);
0750 }
0751
0752 iterator insert(const_iterator hint, node_type&& np)
0753 {
0754 return table_.move_insert_node_type_with_hint_equiv(hint, np);
0755 }
0756
0757 iterator erase(const_iterator);
0758 size_type erase(const key_type&);
0759
0760 template <class Key>
0761 typename boost::enable_if_c<
0762 detail::transparent_non_iterable<Key, unordered_multiset>::value,
0763 size_type>::type
0764 erase(const Key& k)
0765 {
0766 return table_.erase_key_equiv_impl(k);
0767 }
0768
0769 iterator erase(const_iterator, const_iterator);
0770 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0771 void quick_erase(const_iterator it) { erase(it); }
0772 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0773 void erase_return_void(const_iterator it) { erase(it); }
0774
0775 void swap(unordered_multiset&)
0776 noexcept(value_allocator_traits::is_always_equal::value&&
0777 boost::unordered::detail::is_nothrow_swappable<H>::value&&
0778 boost::unordered::detail::is_nothrow_swappable<P>::value);
0779 void clear() noexcept { table_.clear_impl(); }
0780
0781 template <typename H2, typename P2>
0782 void merge(boost::unordered_multiset<T, H2, P2, A>& source);
0783
0784 template <typename H2, typename P2>
0785 void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
0786
0787 template <typename H2, typename P2>
0788 void merge(boost::unordered_set<T, H2, P2, A>& source);
0789
0790 template <typename H2, typename P2>
0791 void merge(boost::unordered_set<T, H2, P2, A>&& source);
0792
0793
0794
0795 hasher hash_function() const;
0796 key_equal key_eq() const;
0797
0798
0799
0800 const_iterator find(const key_type&) const;
0801
0802 template <class Key>
0803 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0804 const_iterator>::type
0805 find(const Key& k) const
0806 {
0807 return table_.find(k);
0808 }
0809
0810 template <class CompatibleKey, class CompatibleHash,
0811 class CompatiblePredicate>
0812 const_iterator find(CompatibleKey const&, CompatibleHash const&,
0813 CompatiblePredicate const&) const;
0814
0815 bool contains(const key_type& k) const
0816 {
0817 return table_.find(k) != this->end();
0818 }
0819
0820 template <class Key>
0821 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0822 bool>::type
0823 contains(const Key& k) const
0824 {
0825 return table_.find(k) != this->end();
0826 }
0827
0828 size_type count(const key_type&) const;
0829
0830 template <class Key>
0831 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0832 size_type>::type
0833 count(const Key& k) const
0834 {
0835 return table_.group_count(k);
0836 }
0837
0838 std::pair<const_iterator, const_iterator> equal_range(
0839 const key_type&) const;
0840
0841 template <class Key>
0842 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0843 std::pair<const_iterator, const_iterator> >::type
0844 equal_range(const Key& k) const
0845 {
0846 iterator first = table_.find(k);
0847 iterator last = table_.next_group(k, first);
0848 return std::make_pair(const_iterator(first), const_iterator(last));
0849 }
0850
0851
0852
0853 size_type bucket_count() const noexcept { return table_.bucket_count(); }
0854
0855 size_type max_bucket_count() const noexcept
0856 {
0857 return table_.max_bucket_count();
0858 }
0859
0860 size_type bucket_size(size_type) const;
0861
0862 size_type bucket(const key_type& k) const
0863 {
0864 return table_.hash_to_bucket(table_.hash(k));
0865 }
0866
0867 template <class Key>
0868 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0869 size_type>::type
0870 bucket(Key&& k) const
0871 {
0872 return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
0873 }
0874
0875 local_iterator begin(size_type n)
0876 {
0877 return local_iterator(table_.begin(n));
0878 }
0879
0880 const_local_iterator begin(size_type n) const
0881 {
0882 return const_local_iterator(table_.begin(n));
0883 }
0884
0885 local_iterator end(size_type) { return local_iterator(); }
0886
0887 const_local_iterator end(size_type) const
0888 {
0889 return const_local_iterator();
0890 }
0891
0892 const_local_iterator cbegin(size_type n) const
0893 {
0894 return const_local_iterator(table_.begin(n));
0895 }
0896
0897 const_local_iterator cend(size_type) const
0898 {
0899 return const_local_iterator();
0900 }
0901
0902
0903
0904 float load_factor() const noexcept;
0905 float max_load_factor() const noexcept { return table_.mlf_; }
0906 void max_load_factor(float) noexcept;
0907 void rehash(size_type);
0908 void reserve(size_type);
0909
0910 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
0911 friend bool operator==
0912 <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
0913 friend bool operator!=
0914 <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
0915 #endif
0916 };
0917
0918 template <class Archive, class K, class H, class P, class A>
0919 void serialize(
0920 Archive& ar, unordered_multiset<K, H, P, A>& c, unsigned int version)
0921 {
0922 detail::serialize_fca_container(ar, c, version);
0923 }
0924
0925 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0926
0927 template <class InputIterator,
0928 class Hash =
0929 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0930 class Pred =
0931 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0932 class Allocator = std::allocator<
0933 typename std::iterator_traits<InputIterator>::value_type>,
0934 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0935 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0936 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0937 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0938 unordered_multiset(InputIterator, InputIterator,
0939 std::size_t = boost::unordered::detail::default_bucket_count,
0940 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0941 -> unordered_multiset<
0942 typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
0943 Allocator>;
0944
0945 template <class T, class Hash = boost::hash<T>,
0946 class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0947 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0948 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0949 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0950 unordered_multiset(std::initializer_list<T>,
0951 std::size_t = boost::unordered::detail::default_bucket_count,
0952 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0953 -> unordered_multiset<T, Hash, Pred, Allocator>;
0954
0955 template <class InputIterator, class Allocator,
0956 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0957 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0958 unordered_multiset(InputIterator, InputIterator, std::size_t, Allocator)
0959 -> unordered_multiset<
0960 typename std::iterator_traits<InputIterator>::value_type,
0961 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0962 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0963 Allocator>;
0964
0965 template <class InputIterator, class Hash, class Allocator,
0966 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0967 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0968 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0969 unordered_multiset(
0970 InputIterator, InputIterator, std::size_t, Hash, Allocator)
0971 -> unordered_multiset<
0972 typename std::iterator_traits<InputIterator>::value_type, Hash,
0973 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0974 Allocator>;
0975
0976 template <class T, class Allocator,
0977 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0978 unordered_multiset(std::initializer_list<T>, std::size_t, Allocator)
0979 -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0980
0981 template <class T, class Hash, class Allocator,
0982 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0983 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0984 unordered_multiset(std::initializer_list<T>, std::size_t, Hash, Allocator)
0985 -> unordered_multiset<T, Hash, std::equal_to<T>, Allocator>;
0986
0987 template <class InputIterator, class Allocator,
0988 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0989 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0990 unordered_multiset(InputIterator, InputIterator, Allocator)
0991 -> unordered_multiset<
0992 typename std::iterator_traits<InputIterator>::value_type,
0993 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0994 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0995 Allocator>;
0996
0997 template <class T, class Allocator,
0998 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0999 unordered_multiset(std::initializer_list<T>, Allocator)
1000 -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
1001
1002 #endif
1003
1004
1005 template <class T, class H, class P, class A>
1006 unordered_set<T, H, P, A>::unordered_set()
1007 {
1008 }
1009
1010 template <class T, class H, class P, class A>
1011 unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
1012 const key_equal& eql, const allocator_type& a)
1013 : table_(n, hf, eql, a)
1014 {
1015 }
1016
1017 template <class T, class H, class P, class A>
1018 template <class InputIt>
1019 unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
1020 const hasher& hf, const key_equal& eql, const allocator_type& a)
1021 : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1022 {
1023 this->insert(f, l);
1024 }
1025
1026 template <class T, class H, class P, class A>
1027 unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
1028 : table_(other.table_,
1029 unordered_set::value_allocator_traits::
1030 select_on_container_copy_construction(other.get_allocator()))
1031 {
1032 if (other.size()) {
1033 table_.copy_buckets(other.table_, std::true_type());
1034 }
1035 }
1036
1037 template <class T, class H, class P, class A>
1038 unordered_set<T, H, P, A>::unordered_set(allocator_type const& a)
1039 : table_(boost::unordered::detail::default_bucket_count, hasher(),
1040 key_equal(), a)
1041 {
1042 }
1043
1044 template <class T, class H, class P, class A>
1045 unordered_set<T, H, P, A>::unordered_set(
1046 unordered_set const& other, allocator_type const& a)
1047 : table_(other.table_, a)
1048 {
1049 if (other.table_.size_) {
1050 table_.copy_buckets(other.table_, std::true_type());
1051 }
1052 }
1053
1054 template <class T, class H, class P, class A>
1055 unordered_set<T, H, P, A>::unordered_set(
1056 unordered_set&& other, allocator_type const& a)
1057 : table_(other.table_, a, boost::unordered::detail::move_tag())
1058 {
1059 table_.move_construct_buckets(other.table_);
1060 }
1061
1062 template <class T, class H, class P, class A>
1063 unordered_set<T, H, P, A>::unordered_set(
1064 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1065 const key_equal& eql, const allocator_type& a)
1066 : table_(
1067 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1068 hf, eql, a)
1069 {
1070 this->insert(list.begin(), list.end());
1071 }
1072
1073 template <class T, class H, class P, class A>
1074 unordered_set<T, H, P, A>::unordered_set(
1075 size_type n, const allocator_type& a)
1076 : table_(n, hasher(), key_equal(), a)
1077 {
1078 }
1079
1080 template <class T, class H, class P, class A>
1081 unordered_set<T, H, P, A>::unordered_set(
1082 size_type n, const hasher& hf, const allocator_type& a)
1083 : table_(n, hf, key_equal(), a)
1084 {
1085 }
1086
1087 template <class T, class H, class P, class A>
1088 template <class InputIterator>
1089 unordered_set<T, H, P, A>::unordered_set(
1090 InputIterator f, InputIterator l, const allocator_type& a)
1091 : table_(boost::unordered::detail::initial_size(
1092 f, l, detail::default_bucket_count),
1093 hasher(), key_equal(), a)
1094 {
1095 this->insert(f, l);
1096 }
1097
1098 template <class T, class H, class P, class A>
1099 template <class InputIt>
1100 unordered_set<T, H, P, A>::unordered_set(
1101 InputIt f, InputIt l, size_type n, const allocator_type& a)
1102 : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1103 key_equal(), a)
1104 {
1105 this->insert(f, l);
1106 }
1107
1108 template <class T, class H, class P, class A>
1109 template <class InputIt>
1110 unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
1111 const hasher& hf, const allocator_type& a)
1112 : table_(
1113 boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1114 {
1115 this->insert(f, l);
1116 }
1117
1118 template <class T, class H, class P, class A>
1119 unordered_set<T, H, P, A>::unordered_set(
1120 std::initializer_list<value_type> list, const allocator_type& a)
1121 : table_(boost::unordered::detail::initial_size(
1122 list.begin(), list.end(), detail::default_bucket_count),
1123 hasher(), key_equal(), a)
1124 {
1125 this->insert(list.begin(), list.end());
1126 }
1127
1128 template <class T, class H, class P, class A>
1129 unordered_set<T, H, P, A>::unordered_set(
1130 std::initializer_list<value_type> list, size_type n,
1131 const allocator_type& a)
1132 : table_(
1133 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1134 hasher(), key_equal(), a)
1135 {
1136 this->insert(list.begin(), list.end());
1137 }
1138
1139 template <class T, class H, class P, class A>
1140 unordered_set<T, H, P, A>::unordered_set(
1141 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1142 const allocator_type& a)
1143 : table_(
1144 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1145 hf, key_equal(), a)
1146 {
1147 this->insert(list.begin(), list.end());
1148 }
1149
1150 template <class T, class H, class P, class A>
1151 unordered_set<T, H, P, A>::~unordered_set() noexcept
1152 {
1153 }
1154
1155 template <class T, class H, class P, class A>
1156 unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
1157 std::initializer_list<value_type> list)
1158 {
1159 this->clear();
1160 this->insert(list.begin(), list.end());
1161 return *this;
1162 }
1163
1164
1165
1166 template <class T, class H, class P, class A>
1167 std::size_t unordered_set<T, H, P, A>::max_size() const noexcept
1168 {
1169 using namespace std;
1170
1171
1172 return boost::unordered::detail::double_to_size(
1173 ceil(static_cast<double>(table_.mlf_) *
1174 static_cast<double>(table_.max_bucket_count()))) -
1175 1;
1176 }
1177
1178
1179
1180 template <class T, class H, class P, class A>
1181 template <class InputIt>
1182 void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last)
1183 {
1184 if (first != last) {
1185 table_.insert_range_unique(
1186 table::extractor::extract(*first), first, last);
1187 }
1188 }
1189
1190 template <class T, class H, class P, class A>
1191 void unordered_set<T, H, P, A>::insert(
1192 std::initializer_list<value_type> list)
1193 {
1194 this->insert(list.begin(), list.end());
1195 }
1196
1197 template <class T, class H, class P, class A>
1198 typename unordered_set<T, H, P, A>::iterator
1199 unordered_set<T, H, P, A>::erase(const_iterator position)
1200 {
1201 return table_.erase_node(position);
1202 }
1203
1204 template <class T, class H, class P, class A>
1205 typename unordered_set<T, H, P, A>::size_type
1206 unordered_set<T, H, P, A>::erase(const key_type& k)
1207 {
1208 return table_.erase_key_unique_impl(k);
1209 }
1210
1211 template <class T, class H, class P, class A>
1212 typename unordered_set<T, H, P, A>::iterator
1213 unordered_set<T, H, P, A>::erase(const_iterator first, const_iterator last)
1214 {
1215 return table_.erase_nodes_range(first, last);
1216 }
1217
1218 template <class T, class H, class P, class A>
1219 void unordered_set<T, H, P, A>::swap(unordered_set& other)
1220 noexcept(value_allocator_traits::is_always_equal::value&&
1221 boost::unordered::detail::is_nothrow_swappable<H>::value&&
1222 boost::unordered::detail::is_nothrow_swappable<P>::value)
1223 {
1224 table_.swap(other.table_);
1225 }
1226
1227
1228
1229 template <class T, class H, class P, class A>
1230 typename unordered_set<T, H, P, A>::hasher
1231 unordered_set<T, H, P, A>::hash_function() const
1232 {
1233 return table_.hash_function();
1234 }
1235
1236 template <class T, class H, class P, class A>
1237 typename unordered_set<T, H, P, A>::key_equal
1238 unordered_set<T, H, P, A>::key_eq() const
1239 {
1240 return table_.key_eq();
1241 }
1242
1243 template <class T, class H, class P, class A>
1244 template <typename H2, typename P2>
1245 void unordered_set<T, H, P, A>::merge(
1246 boost::unordered_set<T, H2, P2, A>& source)
1247 {
1248 table_.merge_unique(source.table_);
1249 }
1250
1251 template <class T, class H, class P, class A>
1252 template <typename H2, typename P2>
1253 void unordered_set<T, H, P, A>::merge(
1254 boost::unordered_set<T, H2, P2, A>&& source)
1255 {
1256 table_.merge_unique(source.table_);
1257 }
1258
1259 template <class T, class H, class P, class A>
1260 template <typename H2, typename P2>
1261 void unordered_set<T, H, P, A>::merge(
1262 boost::unordered_multiset<T, H2, P2, A>& source)
1263 {
1264 table_.merge_unique(source.table_);
1265 }
1266
1267 template <class T, class H, class P, class A>
1268 template <typename H2, typename P2>
1269 void unordered_set<T, H, P, A>::merge(
1270 boost::unordered_multiset<T, H2, P2, A>&& source)
1271 {
1272 table_.merge_unique(source.table_);
1273 }
1274
1275
1276
1277 template <class T, class H, class P, class A>
1278 typename unordered_set<T, H, P, A>::const_iterator
1279 unordered_set<T, H, P, A>::find(const key_type& k) const
1280 {
1281 return const_iterator(table_.find(k));
1282 }
1283
1284 template <class T, class H, class P, class A>
1285 template <class CompatibleKey, class CompatibleHash,
1286 class CompatiblePredicate>
1287 typename unordered_set<T, H, P, A>::const_iterator
1288 unordered_set<T, H, P, A>::find(CompatibleKey const& k,
1289 CompatibleHash const& hash, CompatiblePredicate const& eq) const
1290 {
1291 return table_.transparent_find(k, hash, eq);
1292 }
1293
1294 template <class T, class H, class P, class A>
1295 typename unordered_set<T, H, P, A>::size_type
1296 unordered_set<T, H, P, A>::count(const key_type& k) const
1297 {
1298 return table_.find_node(k) ? 1 : 0;
1299 }
1300
1301 template <class T, class H, class P, class A>
1302 std::pair<typename unordered_set<T, H, P, A>::const_iterator,
1303 typename unordered_set<T, H, P, A>::const_iterator>
1304 unordered_set<T, H, P, A>::equal_range(const key_type& k) const
1305 {
1306 iterator first = table_.find(k);
1307 iterator second = first;
1308 if (second != this->end()) {
1309 ++second;
1310 }
1311 return std::make_pair(first, second);
1312 }
1313
1314 template <class T, class H, class P, class A>
1315 typename unordered_set<T, H, P, A>::size_type
1316 unordered_set<T, H, P, A>::bucket_size(size_type n) const
1317 {
1318 return table_.bucket_size(n);
1319 }
1320
1321
1322
1323 template <class T, class H, class P, class A>
1324 float unordered_set<T, H, P, A>::load_factor() const noexcept
1325 {
1326 if (table_.size_ == 0) {
1327 return 0.0f;
1328 }
1329
1330 BOOST_ASSERT(table_.bucket_count() != 0);
1331 return static_cast<float>(table_.size_) /
1332 static_cast<float>(table_.bucket_count());
1333 }
1334
1335 template <class T, class H, class P, class A>
1336 void unordered_set<T, H, P, A>::max_load_factor(float m) noexcept
1337 {
1338 table_.max_load_factor(m);
1339 }
1340
1341 template <class T, class H, class P, class A>
1342 void unordered_set<T, H, P, A>::rehash(size_type n)
1343 {
1344 table_.rehash(n);
1345 }
1346
1347 template <class T, class H, class P, class A>
1348 void unordered_set<T, H, P, A>::reserve(size_type n)
1349 {
1350 table_.reserve(n);
1351 }
1352
1353 template <class T, class H, class P, class A>
1354 inline bool operator==(
1355 unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
1356 {
1357 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1358 struct dummy
1359 {
1360 unordered_set<T, H, P, A> x;
1361 };
1362 #endif
1363 return m1.table_.equals_unique(m2.table_);
1364 }
1365
1366 template <class T, class H, class P, class A>
1367 inline bool operator!=(
1368 unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
1369 {
1370 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1371 struct dummy
1372 {
1373 unordered_set<T, H, P, A> x;
1374 };
1375 #endif
1376 return !m1.table_.equals_unique(m2.table_);
1377 }
1378
1379 template <class T, class H, class P, class A>
1380 inline void swap(unordered_set<T, H, P, A>& m1,
1381 unordered_set<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
1382 {
1383 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1384 struct dummy
1385 {
1386 unordered_set<T, H, P, A> x;
1387 };
1388 #endif
1389 m1.swap(m2);
1390 }
1391
1392 template <class K, class H, class P, class A, class Predicate>
1393 typename unordered_set<K, H, P, A>::size_type erase_if(
1394 unordered_set<K, H, P, A>& c, Predicate pred)
1395 {
1396 return detail::erase_if(c, pred);
1397 }
1398
1399
1400
1401 template <class T, class H, class P, class A>
1402 unordered_multiset<T, H, P, A>::unordered_multiset()
1403 {
1404 }
1405
1406 template <class T, class H, class P, class A>
1407 unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
1408 const hasher& hf, const key_equal& eql, const allocator_type& a)
1409 : table_(n, hf, eql, a)
1410 {
1411 }
1412
1413 template <class T, class H, class P, class A>
1414 template <class InputIt>
1415 unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
1416 size_type n, const hasher& hf, const key_equal& eql,
1417 const allocator_type& a)
1418 : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1419 {
1420 this->insert(f, l);
1421 }
1422
1423 template <class T, class H, class P, class A>
1424 unordered_multiset<T, H, P, A>::unordered_multiset(
1425 unordered_multiset const& other)
1426 : table_(other.table_,
1427 unordered_multiset::value_allocator_traits::
1428 select_on_container_copy_construction(other.get_allocator()))
1429 {
1430 if (other.table_.size_) {
1431 table_.copy_buckets(other.table_, std::false_type());
1432 }
1433 }
1434
1435 template <class T, class H, class P, class A>
1436 unordered_multiset<T, H, P, A>::unordered_multiset(allocator_type const& a)
1437 : table_(boost::unordered::detail::default_bucket_count, hasher(),
1438 key_equal(), a)
1439 {
1440 }
1441
1442 template <class T, class H, class P, class A>
1443 unordered_multiset<T, H, P, A>::unordered_multiset(
1444 unordered_multiset const& other, allocator_type const& a)
1445 : table_(other.table_, a)
1446 {
1447 if (other.table_.size_) {
1448 table_.copy_buckets(other.table_, std::false_type());
1449 }
1450 }
1451
1452 template <class T, class H, class P, class A>
1453 unordered_multiset<T, H, P, A>::unordered_multiset(
1454 unordered_multiset&& other, allocator_type const& a)
1455 : table_(other.table_, a, boost::unordered::detail::move_tag())
1456 {
1457 table_.move_construct_buckets(other.table_);
1458 }
1459
1460 template <class T, class H, class P, class A>
1461 unordered_multiset<T, H, P, A>::unordered_multiset(
1462 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1463 const key_equal& eql, const allocator_type& a)
1464 : table_(
1465 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1466 hf, eql, a)
1467 {
1468 this->insert(list.begin(), list.end());
1469 }
1470
1471 template <class T, class H, class P, class A>
1472 unordered_multiset<T, H, P, A>::unordered_multiset(
1473 size_type n, const allocator_type& a)
1474 : table_(n, hasher(), key_equal(), a)
1475 {
1476 }
1477
1478 template <class T, class H, class P, class A>
1479 unordered_multiset<T, H, P, A>::unordered_multiset(
1480 size_type n, const hasher& hf, const allocator_type& a)
1481 : table_(n, hf, key_equal(), a)
1482 {
1483 }
1484
1485 template <class T, class H, class P, class A>
1486 template <class InputIterator>
1487 unordered_multiset<T, H, P, A>::unordered_multiset(
1488 InputIterator f, InputIterator l, const allocator_type& a)
1489 : table_(boost::unordered::detail::initial_size(
1490 f, l, detail::default_bucket_count),
1491 hasher(), key_equal(), a)
1492 {
1493 this->insert(f, l);
1494 }
1495
1496 template <class T, class H, class P, class A>
1497 template <class InputIt>
1498 unordered_multiset<T, H, P, A>::unordered_multiset(
1499 InputIt f, InputIt l, size_type n, const allocator_type& a)
1500 : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1501 key_equal(), a)
1502 {
1503 this->insert(f, l);
1504 }
1505
1506 template <class T, class H, class P, class A>
1507 template <class InputIt>
1508 unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
1509 size_type n, const hasher& hf, const allocator_type& a)
1510 : table_(
1511 boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1512 {
1513 this->insert(f, l);
1514 }
1515
1516 template <class T, class H, class P, class A>
1517 unordered_multiset<T, H, P, A>::unordered_multiset(
1518 std::initializer_list<value_type> list, const allocator_type& a)
1519 : table_(boost::unordered::detail::initial_size(
1520 list.begin(), list.end(), detail::default_bucket_count),
1521 hasher(), key_equal(), a)
1522 {
1523 this->insert(list.begin(), list.end());
1524 }
1525
1526 template <class T, class H, class P, class A>
1527 unordered_multiset<T, H, P, A>::unordered_multiset(
1528 std::initializer_list<value_type> list, size_type n,
1529 const allocator_type& a)
1530 : table_(
1531 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1532 hasher(), key_equal(), a)
1533 {
1534 this->insert(list.begin(), list.end());
1535 }
1536
1537 template <class T, class H, class P, class A>
1538 unordered_multiset<T, H, P, A>::unordered_multiset(
1539 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1540 const allocator_type& a)
1541 : table_(
1542 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1543 hf, key_equal(), a)
1544 {
1545 this->insert(list.begin(), list.end());
1546 }
1547
1548 template <class T, class H, class P, class A>
1549 unordered_multiset<T, H, P, A>::~unordered_multiset() noexcept
1550 {
1551 }
1552
1553 template <class T, class H, class P, class A>
1554 unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
1555 std::initializer_list<value_type> list)
1556 {
1557 this->clear();
1558 this->insert(list.begin(), list.end());
1559 return *this;
1560 }
1561
1562
1563
1564 template <class T, class H, class P, class A>
1565 std::size_t unordered_multiset<T, H, P, A>::max_size() const noexcept
1566 {
1567 using namespace std;
1568
1569
1570 return boost::unordered::detail::double_to_size(
1571 ceil(static_cast<double>(table_.mlf_) *
1572 static_cast<double>(table_.max_bucket_count()))) -
1573 1;
1574 }
1575
1576
1577
1578 template <class T, class H, class P, class A>
1579 template <class InputIt>
1580 void unordered_multiset<T, H, P, A>::insert(InputIt first, InputIt last)
1581 {
1582 table_.insert_range_equiv(first, last);
1583 }
1584
1585 template <class T, class H, class P, class A>
1586 void unordered_multiset<T, H, P, A>::insert(
1587 std::initializer_list<value_type> list)
1588 {
1589 this->insert(list.begin(), list.end());
1590 }
1591
1592 template <class T, class H, class P, class A>
1593 typename unordered_multiset<T, H, P, A>::iterator
1594 unordered_multiset<T, H, P, A>::erase(const_iterator position)
1595 {
1596 BOOST_ASSERT(position != this->end());
1597 return table_.erase_node(position);
1598 }
1599
1600 template <class T, class H, class P, class A>
1601 typename unordered_multiset<T, H, P, A>::size_type
1602 unordered_multiset<T, H, P, A>::erase(const key_type& k)
1603 {
1604 return table_.erase_key_equiv(k);
1605 }
1606
1607 template <class T, class H, class P, class A>
1608 typename unordered_multiset<T, H, P, A>::iterator
1609 unordered_multiset<T, H, P, A>::erase(
1610 const_iterator first, const_iterator last)
1611 {
1612 return table_.erase_nodes_range(first, last);
1613 }
1614
1615 template <class T, class H, class P, class A>
1616 void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
1617 noexcept(value_allocator_traits::is_always_equal::value&&
1618 boost::unordered::detail::is_nothrow_swappable<H>::value&&
1619 boost::unordered::detail::is_nothrow_swappable<P>::value)
1620 {
1621 table_.swap(other.table_);
1622 }
1623
1624
1625
1626 template <class T, class H, class P, class A>
1627 typename unordered_multiset<T, H, P, A>::hasher
1628 unordered_multiset<T, H, P, A>::hash_function() const
1629 {
1630 return table_.hash_function();
1631 }
1632
1633 template <class T, class H, class P, class A>
1634 typename unordered_multiset<T, H, P, A>::key_equal
1635 unordered_multiset<T, H, P, A>::key_eq() const
1636 {
1637 return table_.key_eq();
1638 }
1639
1640 template <class T, class H, class P, class A>
1641 template <typename H2, typename P2>
1642 void unordered_multiset<T, H, P, A>::merge(
1643 boost::unordered_multiset<T, H2, P2, A>& source)
1644 {
1645 while (!source.empty()) {
1646 insert(source.extract(source.begin()));
1647 }
1648 }
1649
1650 template <class T, class H, class P, class A>
1651 template <typename H2, typename P2>
1652 void unordered_multiset<T, H, P, A>::merge(
1653 boost::unordered_multiset<T, H2, P2, A>&& source)
1654 {
1655 while (!source.empty()) {
1656 insert(source.extract(source.begin()));
1657 }
1658 }
1659
1660 template <class T, class H, class P, class A>
1661 template <typename H2, typename P2>
1662 void unordered_multiset<T, H, P, A>::merge(
1663 boost::unordered_set<T, H2, P2, A>& source)
1664 {
1665 while (!source.empty()) {
1666 insert(source.extract(source.begin()));
1667 }
1668 }
1669
1670 template <class T, class H, class P, class A>
1671 template <typename H2, typename P2>
1672 void unordered_multiset<T, H, P, A>::merge(
1673 boost::unordered_set<T, H2, P2, A>&& source)
1674 {
1675 while (!source.empty()) {
1676 insert(source.extract(source.begin()));
1677 }
1678 }
1679
1680
1681
1682 template <class T, class H, class P, class A>
1683 typename unordered_multiset<T, H, P, A>::const_iterator
1684 unordered_multiset<T, H, P, A>::find(const key_type& k) const
1685 {
1686 return const_iterator(table_.find(k));
1687 }
1688
1689 template <class T, class H, class P, class A>
1690 template <class CompatibleKey, class CompatibleHash,
1691 class CompatiblePredicate>
1692 typename unordered_multiset<T, H, P, A>::const_iterator
1693 unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
1694 CompatibleHash const& hash, CompatiblePredicate const& eq) const
1695 {
1696 return table_.transparent_find(k, hash, eq);
1697 }
1698
1699 template <class T, class H, class P, class A>
1700 typename unordered_multiset<T, H, P, A>::size_type
1701 unordered_multiset<T, H, P, A>::count(const key_type& k) const
1702 {
1703 return table_.group_count(k);
1704 }
1705
1706 template <class T, class H, class P, class A>
1707 std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
1708 typename unordered_multiset<T, H, P, A>::const_iterator>
1709 unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
1710 {
1711 iterator n = table_.find(k);
1712 return std::make_pair(const_iterator(n),
1713 const_iterator(n == end() ? n : table_.next_group(k, n)));
1714 }
1715
1716 template <class T, class H, class P, class A>
1717 typename unordered_multiset<T, H, P, A>::size_type
1718 unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
1719 {
1720 return table_.bucket_size(n);
1721 }
1722
1723
1724
1725 template <class T, class H, class P, class A>
1726 float unordered_multiset<T, H, P, A>::load_factor() const noexcept
1727 {
1728 if (table_.size_ == 0) {
1729 return 0.0f;
1730 }
1731
1732 BOOST_ASSERT(table_.bucket_count() != 0);
1733 return static_cast<float>(table_.size_) /
1734 static_cast<float>(table_.bucket_count());
1735 }
1736
1737 template <class T, class H, class P, class A>
1738 void unordered_multiset<T, H, P, A>::max_load_factor(float m) noexcept
1739 {
1740 table_.max_load_factor(m);
1741 }
1742
1743 template <class T, class H, class P, class A>
1744 void unordered_multiset<T, H, P, A>::rehash(size_type n)
1745 {
1746 table_.rehash(n);
1747 }
1748
1749 template <class T, class H, class P, class A>
1750 void unordered_multiset<T, H, P, A>::reserve(size_type n)
1751 {
1752 table_.reserve(n);
1753 }
1754
1755 template <class T, class H, class P, class A>
1756 inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
1757 unordered_multiset<T, H, P, A> const& m2)
1758 {
1759 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1760 struct dummy
1761 {
1762 unordered_multiset<T, H, P, A> x;
1763 };
1764 #endif
1765 return m1.table_.equals_equiv(m2.table_);
1766 }
1767
1768 template <class T, class H, class P, class A>
1769 inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
1770 unordered_multiset<T, H, P, A> const& m2)
1771 {
1772 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1773 struct dummy
1774 {
1775 unordered_multiset<T, H, P, A> x;
1776 };
1777 #endif
1778 return !m1.table_.equals_equiv(m2.table_);
1779 }
1780
1781 template <class T, class H, class P, class A>
1782 inline void swap(unordered_multiset<T, H, P, A>& m1,
1783 unordered_multiset<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
1784 {
1785 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1786 struct dummy
1787 {
1788 unordered_multiset<T, H, P, A> x;
1789 };
1790 #endif
1791 m1.swap(m2);
1792 }
1793
1794 template <class K, class H, class P, class A, class Predicate>
1795 typename unordered_multiset<K, H, P, A>::size_type erase_if(
1796 unordered_multiset<K, H, P, A>& c, Predicate pred)
1797 {
1798 return detail::erase_if(c, pred);
1799 }
1800
1801 template <typename N, typename T, typename A> class node_handle_set
1802 {
1803 template <typename Types> friend struct ::boost::unordered::detail::table;
1804 template <class T2, class H2, class P2, class A2>
1805 friend class unordered_set;
1806 template <class T2, class H2, class P2, class A2>
1807 friend class unordered_multiset;
1808
1809 typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
1810 value_allocator;
1811 typedef boost::unordered::detail::allocator_traits<value_allocator>
1812 value_allocator_traits;
1813 typedef N node;
1814 typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
1815 node_allocator;
1816 typedef boost::unordered::detail::allocator_traits<node_allocator>
1817 node_allocator_traits;
1818 typedef typename node_allocator_traits::pointer node_pointer;
1819
1820 public:
1821 typedef T value_type;
1822 typedef A allocator_type;
1823
1824 private:
1825 node_pointer ptr_;
1826 bool has_alloc_;
1827 boost::unordered::detail::optional<value_allocator> alloc_;
1828
1829 node_handle_set(node_pointer ptr, allocator_type const& a)
1830 : ptr_(ptr), alloc_(a)
1831 {
1832 }
1833
1834 public:
1835 constexpr node_handle_set() noexcept : ptr_(), has_alloc_(false) {}
1836 node_handle_set(node_handle_set const&) = delete;
1837 node_handle_set& operator=(node_handle_set const&) = delete;
1838
1839 ~node_handle_set()
1840 {
1841 if (ptr_) {
1842 node_allocator node_alloc(*alloc_);
1843 boost::unordered::detail::node_tmp<node_allocator> tmp(
1844 ptr_, node_alloc);
1845 }
1846 }
1847
1848 node_handle_set(node_handle_set&& n) noexcept
1849 : ptr_(n.ptr_),
1850 alloc_(std::move(n.alloc_))
1851 {
1852 n.ptr_ = node_pointer();
1853 }
1854
1855 node_handle_set& operator=(node_handle_set&& n)
1856 {
1857 BOOST_ASSERT(!alloc_.has_value() ||
1858 value_allocator_traits::
1859 propagate_on_container_move_assignment::value ||
1860 (n.alloc_.has_value() && alloc_ == n.alloc_));
1861
1862 if (ptr_) {
1863 node_allocator node_alloc(*alloc_);
1864 boost::unordered::detail::node_tmp<node_allocator> tmp(
1865 ptr_, node_alloc);
1866 ptr_ = node_pointer();
1867 }
1868
1869 if (!alloc_.has_value() ||
1870 value_allocator_traits::propagate_on_container_move_assignment::
1871 value) {
1872 alloc_ = std::move(n.alloc_);
1873 }
1874 ptr_ = n.ptr_;
1875 n.ptr_ = node_pointer();
1876
1877 return *this;
1878 }
1879
1880 value_type& value() const { return ptr_->value(); }
1881
1882 allocator_type get_allocator() const { return *alloc_; }
1883
1884 explicit operator bool() const noexcept
1885 {
1886 return !this->operator!();
1887 }
1888
1889 bool operator!() const noexcept { return ptr_ ? 0 : 1; }
1890
1891 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
1892 {
1893 return ptr_ ? 0 : 1;
1894 }
1895
1896 void swap(node_handle_set& n)
1897 noexcept(value_allocator_traits::propagate_on_container_swap::value ||
1898 value_allocator_traits::is_always_equal::value)
1899 {
1900 BOOST_ASSERT(
1901 !alloc_.has_value() || !n.alloc_.has_value() ||
1902 value_allocator_traits::propagate_on_container_swap::value ||
1903 alloc_ == n.alloc_);
1904 if (value_allocator_traits::propagate_on_container_swap::value ||
1905 !alloc_.has_value() || !n.alloc_.has_value()) {
1906 boost::core::invoke_swap(alloc_, n.alloc_);
1907 }
1908 boost::core::invoke_swap(ptr_, n.ptr_);
1909 }
1910 };
1911
1912 template <typename N, typename T, typename A>
1913 void swap(node_handle_set<N, T, A>& x, node_handle_set<N, T, A>& y)
1914 noexcept(noexcept(x.swap(y)))
1915 {
1916 x.swap(y);
1917 }
1918
1919 template <class Iter, class NodeType> struct insert_return_type_set
1920 {
1921 public:
1922 Iter position;
1923 bool inserted;
1924 NodeType node;
1925
1926 insert_return_type_set() : position(), inserted(false), node() {}
1927 insert_return_type_set(insert_return_type_set const&) = delete;
1928 insert_return_type_set& operator=(insert_return_type_set const&) = delete;
1929
1930 insert_return_type_set(insert_return_type_set&& x) noexcept
1931 : position(x.position),
1932 inserted(x.inserted),
1933 node(std::move(x.node))
1934 {
1935 }
1936
1937 insert_return_type_set& operator=(insert_return_type_set&& x)
1938 {
1939 inserted = x.inserted;
1940 position = x.position;
1941 node = std::move(x.node);
1942 return *this;
1943 }
1944 };
1945
1946 template <class Iter, class NodeType>
1947 void swap(insert_return_type_set<Iter, NodeType>& x,
1948 insert_return_type_set<Iter, NodeType>& y)
1949 {
1950 boost::core::invoke_swap(x.node, y.node);
1951 boost::core::invoke_swap(x.inserted, y.inserted);
1952 boost::core::invoke_swap(x.position, y.position);
1953 }
1954 }
1955
1956 namespace serialization {
1957 template <class K, class H, class P, class A>
1958 struct version<boost::unordered_set<K, H, P, A> >
1959 {
1960 BOOST_STATIC_CONSTANT(int, value = 1);
1961 };
1962
1963 template <class K, class H, class P, class A>
1964 struct version<boost::unordered_multiset<K, H, P, A> >
1965 {
1966 BOOST_STATIC_CONSTANT(int, value = 1);
1967 };
1968 }
1969
1970 }
1971
1972 #if defined(BOOST_MSVC)
1973 #pragma warning(pop)
1974 #endif
1975
1976 #endif