unordered_map.hpp 79 KB

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