unordered_set.hpp 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970
  1. // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
  2. // Copyright (C) 2005-2011 Daniel James.
  3. // Copyright (C) 2022-2023 Christian Mazakas
  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. // See http://www.boost.org/libs/unordered for documentation
  7. #ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
  8. #define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
  9. #include <boost/config.hpp>
  10. #if defined(BOOST_HAS_PRAGMA_ONCE)
  11. #pragma once
  12. #endif
  13. #include <boost/unordered/detail/serialize_fca_container.hpp>
  14. #include <boost/unordered/detail/set.hpp>
  15. #include <boost/unordered/detail/type_traits.hpp>
  16. #include <boost/container_hash/hash.hpp>
  17. #include <initializer_list>
  18. #if defined(BOOST_MSVC)
  19. #pragma warning(push)
  20. // conditional expression is constant
  21. #pragma warning(disable : 4127)
  22. #if BOOST_MSVC >= 1400
  23. // the inline specifier cannot be used when a friend declaration refers to a
  24. // specialization of a function template
  25. #pragma warning(disable : 4396)
  26. #endif
  27. #endif
  28. namespace boost {
  29. namespace unordered {
  30. template <class T, class H, class P, class A> class unordered_set
  31. {
  32. template <typename, typename, typename, typename>
  33. friend class unordered_multiset;
  34. public:
  35. typedef T key_type;
  36. typedef T value_type;
  37. typedef H hasher;
  38. typedef P key_equal;
  39. typedef A allocator_type;
  40. private:
  41. typedef boost::unordered::detail::set<A, T, H, P> types;
  42. typedef typename types::value_allocator_traits value_allocator_traits;
  43. typedef typename types::table table;
  44. public:
  45. typedef typename value_allocator_traits::pointer pointer;
  46. typedef typename value_allocator_traits::const_pointer const_pointer;
  47. typedef value_type& reference;
  48. typedef value_type const& const_reference;
  49. typedef std::size_t size_type;
  50. typedef std::ptrdiff_t difference_type;
  51. typedef typename table::c_iterator iterator;
  52. typedef typename table::c_iterator const_iterator;
  53. typedef typename table::cl_iterator local_iterator;
  54. typedef typename table::cl_iterator const_local_iterator;
  55. typedef typename types::node_type node_type;
  56. typedef typename types::insert_return_type insert_return_type;
  57. private:
  58. table table_;
  59. public:
  60. // constructors
  61. unordered_set();
  62. explicit unordered_set(size_type, const hasher& = hasher(),
  63. const key_equal& = key_equal(),
  64. const allocator_type& = allocator_type());
  65. template <class InputIt>
  66. unordered_set(InputIt, InputIt,
  67. size_type = boost::unordered::detail::default_bucket_count,
  68. const hasher& = hasher(), const key_equal& = key_equal(),
  69. const allocator_type& = allocator_type());
  70. unordered_set(unordered_set const&);
  71. unordered_set(unordered_set&& other)
  72. noexcept(table::nothrow_move_constructible)
  73. : table_(other.table_, boost::unordered::detail::move_tag())
  74. {
  75. // The move is done in table_
  76. }
  77. explicit unordered_set(allocator_type const&);
  78. unordered_set(unordered_set const&, allocator_type const&);
  79. unordered_set(unordered_set&&, allocator_type const&);
  80. unordered_set(std::initializer_list<value_type>,
  81. size_type = boost::unordered::detail::default_bucket_count,
  82. const hasher& = hasher(), const key_equal& l = key_equal(),
  83. const allocator_type& = allocator_type());
  84. explicit unordered_set(size_type, const allocator_type&);
  85. explicit unordered_set(size_type, const hasher&, const allocator_type&);
  86. template <class InputIterator>
  87. unordered_set(InputIterator, InputIterator, const allocator_type&);
  88. template <class InputIt>
  89. unordered_set(InputIt, InputIt, size_type, const allocator_type&);
  90. template <class InputIt>
  91. unordered_set(
  92. InputIt, InputIt, size_type, const hasher&, const allocator_type&);
  93. unordered_set(std::initializer_list<value_type>, const allocator_type&);
  94. unordered_set(
  95. std::initializer_list<value_type>, size_type, const allocator_type&);
  96. unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
  97. const allocator_type&);
  98. // Destructor
  99. ~unordered_set() noexcept;
  100. // Assign
  101. unordered_set& operator=(unordered_set const& x)
  102. {
  103. table_.assign(x.table_, std::true_type());
  104. return *this;
  105. }
  106. unordered_set& operator=(unordered_set&& x)
  107. noexcept(value_allocator_traits::is_always_equal::value&&
  108. std::is_nothrow_move_assignable<H>::value&&
  109. std::is_nothrow_move_assignable<P>::value)
  110. {
  111. table_.move_assign(x.table_, std::true_type());
  112. return *this;
  113. }
  114. unordered_set& operator=(std::initializer_list<value_type>);
  115. allocator_type get_allocator() const noexcept
  116. {
  117. return table_.node_alloc();
  118. }
  119. // iterators
  120. iterator begin() noexcept { return iterator(table_.begin()); }
  121. const_iterator begin() const noexcept
  122. {
  123. return const_iterator(table_.begin());
  124. }
  125. iterator end() noexcept { return iterator(); }
  126. const_iterator end() const noexcept { return const_iterator(); }
  127. const_iterator cbegin() const noexcept
  128. {
  129. return const_iterator(table_.begin());
  130. }
  131. const_iterator cend() const noexcept { return const_iterator(); }
  132. // size and capacity
  133. BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
  134. {
  135. return table_.size_ == 0;
  136. }
  137. size_type size() const noexcept { return table_.size_; }
  138. size_type max_size() const noexcept;
  139. // emplace
  140. template <class... Args> std::pair<iterator, bool> emplace(Args&&... args)
  141. {
  142. return table_.emplace_unique(
  143. table::extractor::extract(std::forward<Args>(args)...),
  144. std::forward<Args>(args)...);
  145. }
  146. template <class... Args>
  147. iterator emplace_hint(const_iterator hint, Args&&... args)
  148. {
  149. return table_.emplace_hint_unique(hint,
  150. table::extractor::extract(std::forward<Args>(args)...),
  151. std::forward<Args>(args)...);
  152. }
  153. std::pair<iterator, bool> insert(value_type const& x)
  154. {
  155. return this->emplace(x);
  156. }
  157. std::pair<iterator, bool> insert(value_type&& x)
  158. {
  159. return this->emplace(std::move(x));
  160. }
  161. template <class Key>
  162. typename boost::enable_if_c<
  163. detail::transparent_non_iterable<Key, unordered_set>::value,
  164. std::pair<iterator, bool> >::type
  165. insert(Key&& k)
  166. {
  167. return table_.try_emplace_unique(std::forward<Key>(k));
  168. }
  169. iterator insert(const_iterator hint, value_type const& x)
  170. {
  171. return this->emplace_hint(hint, x);
  172. }
  173. iterator insert(const_iterator hint, value_type&& x)
  174. {
  175. return this->emplace_hint(hint, std::move(x));
  176. }
  177. template <class Key>
  178. typename boost::enable_if_c<
  179. detail::transparent_non_iterable<Key, unordered_set>::value,
  180. iterator>::type
  181. insert(const_iterator hint, Key&& k)
  182. {
  183. return table_.try_emplace_hint_unique(hint, std::forward<Key>(k));
  184. }
  185. template <class InputIt> void insert(InputIt, InputIt);
  186. void insert(std::initializer_list<value_type>);
  187. // extract
  188. node_type extract(const_iterator position)
  189. {
  190. return node_type(
  191. table_.extract_by_iterator_unique(position), table_.node_alloc());
  192. }
  193. node_type extract(const key_type& k)
  194. {
  195. return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
  196. }
  197. template <class Key>
  198. typename boost::enable_if_c<
  199. detail::transparent_non_iterable<Key, unordered_set>::value,
  200. node_type>::type
  201. extract(const Key& k)
  202. {
  203. return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
  204. }
  205. insert_return_type insert(node_type&& np)
  206. {
  207. insert_return_type result;
  208. table_.move_insert_node_type_unique(np, result);
  209. return result;
  210. }
  211. iterator insert(const_iterator hint, node_type&& np)
  212. {
  213. return table_.move_insert_node_type_with_hint_unique(hint, np);
  214. }
  215. iterator erase(const_iterator);
  216. size_type erase(const key_type&);
  217. iterator erase(const_iterator, const_iterator);
  218. template <class Key>
  219. typename boost::enable_if_c<
  220. detail::transparent_non_iterable<Key, unordered_set>::value,
  221. size_type>::type
  222. erase(Key&& k)
  223. {
  224. return table_.erase_key_unique_impl(std::forward<Key>(k));
  225. }
  226. BOOST_UNORDERED_DEPRECATED("Use erase instead")
  227. void quick_erase(const_iterator it) { erase(it); }
  228. BOOST_UNORDERED_DEPRECATED("Use erase instead")
  229. void erase_return_void(const_iterator it) { erase(it); }
  230. void swap(unordered_set&)
  231. noexcept(value_allocator_traits::is_always_equal::value&&
  232. boost::unordered::detail::is_nothrow_swappable<H>::value&&
  233. boost::unordered::detail::is_nothrow_swappable<P>::value);
  234. void clear() noexcept { table_.clear_impl(); }
  235. template <typename H2, typename P2>
  236. void merge(boost::unordered_set<T, H2, P2, A>& source);
  237. template <typename H2, typename P2>
  238. void merge(boost::unordered_set<T, H2, P2, A>&& source);
  239. template <typename H2, typename P2>
  240. void merge(boost::unordered_multiset<T, H2, P2, A>& source);
  241. template <typename H2, typename P2>
  242. void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
  243. // observers
  244. hasher hash_function() const;
  245. key_equal key_eq() const;
  246. // lookup
  247. const_iterator find(const key_type&) const;
  248. template <class Key>
  249. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  250. const_iterator>::type
  251. find(const Key& k) const
  252. {
  253. return const_iterator(table_.find(k));
  254. }
  255. template <class CompatibleKey, class CompatibleHash,
  256. class CompatiblePredicate>
  257. const_iterator find(CompatibleKey const&, CompatibleHash const&,
  258. CompatiblePredicate const&) const;
  259. bool contains(key_type const& k) const
  260. {
  261. return table_.find(k) != this->end();
  262. }
  263. template <class Key>
  264. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  265. bool>::type
  266. contains(const Key& k) const
  267. {
  268. return table_.find(k) != this->end();
  269. }
  270. size_type count(const key_type&) const;
  271. template <class Key>
  272. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  273. size_type>::type
  274. count(const Key& k) const
  275. {
  276. return table_.find(k) != this->end() ? 1 : 0;
  277. }
  278. std::pair<const_iterator, const_iterator> equal_range(
  279. const key_type&) const;
  280. template <class Key>
  281. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  282. std::pair<const_iterator, const_iterator> >::type
  283. equal_range(Key const& k) const
  284. {
  285. iterator n = table_.find(k);
  286. iterator m = n;
  287. if (m != this->end()) {
  288. ++m;
  289. }
  290. return std::make_pair(const_iterator(n), const_iterator(m));
  291. }
  292. // bucket interface
  293. size_type bucket_count() const noexcept { return table_.bucket_count(); }
  294. size_type max_bucket_count() const noexcept
  295. {
  296. return table_.max_bucket_count();
  297. }
  298. size_type bucket_size(size_type) const;
  299. size_type bucket(const key_type& k) const
  300. {
  301. return table_.hash_to_bucket(table_.hash(k));
  302. }
  303. template <class Key>
  304. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  305. size_type>::type
  306. bucket(Key&& k) const
  307. {
  308. return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
  309. }
  310. local_iterator begin(size_type n)
  311. {
  312. return local_iterator(table_.begin(n));
  313. }
  314. const_local_iterator begin(size_type n) const
  315. {
  316. return const_local_iterator(table_.begin(n));
  317. }
  318. local_iterator end(size_type) { return local_iterator(); }
  319. const_local_iterator end(size_type) const
  320. {
  321. return const_local_iterator();
  322. }
  323. const_local_iterator cbegin(size_type n) const
  324. {
  325. return const_local_iterator(table_.begin(n));
  326. }
  327. const_local_iterator cend(size_type) const
  328. {
  329. return const_local_iterator();
  330. }
  331. // hash policy
  332. float load_factor() const noexcept;
  333. float max_load_factor() const noexcept { return table_.mlf_; }
  334. void max_load_factor(float) noexcept;
  335. void rehash(size_type);
  336. void reserve(size_type);
  337. #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
  338. friend bool operator==
  339. <T, H, P, A>(unordered_set const&, unordered_set const&);
  340. friend bool operator!=
  341. <T, H, P, A>(unordered_set const&, unordered_set const&);
  342. #endif
  343. }; // class template unordered_set
  344. template <class Archive, class K, class H, class P, class A>
  345. void serialize(
  346. Archive& ar, unordered_set<K, H, P, A>& c, unsigned int version)
  347. {
  348. detail::serialize_fca_container(ar, c, version);
  349. }
  350. #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
  351. template <class InputIterator,
  352. class Hash =
  353. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  354. class Pred =
  355. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  356. class Allocator = std::allocator<
  357. typename std::iterator_traits<InputIterator>::value_type>,
  358. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  359. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  360. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  361. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  362. unordered_set(InputIterator, InputIterator,
  363. std::size_t = boost::unordered::detail::default_bucket_count,
  364. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  365. -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
  366. Hash, Pred, Allocator>;
  367. template <class T, class Hash = boost::hash<T>,
  368. class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
  369. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  370. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  371. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  372. unordered_set(std::initializer_list<T>,
  373. std::size_t = boost::unordered::detail::default_bucket_count,
  374. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  375. -> unordered_set<T, Hash, Pred, Allocator>;
  376. template <class InputIterator, class Allocator,
  377. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  378. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  379. unordered_set(InputIterator, InputIterator, std::size_t, Allocator)
  380. -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
  381. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  382. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  383. Allocator>;
  384. template <class InputIterator, class Hash, class Allocator,
  385. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  386. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  387. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  388. unordered_set(InputIterator, InputIterator, std::size_t, Hash, Allocator)
  389. -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
  390. Hash,
  391. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  392. Allocator>;
  393. template <class T, class Allocator,
  394. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  395. unordered_set(std::initializer_list<T>, std::size_t, Allocator)
  396. -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
  397. template <class T, class Hash, class Allocator,
  398. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  399. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  400. unordered_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
  401. -> unordered_set<T, Hash, std::equal_to<T>, Allocator>;
  402. template <class InputIterator, class Allocator,
  403. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  404. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  405. unordered_set(InputIterator, InputIterator, Allocator)
  406. -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
  407. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  408. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  409. Allocator>;
  410. template <class T, class Allocator,
  411. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  412. unordered_set(std::initializer_list<T>, Allocator)
  413. -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
  414. #endif
  415. template <class T, class H, class P, class A> class unordered_multiset
  416. {
  417. template <typename, typename, typename, typename>
  418. friend class unordered_set;
  419. public:
  420. typedef T key_type;
  421. typedef T value_type;
  422. typedef H hasher;
  423. typedef P key_equal;
  424. typedef A allocator_type;
  425. private:
  426. typedef boost::unordered::detail::set<A, T, H, P> types;
  427. typedef typename types::value_allocator_traits value_allocator_traits;
  428. typedef typename types::table table;
  429. public:
  430. typedef typename value_allocator_traits::pointer pointer;
  431. typedef typename value_allocator_traits::const_pointer const_pointer;
  432. typedef value_type& reference;
  433. typedef value_type const& const_reference;
  434. typedef std::size_t size_type;
  435. typedef std::ptrdiff_t difference_type;
  436. typedef typename table::c_iterator iterator;
  437. typedef typename table::c_iterator const_iterator;
  438. typedef typename table::cl_iterator local_iterator;
  439. typedef typename table::cl_iterator const_local_iterator;
  440. typedef typename types::node_type node_type;
  441. private:
  442. table table_;
  443. public:
  444. // constructors
  445. unordered_multiset();
  446. explicit unordered_multiset(size_type, const hasher& = hasher(),
  447. const key_equal& = key_equal(),
  448. const allocator_type& = allocator_type());
  449. template <class InputIt>
  450. unordered_multiset(InputIt, InputIt,
  451. size_type = boost::unordered::detail::default_bucket_count,
  452. const hasher& = hasher(), const key_equal& = key_equal(),
  453. const allocator_type& = allocator_type());
  454. unordered_multiset(unordered_multiset const&);
  455. unordered_multiset(unordered_multiset&& other)
  456. noexcept(table::nothrow_move_constructible)
  457. : table_(other.table_, boost::unordered::detail::move_tag())
  458. {
  459. // The move is done in table_
  460. }
  461. explicit unordered_multiset(allocator_type const&);
  462. unordered_multiset(unordered_multiset const&, allocator_type const&);
  463. unordered_multiset(unordered_multiset&&, allocator_type const&);
  464. unordered_multiset(std::initializer_list<value_type>,
  465. size_type = boost::unordered::detail::default_bucket_count,
  466. const hasher& = hasher(), const key_equal& l = key_equal(),
  467. const allocator_type& = allocator_type());
  468. explicit unordered_multiset(size_type, const allocator_type&);
  469. explicit unordered_multiset(
  470. size_type, const hasher&, const allocator_type&);
  471. template <class InputIterator>
  472. unordered_multiset(InputIterator, InputIterator, const allocator_type&);
  473. template <class InputIt>
  474. unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
  475. template <class InputIt>
  476. unordered_multiset(
  477. InputIt, InputIt, size_type, const hasher&, const allocator_type&);
  478. unordered_multiset(
  479. std::initializer_list<value_type>, const allocator_type&);
  480. unordered_multiset(
  481. std::initializer_list<value_type>, size_type, const allocator_type&);
  482. unordered_multiset(std::initializer_list<value_type>, size_type,
  483. const hasher&, const allocator_type&);
  484. // Destructor
  485. ~unordered_multiset() noexcept;
  486. // Assign
  487. unordered_multiset& operator=(unordered_multiset const& x)
  488. {
  489. table_.assign(x.table_, std::false_type());
  490. return *this;
  491. }
  492. unordered_multiset& operator=(unordered_multiset&& x)
  493. noexcept(value_allocator_traits::is_always_equal::value&&
  494. std::is_nothrow_move_assignable<H>::value&&
  495. std::is_nothrow_move_assignable<P>::value)
  496. {
  497. table_.move_assign(x.table_, std::false_type());
  498. return *this;
  499. }
  500. unordered_multiset& operator=(std::initializer_list<value_type>);
  501. allocator_type get_allocator() const noexcept
  502. {
  503. return table_.node_alloc();
  504. }
  505. // iterators
  506. iterator begin() noexcept { return iterator(table_.begin()); }
  507. const_iterator begin() const noexcept
  508. {
  509. return const_iterator(table_.begin());
  510. }
  511. iterator end() noexcept { return iterator(); }
  512. const_iterator end() const noexcept { return const_iterator(); }
  513. const_iterator cbegin() const noexcept
  514. {
  515. return const_iterator(table_.begin());
  516. }
  517. const_iterator cend() const noexcept { return const_iterator(); }
  518. // size and capacity
  519. BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
  520. {
  521. return table_.size_ == 0;
  522. }
  523. size_type size() const noexcept { return table_.size_; }
  524. size_type max_size() const noexcept;
  525. // emplace
  526. template <class... Args> iterator emplace(Args&&... args)
  527. {
  528. return iterator(table_.emplace_equiv(
  529. boost::unordered::detail::func::construct_node_from_args(
  530. table_.node_alloc(), std::forward<Args>(args)...)));
  531. }
  532. template <class... Args>
  533. iterator emplace_hint(const_iterator hint, Args&&... args)
  534. {
  535. return iterator(table_.emplace_hint_equiv(
  536. hint, boost::unordered::detail::func::construct_node_from_args(
  537. table_.node_alloc(), std::forward<Args>(args)...)));
  538. }
  539. iterator insert(value_type const& x) { return this->emplace(x); }
  540. iterator insert(value_type&& x) { return this->emplace(std::move(x)); }
  541. iterator insert(const_iterator hint, value_type const& x)
  542. {
  543. return this->emplace_hint(hint, x);
  544. }
  545. iterator insert(const_iterator hint, value_type&& x)
  546. {
  547. return this->emplace_hint(hint, std::move(x));
  548. }
  549. template <class InputIt> void insert(InputIt, InputIt);
  550. void insert(std::initializer_list<value_type>);
  551. // extract
  552. node_type extract(const_iterator position)
  553. {
  554. return node_type(
  555. table_.extract_by_iterator_equiv(position), table_.node_alloc());
  556. }
  557. node_type extract(const key_type& k)
  558. {
  559. return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
  560. }
  561. template <class Key>
  562. typename boost::enable_if_c<
  563. detail::transparent_non_iterable<Key, unordered_multiset>::value,
  564. node_type>::type
  565. extract(const Key& k)
  566. {
  567. return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
  568. }
  569. iterator insert(node_type&& np)
  570. {
  571. return table_.move_insert_node_type_equiv(np);
  572. }
  573. iterator insert(const_iterator hint, node_type&& np)
  574. {
  575. return table_.move_insert_node_type_with_hint_equiv(hint, np);
  576. }
  577. iterator erase(const_iterator);
  578. size_type erase(const key_type&);
  579. template <class Key>
  580. typename boost::enable_if_c<
  581. detail::transparent_non_iterable<Key, unordered_multiset>::value,
  582. size_type>::type
  583. erase(const Key& k)
  584. {
  585. return table_.erase_key_equiv_impl(k);
  586. }
  587. iterator erase(const_iterator, const_iterator);
  588. BOOST_UNORDERED_DEPRECATED("Use erase instead")
  589. void quick_erase(const_iterator it) { erase(it); }
  590. BOOST_UNORDERED_DEPRECATED("Use erase instead")
  591. void erase_return_void(const_iterator it) { erase(it); }
  592. void swap(unordered_multiset&)
  593. noexcept(value_allocator_traits::is_always_equal::value&&
  594. boost::unordered::detail::is_nothrow_swappable<H>::value&&
  595. boost::unordered::detail::is_nothrow_swappable<P>::value);
  596. void clear() noexcept { table_.clear_impl(); }
  597. template <typename H2, typename P2>
  598. void merge(boost::unordered_multiset<T, H2, P2, A>& source);
  599. template <typename H2, typename P2>
  600. void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
  601. template <typename H2, typename P2>
  602. void merge(boost::unordered_set<T, H2, P2, A>& source);
  603. template <typename H2, typename P2>
  604. void merge(boost::unordered_set<T, H2, P2, A>&& source);
  605. // observers
  606. hasher hash_function() const;
  607. key_equal key_eq() const;
  608. // lookup
  609. const_iterator find(const key_type&) const;
  610. template <class Key>
  611. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  612. const_iterator>::type
  613. find(const Key& k) const
  614. {
  615. return table_.find(k);
  616. }
  617. template <class CompatibleKey, class CompatibleHash,
  618. class CompatiblePredicate>
  619. const_iterator find(CompatibleKey const&, CompatibleHash const&,
  620. CompatiblePredicate const&) const;
  621. bool contains(const key_type& k) const
  622. {
  623. return table_.find(k) != this->end();
  624. }
  625. template <class Key>
  626. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  627. bool>::type
  628. contains(const Key& k) const
  629. {
  630. return table_.find(k) != this->end();
  631. }
  632. size_type count(const key_type&) const;
  633. template <class Key>
  634. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  635. size_type>::type
  636. count(const Key& k) const
  637. {
  638. return table_.group_count(k);
  639. }
  640. std::pair<const_iterator, const_iterator> equal_range(
  641. const key_type&) const;
  642. template <class Key>
  643. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  644. std::pair<const_iterator, const_iterator> >::type
  645. equal_range(const Key& k) const
  646. {
  647. iterator first = table_.find(k);
  648. iterator last = table_.next_group(k, first);
  649. return std::make_pair(const_iterator(first), const_iterator(last));
  650. }
  651. // bucket interface
  652. size_type bucket_count() const noexcept { return table_.bucket_count(); }
  653. size_type max_bucket_count() const noexcept
  654. {
  655. return table_.max_bucket_count();
  656. }
  657. size_type bucket_size(size_type) const;
  658. size_type bucket(const key_type& k) const
  659. {
  660. return table_.hash_to_bucket(table_.hash(k));
  661. }
  662. template <class Key>
  663. typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
  664. size_type>::type
  665. bucket(Key&& k) const
  666. {
  667. return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
  668. }
  669. local_iterator begin(size_type n)
  670. {
  671. return local_iterator(table_.begin(n));
  672. }
  673. const_local_iterator begin(size_type n) const
  674. {
  675. return const_local_iterator(table_.begin(n));
  676. }
  677. local_iterator end(size_type) { return local_iterator(); }
  678. const_local_iterator end(size_type) const
  679. {
  680. return const_local_iterator();
  681. }
  682. const_local_iterator cbegin(size_type n) const
  683. {
  684. return const_local_iterator(table_.begin(n));
  685. }
  686. const_local_iterator cend(size_type) const
  687. {
  688. return const_local_iterator();
  689. }
  690. // hash policy
  691. float load_factor() const noexcept;
  692. float max_load_factor() const noexcept { return table_.mlf_; }
  693. void max_load_factor(float) noexcept;
  694. void rehash(size_type);
  695. void reserve(size_type);
  696. #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
  697. friend bool operator==
  698. <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
  699. friend bool operator!=
  700. <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
  701. #endif
  702. }; // class template unordered_multiset
  703. template <class Archive, class K, class H, class P, class A>
  704. void serialize(
  705. Archive& ar, unordered_multiset<K, H, P, A>& c, unsigned int version)
  706. {
  707. detail::serialize_fca_container(ar, c, version);
  708. }
  709. #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
  710. template <class InputIterator,
  711. class Hash =
  712. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  713. class Pred =
  714. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  715. class Allocator = std::allocator<
  716. typename std::iterator_traits<InputIterator>::value_type>,
  717. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  718. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  719. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  720. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  721. unordered_multiset(InputIterator, InputIterator,
  722. std::size_t = boost::unordered::detail::default_bucket_count,
  723. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  724. -> unordered_multiset<
  725. typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
  726. Allocator>;
  727. template <class T, class Hash = boost::hash<T>,
  728. class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
  729. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  730. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  731. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  732. unordered_multiset(std::initializer_list<T>,
  733. std::size_t = boost::unordered::detail::default_bucket_count,
  734. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  735. -> unordered_multiset<T, Hash, Pred, Allocator>;
  736. template <class InputIterator, class Allocator,
  737. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  738. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  739. unordered_multiset(InputIterator, InputIterator, std::size_t, Allocator)
  740. -> unordered_multiset<
  741. typename std::iterator_traits<InputIterator>::value_type,
  742. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  743. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  744. Allocator>;
  745. template <class InputIterator, class Hash, class Allocator,
  746. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  747. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  748. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  749. unordered_multiset(
  750. InputIterator, InputIterator, std::size_t, Hash, Allocator)
  751. -> unordered_multiset<
  752. typename std::iterator_traits<InputIterator>::value_type, Hash,
  753. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  754. Allocator>;
  755. template <class T, class Allocator,
  756. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  757. unordered_multiset(std::initializer_list<T>, std::size_t, Allocator)
  758. -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
  759. template <class T, class Hash, class Allocator,
  760. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  761. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  762. unordered_multiset(std::initializer_list<T>, std::size_t, Hash, Allocator)
  763. -> unordered_multiset<T, Hash, std::equal_to<T>, Allocator>;
  764. template <class InputIterator, class Allocator,
  765. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  766. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  767. unordered_multiset(InputIterator, InputIterator, Allocator)
  768. -> unordered_multiset<
  769. typename std::iterator_traits<InputIterator>::value_type,
  770. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  771. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  772. Allocator>;
  773. template <class T, class Allocator,
  774. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  775. unordered_multiset(std::initializer_list<T>, Allocator)
  776. -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
  777. #endif
  778. ////////////////////////////////////////////////////////////////////////////
  779. template <class T, class H, class P, class A>
  780. unordered_set<T, H, P, A>::unordered_set()
  781. {
  782. }
  783. template <class T, class H, class P, class A>
  784. unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
  785. const key_equal& eql, const allocator_type& a)
  786. : table_(n, hf, eql, a)
  787. {
  788. }
  789. template <class T, class H, class P, class A>
  790. template <class InputIt>
  791. unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
  792. const hasher& hf, const key_equal& eql, const allocator_type& a)
  793. : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
  794. {
  795. this->insert(f, l);
  796. }
  797. template <class T, class H, class P, class A>
  798. unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
  799. : table_(other.table_,
  800. unordered_set::value_allocator_traits::
  801. select_on_container_copy_construction(other.get_allocator()))
  802. {
  803. if (other.size()) {
  804. table_.copy_buckets(other.table_, std::true_type());
  805. }
  806. }
  807. template <class T, class H, class P, class A>
  808. unordered_set<T, H, P, A>::unordered_set(allocator_type const& a)
  809. : table_(boost::unordered::detail::default_bucket_count, hasher(),
  810. key_equal(), a)
  811. {
  812. }
  813. template <class T, class H, class P, class A>
  814. unordered_set<T, H, P, A>::unordered_set(
  815. unordered_set const& other, allocator_type const& a)
  816. : table_(other.table_, a)
  817. {
  818. if (other.table_.size_) {
  819. table_.copy_buckets(other.table_, std::true_type());
  820. }
  821. }
  822. template <class T, class H, class P, class A>
  823. unordered_set<T, H, P, A>::unordered_set(
  824. unordered_set&& other, allocator_type const& a)
  825. : table_(other.table_, a, boost::unordered::detail::move_tag())
  826. {
  827. table_.move_construct_buckets(other.table_);
  828. }
  829. template <class T, class H, class P, class A>
  830. unordered_set<T, H, P, A>::unordered_set(
  831. std::initializer_list<value_type> list, size_type n, const hasher& hf,
  832. const key_equal& eql, const allocator_type& a)
  833. : table_(
  834. boost::unordered::detail::initial_size(list.begin(), list.end(), n),
  835. hf, eql, a)
  836. {
  837. this->insert(list.begin(), list.end());
  838. }
  839. template <class T, class H, class P, class A>
  840. unordered_set<T, H, P, A>::unordered_set(
  841. size_type n, const allocator_type& a)
  842. : table_(n, hasher(), key_equal(), a)
  843. {
  844. }
  845. template <class T, class H, class P, class A>
  846. unordered_set<T, H, P, A>::unordered_set(
  847. size_type n, const hasher& hf, const allocator_type& a)
  848. : table_(n, hf, key_equal(), a)
  849. {
  850. }
  851. template <class T, class H, class P, class A>
  852. template <class InputIterator>
  853. unordered_set<T, H, P, A>::unordered_set(
  854. InputIterator f, InputIterator l, const allocator_type& a)
  855. : table_(boost::unordered::detail::initial_size(
  856. f, l, detail::default_bucket_count),
  857. hasher(), key_equal(), a)
  858. {
  859. this->insert(f, l);
  860. }
  861. template <class T, class H, class P, class A>
  862. template <class InputIt>
  863. unordered_set<T, H, P, A>::unordered_set(
  864. InputIt f, InputIt l, size_type n, const allocator_type& a)
  865. : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
  866. key_equal(), a)
  867. {
  868. this->insert(f, l);
  869. }
  870. template <class T, class H, class P, class A>
  871. template <class InputIt>
  872. unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
  873. const hasher& hf, const allocator_type& a)
  874. : table_(
  875. boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
  876. {
  877. this->insert(f, l);
  878. }
  879. template <class T, class H, class P, class A>
  880. unordered_set<T, H, P, A>::unordered_set(
  881. std::initializer_list<value_type> list, const allocator_type& a)
  882. : table_(boost::unordered::detail::initial_size(
  883. list.begin(), list.end(), detail::default_bucket_count),
  884. hasher(), key_equal(), a)
  885. {
  886. this->insert(list.begin(), list.end());
  887. }
  888. template <class T, class H, class P, class A>
  889. unordered_set<T, H, P, A>::unordered_set(
  890. std::initializer_list<value_type> list, size_type n,
  891. const allocator_type& a)
  892. : table_(
  893. boost::unordered::detail::initial_size(list.begin(), list.end(), n),
  894. hasher(), key_equal(), a)
  895. {
  896. this->insert(list.begin(), list.end());
  897. }
  898. template <class T, class H, class P, class A>
  899. unordered_set<T, H, P, A>::unordered_set(
  900. std::initializer_list<value_type> list, size_type n, const hasher& hf,
  901. const allocator_type& a)
  902. : table_(
  903. boost::unordered::detail::initial_size(list.begin(), list.end(), n),
  904. hf, key_equal(), a)
  905. {
  906. this->insert(list.begin(), list.end());
  907. }
  908. template <class T, class H, class P, class A>
  909. unordered_set<T, H, P, A>::~unordered_set() noexcept
  910. {
  911. }
  912. template <class T, class H, class P, class A>
  913. unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
  914. std::initializer_list<value_type> list)
  915. {
  916. this->clear();
  917. this->insert(list.begin(), list.end());
  918. return *this;
  919. }
  920. // size and capacity
  921. template <class T, class H, class P, class A>
  922. std::size_t unordered_set<T, H, P, A>::max_size() const noexcept
  923. {
  924. using namespace std;
  925. // size < mlf_ * count
  926. return boost::unordered::detail::double_to_size(
  927. ceil(static_cast<double>(table_.mlf_) *
  928. static_cast<double>(table_.max_bucket_count()))) -
  929. 1;
  930. }
  931. // modifiers
  932. template <class T, class H, class P, class A>
  933. template <class InputIt>
  934. void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last)
  935. {
  936. if (first != last) {
  937. table_.insert_range_unique(
  938. table::extractor::extract(*first), first, last);
  939. }
  940. }
  941. template <class T, class H, class P, class A>
  942. void unordered_set<T, H, P, A>::insert(
  943. std::initializer_list<value_type> list)
  944. {
  945. this->insert(list.begin(), list.end());
  946. }
  947. template <class T, class H, class P, class A>
  948. typename unordered_set<T, H, P, A>::iterator
  949. unordered_set<T, H, P, A>::erase(const_iterator position)
  950. {
  951. return table_.erase_node(position);
  952. }
  953. template <class T, class H, class P, class A>
  954. typename unordered_set<T, H, P, A>::size_type
  955. unordered_set<T, H, P, A>::erase(const key_type& k)
  956. {
  957. return table_.erase_key_unique_impl(k);
  958. }
  959. template <class T, class H, class P, class A>
  960. typename unordered_set<T, H, P, A>::iterator
  961. unordered_set<T, H, P, A>::erase(const_iterator first, const_iterator last)
  962. {
  963. return table_.erase_nodes_range(first, last);
  964. }
  965. template <class T, class H, class P, class A>
  966. void unordered_set<T, H, P, A>::swap(unordered_set& other)
  967. noexcept(value_allocator_traits::is_always_equal::value&&
  968. boost::unordered::detail::is_nothrow_swappable<H>::value&&
  969. boost::unordered::detail::is_nothrow_swappable<P>::value)
  970. {
  971. table_.swap(other.table_);
  972. }
  973. // observers
  974. template <class T, class H, class P, class A>
  975. typename unordered_set<T, H, P, A>::hasher
  976. unordered_set<T, H, P, A>::hash_function() const
  977. {
  978. return table_.hash_function();
  979. }
  980. template <class T, class H, class P, class A>
  981. typename unordered_set<T, H, P, A>::key_equal
  982. unordered_set<T, H, P, A>::key_eq() const
  983. {
  984. return table_.key_eq();
  985. }
  986. template <class T, class H, class P, class A>
  987. template <typename H2, typename P2>
  988. void unordered_set<T, H, P, A>::merge(
  989. boost::unordered_set<T, H2, P2, A>& source)
  990. {
  991. table_.merge_unique(source.table_);
  992. }
  993. template <class T, class H, class P, class A>
  994. template <typename H2, typename P2>
  995. void unordered_set<T, H, P, A>::merge(
  996. boost::unordered_set<T, H2, P2, A>&& source)
  997. {
  998. table_.merge_unique(source.table_);
  999. }
  1000. template <class T, class H, class P, class A>
  1001. template <typename H2, typename P2>
  1002. void unordered_set<T, H, P, A>::merge(
  1003. boost::unordered_multiset<T, H2, P2, A>& source)
  1004. {
  1005. table_.merge_unique(source.table_);
  1006. }
  1007. template <class T, class H, class P, class A>
  1008. template <typename H2, typename P2>
  1009. void unordered_set<T, H, P, A>::merge(
  1010. boost::unordered_multiset<T, H2, P2, A>&& source)
  1011. {
  1012. table_.merge_unique(source.table_);
  1013. }
  1014. // lookup
  1015. template <class T, class H, class P, class A>
  1016. typename unordered_set<T, H, P, A>::const_iterator
  1017. unordered_set<T, H, P, A>::find(const key_type& k) const
  1018. {
  1019. return const_iterator(table_.find(k));
  1020. }
  1021. template <class T, class H, class P, class A>
  1022. template <class CompatibleKey, class CompatibleHash,
  1023. class CompatiblePredicate>
  1024. typename unordered_set<T, H, P, A>::const_iterator
  1025. unordered_set<T, H, P, A>::find(CompatibleKey const& k,
  1026. CompatibleHash const& hash, CompatiblePredicate const& eq) const
  1027. {
  1028. return table_.transparent_find(k, hash, eq);
  1029. }
  1030. template <class T, class H, class P, class A>
  1031. typename unordered_set<T, H, P, A>::size_type
  1032. unordered_set<T, H, P, A>::count(const key_type& k) const
  1033. {
  1034. return table_.find_node(k) ? 1 : 0;
  1035. }
  1036. template <class T, class H, class P, class A>
  1037. std::pair<typename unordered_set<T, H, P, A>::const_iterator,
  1038. typename unordered_set<T, H, P, A>::const_iterator>
  1039. unordered_set<T, H, P, A>::equal_range(const key_type& k) const
  1040. {
  1041. iterator first = table_.find(k);
  1042. iterator second = first;
  1043. if (second != this->end()) {
  1044. ++second;
  1045. }
  1046. return std::make_pair(first, second);
  1047. }
  1048. template <class T, class H, class P, class A>
  1049. typename unordered_set<T, H, P, A>::size_type
  1050. unordered_set<T, H, P, A>::bucket_size(size_type n) const
  1051. {
  1052. return table_.bucket_size(n);
  1053. }
  1054. // hash policy
  1055. template <class T, class H, class P, class A>
  1056. float unordered_set<T, H, P, A>::load_factor() const noexcept
  1057. {
  1058. if (table_.size_ == 0) {
  1059. return 0.0f;
  1060. }
  1061. BOOST_ASSERT(table_.bucket_count() != 0);
  1062. return static_cast<float>(table_.size_) /
  1063. static_cast<float>(table_.bucket_count());
  1064. }
  1065. template <class T, class H, class P, class A>
  1066. void unordered_set<T, H, P, A>::max_load_factor(float m) noexcept
  1067. {
  1068. table_.max_load_factor(m);
  1069. }
  1070. template <class T, class H, class P, class A>
  1071. void unordered_set<T, H, P, A>::rehash(size_type n)
  1072. {
  1073. table_.rehash(n);
  1074. }
  1075. template <class T, class H, class P, class A>
  1076. void unordered_set<T, H, P, A>::reserve(size_type n)
  1077. {
  1078. table_.reserve(n);
  1079. }
  1080. template <class T, class H, class P, class A>
  1081. inline bool operator==(
  1082. unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
  1083. {
  1084. #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
  1085. struct dummy
  1086. {
  1087. unordered_set<T, H, P, A> x;
  1088. };
  1089. #endif
  1090. return m1.table_.equals_unique(m2.table_);
  1091. }
  1092. template <class T, class H, class P, class A>
  1093. inline bool operator!=(
  1094. unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
  1095. {
  1096. #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
  1097. struct dummy
  1098. {
  1099. unordered_set<T, H, P, A> x;
  1100. };
  1101. #endif
  1102. return !m1.table_.equals_unique(m2.table_);
  1103. }
  1104. template <class T, class H, class P, class A>
  1105. inline void swap(unordered_set<T, H, P, A>& m1,
  1106. unordered_set<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
  1107. {
  1108. #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
  1109. struct dummy
  1110. {
  1111. unordered_set<T, H, P, A> x;
  1112. };
  1113. #endif
  1114. m1.swap(m2);
  1115. }
  1116. template <class K, class H, class P, class A, class Predicate>
  1117. typename unordered_set<K, H, P, A>::size_type erase_if(
  1118. unordered_set<K, H, P, A>& c, Predicate pred)
  1119. {
  1120. return detail::erase_if(c, pred);
  1121. }
  1122. ////////////////////////////////////////////////////////////////////////////
  1123. template <class T, class H, class P, class A>
  1124. unordered_multiset<T, H, P, A>::unordered_multiset()
  1125. {
  1126. }
  1127. template <class T, class H, class P, class A>
  1128. unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
  1129. const hasher& hf, const key_equal& eql, const allocator_type& a)
  1130. : table_(n, hf, eql, a)
  1131. {
  1132. }
  1133. template <class T, class H, class P, class A>
  1134. template <class InputIt>
  1135. unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
  1136. size_type n, const hasher& hf, const key_equal& eql,
  1137. const allocator_type& a)
  1138. : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
  1139. {
  1140. this->insert(f, l);
  1141. }
  1142. template <class T, class H, class P, class A>
  1143. unordered_multiset<T, H, P, A>::unordered_multiset(
  1144. unordered_multiset const& other)
  1145. : table_(other.table_,
  1146. unordered_multiset::value_allocator_traits::
  1147. select_on_container_copy_construction(other.get_allocator()))
  1148. {
  1149. if (other.table_.size_) {
  1150. table_.copy_buckets(other.table_, std::false_type());
  1151. }
  1152. }
  1153. template <class T, class H, class P, class A>
  1154. unordered_multiset<T, H, P, A>::unordered_multiset(allocator_type const& a)
  1155. : table_(boost::unordered::detail::default_bucket_count, hasher(),
  1156. key_equal(), a)
  1157. {
  1158. }
  1159. template <class T, class H, class P, class A>
  1160. unordered_multiset<T, H, P, A>::unordered_multiset(
  1161. unordered_multiset const& other, allocator_type const& a)
  1162. : table_(other.table_, a)
  1163. {
  1164. if (other.table_.size_) {
  1165. table_.copy_buckets(other.table_, std::false_type());
  1166. }
  1167. }
  1168. template <class T, class H, class P, class A>
  1169. unordered_multiset<T, H, P, A>::unordered_multiset(
  1170. unordered_multiset&& other, allocator_type const& a)
  1171. : table_(other.table_, a, boost::unordered::detail::move_tag())
  1172. {
  1173. table_.move_construct_buckets(other.table_);
  1174. }
  1175. template <class T, class H, class P, class A>
  1176. unordered_multiset<T, H, P, A>::unordered_multiset(
  1177. std::initializer_list<value_type> list, size_type n, const hasher& hf,
  1178. const key_equal& eql, const allocator_type& a)
  1179. : table_(
  1180. boost::unordered::detail::initial_size(list.begin(), list.end(), n),
  1181. hf, eql, a)
  1182. {
  1183. this->insert(list.begin(), list.end());
  1184. }
  1185. template <class T, class H, class P, class A>
  1186. unordered_multiset<T, H, P, A>::unordered_multiset(
  1187. size_type n, const allocator_type& a)
  1188. : table_(n, hasher(), key_equal(), a)
  1189. {
  1190. }
  1191. template <class T, class H, class P, class A>
  1192. unordered_multiset<T, H, P, A>::unordered_multiset(
  1193. size_type n, const hasher& hf, const allocator_type& a)
  1194. : table_(n, hf, key_equal(), a)
  1195. {
  1196. }
  1197. template <class T, class H, class P, class A>
  1198. template <class InputIterator>
  1199. unordered_multiset<T, H, P, A>::unordered_multiset(
  1200. InputIterator f, InputIterator l, const allocator_type& a)
  1201. : table_(boost::unordered::detail::initial_size(
  1202. f, l, detail::default_bucket_count),
  1203. hasher(), key_equal(), a)
  1204. {
  1205. this->insert(f, l);
  1206. }
  1207. template <class T, class H, class P, class A>
  1208. template <class InputIt>
  1209. unordered_multiset<T, H, P, A>::unordered_multiset(
  1210. InputIt f, InputIt l, size_type n, const allocator_type& a)
  1211. : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
  1212. key_equal(), a)
  1213. {
  1214. this->insert(f, l);
  1215. }
  1216. template <class T, class H, class P, class A>
  1217. template <class InputIt>
  1218. unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
  1219. size_type n, const hasher& hf, const allocator_type& a)
  1220. : table_(
  1221. boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
  1222. {
  1223. this->insert(f, l);
  1224. }
  1225. template <class T, class H, class P, class A>
  1226. unordered_multiset<T, H, P, A>::unordered_multiset(
  1227. std::initializer_list<value_type> list, const allocator_type& a)
  1228. : table_(boost::unordered::detail::initial_size(
  1229. list.begin(), list.end(), detail::default_bucket_count),
  1230. hasher(), key_equal(), a)
  1231. {
  1232. this->insert(list.begin(), list.end());
  1233. }
  1234. template <class T, class H, class P, class A>
  1235. unordered_multiset<T, H, P, A>::unordered_multiset(
  1236. std::initializer_list<value_type> list, size_type n,
  1237. const allocator_type& a)
  1238. : table_(
  1239. boost::unordered::detail::initial_size(list.begin(), list.end(), n),
  1240. hasher(), key_equal(), a)
  1241. {
  1242. this->insert(list.begin(), list.end());
  1243. }
  1244. template <class T, class H, class P, class A>
  1245. unordered_multiset<T, H, P, A>::unordered_multiset(
  1246. std::initializer_list<value_type> list, size_type n, const hasher& hf,
  1247. const allocator_type& a)
  1248. : table_(
  1249. boost::unordered::detail::initial_size(list.begin(), list.end(), n),
  1250. hf, key_equal(), a)
  1251. {
  1252. this->insert(list.begin(), list.end());
  1253. }
  1254. template <class T, class H, class P, class A>
  1255. unordered_multiset<T, H, P, A>::~unordered_multiset() noexcept
  1256. {
  1257. }
  1258. template <class T, class H, class P, class A>
  1259. unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
  1260. std::initializer_list<value_type> list)
  1261. {
  1262. this->clear();
  1263. this->insert(list.begin(), list.end());
  1264. return *this;
  1265. }
  1266. // size and capacity
  1267. template <class T, class H, class P, class A>
  1268. std::size_t unordered_multiset<T, H, P, A>::max_size() const noexcept
  1269. {
  1270. using namespace std;
  1271. // size < mlf_ * count
  1272. return boost::unordered::detail::double_to_size(
  1273. ceil(static_cast<double>(table_.mlf_) *
  1274. static_cast<double>(table_.max_bucket_count()))) -
  1275. 1;
  1276. }
  1277. // modifiers
  1278. template <class T, class H, class P, class A>
  1279. template <class InputIt>
  1280. void unordered_multiset<T, H, P, A>::insert(InputIt first, InputIt last)
  1281. {
  1282. table_.insert_range_equiv(first, last);
  1283. }
  1284. template <class T, class H, class P, class A>
  1285. void unordered_multiset<T, H, P, A>::insert(
  1286. std::initializer_list<value_type> list)
  1287. {
  1288. this->insert(list.begin(), list.end());
  1289. }
  1290. template <class T, class H, class P, class A>
  1291. typename unordered_multiset<T, H, P, A>::iterator
  1292. unordered_multiset<T, H, P, A>::erase(const_iterator position)
  1293. {
  1294. BOOST_ASSERT(position != this->end());
  1295. return table_.erase_node(position);
  1296. }
  1297. template <class T, class H, class P, class A>
  1298. typename unordered_multiset<T, H, P, A>::size_type
  1299. unordered_multiset<T, H, P, A>::erase(const key_type& k)
  1300. {
  1301. return table_.erase_key_equiv(k);
  1302. }
  1303. template <class T, class H, class P, class A>
  1304. typename unordered_multiset<T, H, P, A>::iterator
  1305. unordered_multiset<T, H, P, A>::erase(
  1306. const_iterator first, const_iterator last)
  1307. {
  1308. return table_.erase_nodes_range(first, last);
  1309. }
  1310. template <class T, class H, class P, class A>
  1311. void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
  1312. noexcept(value_allocator_traits::is_always_equal::value&&
  1313. boost::unordered::detail::is_nothrow_swappable<H>::value&&
  1314. boost::unordered::detail::is_nothrow_swappable<P>::value)
  1315. {
  1316. table_.swap(other.table_);
  1317. }
  1318. // observers
  1319. template <class T, class H, class P, class A>
  1320. typename unordered_multiset<T, H, P, A>::hasher
  1321. unordered_multiset<T, H, P, A>::hash_function() const
  1322. {
  1323. return table_.hash_function();
  1324. }
  1325. template <class T, class H, class P, class A>
  1326. typename unordered_multiset<T, H, P, A>::key_equal
  1327. unordered_multiset<T, H, P, A>::key_eq() const
  1328. {
  1329. return table_.key_eq();
  1330. }
  1331. template <class T, class H, class P, class A>
  1332. template <typename H2, typename P2>
  1333. void unordered_multiset<T, H, P, A>::merge(
  1334. boost::unordered_multiset<T, H2, P2, A>& source)
  1335. {
  1336. while (!source.empty()) {
  1337. insert(source.extract(source.begin()));
  1338. }
  1339. }
  1340. template <class T, class H, class P, class A>
  1341. template <typename H2, typename P2>
  1342. void unordered_multiset<T, H, P, A>::merge(
  1343. boost::unordered_multiset<T, H2, P2, A>&& source)
  1344. {
  1345. while (!source.empty()) {
  1346. insert(source.extract(source.begin()));
  1347. }
  1348. }
  1349. template <class T, class H, class P, class A>
  1350. template <typename H2, typename P2>
  1351. void unordered_multiset<T, H, P, A>::merge(
  1352. boost::unordered_set<T, H2, P2, A>& source)
  1353. {
  1354. while (!source.empty()) {
  1355. insert(source.extract(source.begin()));
  1356. }
  1357. }
  1358. template <class T, class H, class P, class A>
  1359. template <typename H2, typename P2>
  1360. void unordered_multiset<T, H, P, A>::merge(
  1361. boost::unordered_set<T, H2, P2, A>&& source)
  1362. {
  1363. while (!source.empty()) {
  1364. insert(source.extract(source.begin()));
  1365. }
  1366. }
  1367. // lookup
  1368. template <class T, class H, class P, class A>
  1369. typename unordered_multiset<T, H, P, A>::const_iterator
  1370. unordered_multiset<T, H, P, A>::find(const key_type& k) const
  1371. {
  1372. return const_iterator(table_.find(k));
  1373. }
  1374. template <class T, class H, class P, class A>
  1375. template <class CompatibleKey, class CompatibleHash,
  1376. class CompatiblePredicate>
  1377. typename unordered_multiset<T, H, P, A>::const_iterator
  1378. unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
  1379. CompatibleHash const& hash, CompatiblePredicate const& eq) const
  1380. {
  1381. return table_.transparent_find(k, hash, eq);
  1382. }
  1383. template <class T, class H, class P, class A>
  1384. typename unordered_multiset<T, H, P, A>::size_type
  1385. unordered_multiset<T, H, P, A>::count(const key_type& k) const
  1386. {
  1387. return table_.group_count(k);
  1388. }
  1389. template <class T, class H, class P, class A>
  1390. std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
  1391. typename unordered_multiset<T, H, P, A>::const_iterator>
  1392. unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
  1393. {
  1394. iterator n = table_.find(k);
  1395. return std::make_pair(const_iterator(n),
  1396. const_iterator(n == end() ? n : table_.next_group(k, n)));
  1397. }
  1398. template <class T, class H, class P, class A>
  1399. typename unordered_multiset<T, H, P, A>::size_type
  1400. unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
  1401. {
  1402. return table_.bucket_size(n);
  1403. }
  1404. // hash policy
  1405. template <class T, class H, class P, class A>
  1406. float unordered_multiset<T, H, P, A>::load_factor() const noexcept
  1407. {
  1408. if (table_.size_ == 0) {
  1409. return 0.0f;
  1410. }
  1411. BOOST_ASSERT(table_.bucket_count() != 0);
  1412. return static_cast<float>(table_.size_) /
  1413. static_cast<float>(table_.bucket_count());
  1414. }
  1415. template <class T, class H, class P, class A>
  1416. void unordered_multiset<T, H, P, A>::max_load_factor(float m) noexcept
  1417. {
  1418. table_.max_load_factor(m);
  1419. }
  1420. template <class T, class H, class P, class A>
  1421. void unordered_multiset<T, H, P, A>::rehash(size_type n)
  1422. {
  1423. table_.rehash(n);
  1424. }
  1425. template <class T, class H, class P, class A>
  1426. void unordered_multiset<T, H, P, A>::reserve(size_type n)
  1427. {
  1428. table_.reserve(n);
  1429. }
  1430. template <class T, class H, class P, class A>
  1431. inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
  1432. unordered_multiset<T, H, P, A> const& m2)
  1433. {
  1434. #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
  1435. struct dummy
  1436. {
  1437. unordered_multiset<T, H, P, A> x;
  1438. };
  1439. #endif
  1440. return m1.table_.equals_equiv(m2.table_);
  1441. }
  1442. template <class T, class H, class P, class A>
  1443. inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
  1444. unordered_multiset<T, H, P, A> const& m2)
  1445. {
  1446. #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
  1447. struct dummy
  1448. {
  1449. unordered_multiset<T, H, P, A> x;
  1450. };
  1451. #endif
  1452. return !m1.table_.equals_equiv(m2.table_);
  1453. }
  1454. template <class T, class H, class P, class A>
  1455. inline void swap(unordered_multiset<T, H, P, A>& m1,
  1456. unordered_multiset<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
  1457. {
  1458. #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
  1459. struct dummy
  1460. {
  1461. unordered_multiset<T, H, P, A> x;
  1462. };
  1463. #endif
  1464. m1.swap(m2);
  1465. }
  1466. template <class K, class H, class P, class A, class Predicate>
  1467. typename unordered_multiset<K, H, P, A>::size_type erase_if(
  1468. unordered_multiset<K, H, P, A>& c, Predicate pred)
  1469. {
  1470. return detail::erase_if(c, pred);
  1471. }
  1472. template <typename N, typename T, typename A> class node_handle_set
  1473. {
  1474. template <typename Types> friend struct ::boost::unordered::detail::table;
  1475. template <class T2, class H2, class P2, class A2>
  1476. friend class unordered_set;
  1477. template <class T2, class H2, class P2, class A2>
  1478. friend class unordered_multiset;
  1479. typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
  1480. value_allocator;
  1481. typedef boost::unordered::detail::allocator_traits<value_allocator>
  1482. value_allocator_traits;
  1483. typedef N node;
  1484. typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
  1485. node_allocator;
  1486. typedef boost::unordered::detail::allocator_traits<node_allocator>
  1487. node_allocator_traits;
  1488. typedef typename node_allocator_traits::pointer node_pointer;
  1489. public:
  1490. typedef T value_type;
  1491. typedef A allocator_type;
  1492. private:
  1493. node_pointer ptr_;
  1494. bool has_alloc_;
  1495. boost::unordered::detail::optional<value_allocator> alloc_;
  1496. node_handle_set(node_pointer ptr, allocator_type const& a)
  1497. : ptr_(ptr), alloc_(a)
  1498. {
  1499. }
  1500. public:
  1501. constexpr node_handle_set() noexcept : ptr_(), has_alloc_(false) {}
  1502. node_handle_set(node_handle_set const&) = delete;
  1503. node_handle_set& operator=(node_handle_set const&) = delete;
  1504. ~node_handle_set()
  1505. {
  1506. if (ptr_) {
  1507. node_allocator node_alloc(*alloc_);
  1508. boost::unordered::detail::node_tmp<node_allocator> tmp(
  1509. ptr_, node_alloc);
  1510. }
  1511. }
  1512. node_handle_set(node_handle_set&& n) noexcept
  1513. : ptr_(n.ptr_),
  1514. alloc_(std::move(n.alloc_))
  1515. {
  1516. n.ptr_ = node_pointer();
  1517. }
  1518. node_handle_set& operator=(node_handle_set&& n)
  1519. {
  1520. BOOST_ASSERT(!alloc_.has_value() ||
  1521. value_allocator_traits::
  1522. propagate_on_container_move_assignment::value ||
  1523. (n.alloc_.has_value() && alloc_ == n.alloc_));
  1524. if (ptr_) {
  1525. node_allocator node_alloc(*alloc_);
  1526. boost::unordered::detail::node_tmp<node_allocator> tmp(
  1527. ptr_, node_alloc);
  1528. ptr_ = node_pointer();
  1529. }
  1530. if (!alloc_.has_value() ||
  1531. value_allocator_traits::propagate_on_container_move_assignment::
  1532. value) {
  1533. alloc_ = std::move(n.alloc_);
  1534. }
  1535. ptr_ = n.ptr_;
  1536. n.ptr_ = node_pointer();
  1537. return *this;
  1538. }
  1539. value_type& value() const { return ptr_->value(); }
  1540. allocator_type get_allocator() const { return *alloc_; }
  1541. explicit operator bool() const noexcept
  1542. {
  1543. return !this->operator!();
  1544. }
  1545. bool operator!() const noexcept { return ptr_ ? 0 : 1; }
  1546. BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
  1547. {
  1548. return ptr_ ? 0 : 1;
  1549. }
  1550. void swap(node_handle_set& n)
  1551. noexcept(value_allocator_traits::propagate_on_container_swap::value ||
  1552. value_allocator_traits::is_always_equal::value)
  1553. {
  1554. BOOST_ASSERT(
  1555. !alloc_.has_value() || !n.alloc_.has_value() ||
  1556. value_allocator_traits::propagate_on_container_swap::value ||
  1557. alloc_ == n.alloc_);
  1558. if (value_allocator_traits::propagate_on_container_swap::value ||
  1559. !alloc_.has_value() || !n.alloc_.has_value()) {
  1560. boost::core::invoke_swap(alloc_, n.alloc_);
  1561. }
  1562. boost::core::invoke_swap(ptr_, n.ptr_);
  1563. }
  1564. };
  1565. template <typename N, typename T, typename A>
  1566. void swap(node_handle_set<N, T, A>& x, node_handle_set<N, T, A>& y)
  1567. noexcept(noexcept(x.swap(y)))
  1568. {
  1569. x.swap(y);
  1570. }
  1571. template <class Iter, class NodeType> struct insert_return_type_set
  1572. {
  1573. public:
  1574. Iter position;
  1575. bool inserted;
  1576. NodeType node;
  1577. insert_return_type_set() : position(), inserted(false), node() {}
  1578. insert_return_type_set(insert_return_type_set const&) = delete;
  1579. insert_return_type_set& operator=(insert_return_type_set const&) = delete;
  1580. insert_return_type_set(insert_return_type_set&& x) noexcept
  1581. : position(x.position),
  1582. inserted(x.inserted),
  1583. node(std::move(x.node))
  1584. {
  1585. }
  1586. insert_return_type_set& operator=(insert_return_type_set&& x)
  1587. {
  1588. inserted = x.inserted;
  1589. position = x.position;
  1590. node = std::move(x.node);
  1591. return *this;
  1592. }
  1593. };
  1594. template <class Iter, class NodeType>
  1595. void swap(insert_return_type_set<Iter, NodeType>& x,
  1596. insert_return_type_set<Iter, NodeType>& y)
  1597. {
  1598. boost::core::invoke_swap(x.node, y.node);
  1599. boost::core::invoke_swap(x.inserted, y.inserted);
  1600. boost::core::invoke_swap(x.position, y.position);
  1601. }
  1602. } // namespace unordered
  1603. namespace serialization {
  1604. template <class K, class H, class P, class A>
  1605. struct version<boost::unordered_set<K, H, P, A> >
  1606. {
  1607. BOOST_STATIC_CONSTANT(int, value = 1);
  1608. };
  1609. template <class K, class H, class P, class A>
  1610. struct version<boost::unordered_multiset<K, H, P, A> >
  1611. {
  1612. BOOST_STATIC_CONSTANT(int, value = 1);
  1613. };
  1614. } // namespace serialization
  1615. } // namespace boost
  1616. #if defined(BOOST_MSVC)
  1617. #pragma warning(pop)
  1618. #endif
  1619. #endif // BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED