unordered_set.hpp 62 KB

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