implementation.hpp 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914
  1. // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
  2. // Copyright (C) 2005-2016 Daniel James
  3. // Copyright (C) 2022-2024 Joaquin M Lopez Munoz.
  4. // Copyright (C) 2022-2023 Christian Mazakas
  5. // Copyright (C) 2024 Braden Ganetsky
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. #ifndef BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
  10. #define BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
  11. #include <boost/config.hpp>
  12. #if defined(BOOST_HAS_PRAGMA_ONCE)
  13. #pragma once
  14. #endif
  15. #include <boost/unordered/detail/allocator_constructed.hpp>
  16. #include <boost/unordered/detail/fca.hpp>
  17. #include <boost/unordered/detail/opt_storage.hpp>
  18. #include <boost/unordered/detail/serialize_tracked_address.hpp>
  19. #include <boost/unordered/detail/static_assert.hpp>
  20. #include <boost/unordered/detail/type_traits.hpp>
  21. #include <boost/unordered/detail/unordered_printers.hpp>
  22. #include <boost/assert.hpp>
  23. #include <boost/core/allocator_traits.hpp>
  24. #include <boost/core/bit.hpp>
  25. #include <boost/core/invoke_swap.hpp>
  26. #include <boost/core/no_exceptions_support.hpp>
  27. #include <boost/core/pointer_traits.hpp>
  28. #include <boost/core/serialization.hpp>
  29. #include <boost/mp11/algorithm.hpp>
  30. #include <boost/mp11/list.hpp>
  31. #include <boost/throw_exception.hpp>
  32. #include <algorithm>
  33. #include <cmath>
  34. #include <iterator>
  35. #include <limits>
  36. #include <stdexcept>
  37. #include <type_traits>
  38. #include <utility>
  39. #include <tuple> // std::forward_as_tuple
  40. namespace boost {
  41. namespace tuples {
  42. struct null_type;
  43. }
  44. } // namespace boost
  45. // BOOST_UNORDERED_SUPPRESS_DEPRECATED
  46. //
  47. // Define to stop deprecation attributes
  48. #if defined(BOOST_UNORDERED_SUPPRESS_DEPRECATED)
  49. #define BOOST_UNORDERED_DEPRECATED(msg)
  50. #endif
  51. // BOOST_UNORDERED_DEPRECATED
  52. //
  53. // Wrapper around various depreaction attributes.
  54. #if defined(__has_cpp_attribute) && \
  55. (!defined(__cplusplus) || __cplusplus >= 201402)
  56. #if __has_cpp_attribute(deprecated) && !defined(BOOST_UNORDERED_DEPRECATED)
  57. #define BOOST_UNORDERED_DEPRECATED(msg) [[deprecated(msg)]]
  58. #endif
  59. #endif
  60. #if !defined(BOOST_UNORDERED_DEPRECATED)
  61. #if defined(__GNUC__) && __GNUC__ >= 4
  62. #define BOOST_UNORDERED_DEPRECATED(msg) __attribute__((deprecated))
  63. #elif defined(_MSC_VER) && _MSC_VER >= 1400
  64. #define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated(msg))
  65. #elif defined(_MSC_VER) && _MSC_VER >= 1310
  66. #define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated)
  67. #else
  68. #define BOOST_UNORDERED_DEPRECATED(msg)
  69. #endif
  70. #endif
  71. namespace boost {
  72. namespace unordered {
  73. using std::piecewise_construct;
  74. using std::piecewise_construct_t;
  75. namespace detail {
  76. template <typename Types> struct table;
  77. static const float minimum_max_load_factor = 1e-3f;
  78. static const std::size_t default_bucket_count = 0;
  79. struct move_tag
  80. {
  81. };
  82. struct empty_emplace
  83. {
  84. };
  85. struct no_key
  86. {
  87. no_key() {}
  88. template <class T> no_key(T const&) {}
  89. };
  90. struct converting_key
  91. {
  92. };
  93. namespace func {
  94. template <class T> inline void ignore_unused_variable_warning(T const&)
  95. {
  96. }
  97. } // namespace func
  98. //////////////////////////////////////////////////////////////////////////
  99. // iterator SFINAE
  100. template <typename I>
  101. struct is_forward : std::is_base_of<std::forward_iterator_tag,
  102. typename std::iterator_traits<I>::iterator_category>
  103. {
  104. };
  105. template <typename I, typename ReturnType>
  106. struct enable_if_forward
  107. : std::enable_if<boost::unordered::detail::is_forward<I>::value,
  108. ReturnType>
  109. {
  110. };
  111. template <typename I, typename ReturnType>
  112. struct disable_if_forward
  113. : std::enable_if<!boost::unordered::detail::is_forward<I>::value,
  114. ReturnType>
  115. {
  116. };
  117. } // namespace detail
  118. } // namespace unordered
  119. } // namespace boost
  120. namespace boost {
  121. namespace unordered {
  122. namespace detail {
  123. //////////////////////////////////////////////////////////////////////////
  124. // insert_size/initial_size
  125. template <class I>
  126. inline typename boost::unordered::detail::enable_if_forward<I,
  127. std::size_t>::type
  128. insert_size(I i, I j)
  129. {
  130. return static_cast<std::size_t>(std::distance(i, j));
  131. }
  132. template <class I>
  133. inline typename boost::unordered::detail::disable_if_forward<I,
  134. std::size_t>::type
  135. insert_size(I, I)
  136. {
  137. return 1;
  138. }
  139. template <class I>
  140. inline std::size_t initial_size(I i, I j,
  141. std::size_t num_buckets =
  142. boost::unordered::detail::default_bucket_count)
  143. {
  144. return (std::max)(
  145. boost::unordered::detail::insert_size(i, j), num_buckets);
  146. }
  147. //////////////////////////////////////////////////////////////////////////
  148. // compressed
  149. template <typename T, int Index>
  150. struct compressed_base : boost::empty_value<T>
  151. {
  152. compressed_base(T const& x) : empty_value<T>(boost::empty_init_t(), x)
  153. {
  154. }
  155. compressed_base(T& x, move_tag)
  156. : empty_value<T>(boost::empty_init_t(), std::move(x))
  157. {
  158. }
  159. T& get() { return empty_value<T>::get(); }
  160. T const& get() const { return empty_value<T>::get(); }
  161. };
  162. template <typename T, int Index>
  163. struct generate_base : boost::unordered::detail::compressed_base<T, Index>
  164. {
  165. typedef compressed_base<T, Index> type;
  166. generate_base() : type() {}
  167. };
  168. template <typename T1, typename T2>
  169. struct compressed
  170. : private boost::unordered::detail::generate_base<T1, 1>::type,
  171. private boost::unordered::detail::generate_base<T2, 2>::type
  172. {
  173. typedef typename generate_base<T1, 1>::type base1;
  174. typedef typename generate_base<T2, 2>::type base2;
  175. typedef T1 first_type;
  176. typedef T2 second_type;
  177. first_type& first() { return static_cast<base1*>(this)->get(); }
  178. first_type const& first() const
  179. {
  180. return static_cast<base1 const*>(this)->get();
  181. }
  182. second_type& second() { return static_cast<base2*>(this)->get(); }
  183. second_type const& second() const
  184. {
  185. return static_cast<base2 const*>(this)->get();
  186. }
  187. template <typename First, typename Second>
  188. compressed(First const& x1, Second const& x2) : base1(x1), base2(x2)
  189. {
  190. }
  191. compressed(compressed const& x) : base1(x.first()), base2(x.second()) {}
  192. compressed(compressed& x, move_tag m)
  193. : base1(x.first(), m), base2(x.second(), m)
  194. {
  195. }
  196. void assign(compressed const& x)
  197. {
  198. first() = x.first();
  199. second() = x.second();
  200. }
  201. void move_assign(compressed& x)
  202. {
  203. first() = std::move(x.first());
  204. second() = std::move(x.second());
  205. }
  206. void swap(compressed& x)
  207. {
  208. boost::core::invoke_swap(first(), x.first());
  209. boost::core::invoke_swap(second(), x.second());
  210. }
  211. private:
  212. // Prevent assignment just to make use of assign or
  213. // move_assign explicit.
  214. compressed& operator=(compressed const&);
  215. };
  216. //////////////////////////////////////////////////////////////////////////
  217. // pair_traits
  218. //
  219. // Used to get the types from a pair without instantiating it.
  220. template <typename Pair> struct pair_traits
  221. {
  222. typedef typename Pair::first_type first_type;
  223. typedef typename Pair::second_type second_type;
  224. };
  225. template <typename T1, typename T2> struct pair_traits<std::pair<T1, T2> >
  226. {
  227. typedef T1 first_type;
  228. typedef T2 second_type;
  229. };
  230. #if defined(BOOST_MSVC)
  231. #pragma warning(push)
  232. #pragma warning(disable : 4512) // assignment operator could not be generated.
  233. #pragma warning(disable : 4345) // behavior change: an object of POD type
  234. // constructed with an initializer of the form ()
  235. // will be default-initialized.
  236. #endif
  237. //////////////////////////////////////////////////////////////////////////
  238. // Bits and pieces for implementing traits
  239. template <typename T> typename std::add_lvalue_reference<T>::type make();
  240. struct choice2
  241. {
  242. typedef char (&type)[2];
  243. };
  244. struct choice1 : choice2
  245. {
  246. typedef char (&type)[1];
  247. };
  248. choice1 choose();
  249. typedef choice1::type yes_type;
  250. typedef choice2::type no_type;
  251. struct private_type
  252. {
  253. private_type const& operator,(int) const;
  254. };
  255. template <typename T> no_type is_private_type(T const&);
  256. yes_type is_private_type(private_type const&);
  257. struct convert_from_anything
  258. {
  259. template <typename T> convert_from_anything(T const&);
  260. };
  261. } // namespace detail
  262. } // namespace unordered
  263. } // namespace boost
  264. ////////////////////////////////////////////////////////////////////////////////
  265. //
  266. // Some utilities for implementing allocator_traits, but useful elsewhere so
  267. // they're always defined.
  268. namespace boost {
  269. namespace unordered {
  270. namespace detail {
  271. ////////////////////////////////////////////////////////////////////////////
  272. // Explicitly call a destructor
  273. #if defined(BOOST_MSVC)
  274. #pragma warning(push)
  275. #pragma warning(disable : 4100) // unreferenced formal parameter
  276. #endif
  277. namespace func {
  278. template <class T> inline void destroy(T* x) { x->~T(); }
  279. } // namespace func
  280. #if defined(BOOST_MSVC)
  281. #pragma warning(pop)
  282. #endif
  283. //////////////////////////////////////////////////////////////////////////
  284. // value_base
  285. //
  286. // Space used to store values.
  287. template <typename ValueType> struct value_base
  288. {
  289. typedef ValueType value_type;
  290. opt_storage<value_type> data_;
  291. value_base() : data_() {}
  292. void* address() { return this; }
  293. value_type& value() { return *(ValueType*)this; }
  294. value_type const& value() const { return *(ValueType const*)this; }
  295. value_type* value_ptr() { return (ValueType*)this; }
  296. value_type const* value_ptr() const { return (ValueType const*)this; }
  297. private:
  298. value_base& operator=(value_base const&);
  299. };
  300. //////////////////////////////////////////////////////////////////////////
  301. // optional
  302. // TODO: Use std::optional when available.
  303. template <typename T> class optional
  304. {
  305. boost::unordered::detail::value_base<T> value_;
  306. bool has_value_;
  307. void destroy()
  308. {
  309. if (has_value_) {
  310. boost::unordered::detail::func::destroy(value_.value_ptr());
  311. has_value_ = false;
  312. }
  313. }
  314. void move(optional<T>& x)
  315. {
  316. BOOST_ASSERT(!has_value_ && x.has_value_);
  317. new (value_.value_ptr()) T(std::move(x.value_.value()));
  318. boost::unordered::detail::func::destroy(x.value_.value_ptr());
  319. has_value_ = true;
  320. x.has_value_ = false;
  321. }
  322. public:
  323. optional() noexcept : has_value_(false) {}
  324. optional(optional const&) = delete;
  325. optional& operator=(optional const&) = delete;
  326. optional(optional<T>&& x) : has_value_(false)
  327. {
  328. if (x.has_value_) {
  329. move(x);
  330. }
  331. }
  332. explicit optional(T const& x) : has_value_(true)
  333. {
  334. new (value_.value_ptr()) T(x);
  335. }
  336. optional& operator=(optional<T>&& x)
  337. {
  338. destroy();
  339. if (x.has_value_) {
  340. move(x);
  341. }
  342. return *this;
  343. }
  344. ~optional() { destroy(); }
  345. bool has_value() const { return has_value_; }
  346. T& operator*() { return value_.value(); }
  347. T const& operator*() const { return value_.value(); }
  348. T* operator->() { return value_.value_ptr(); }
  349. T const* operator->() const { return value_.value_ptr(); }
  350. bool operator==(optional<T> const& x) const
  351. {
  352. return has_value_ ? x.has_value_ && value_.value() == x.value_.value()
  353. : !x.has_value_;
  354. }
  355. bool operator!=(optional<T> const& x) const { return !((*this) == x); }
  356. void swap(optional<T>& x)
  357. {
  358. if (has_value_ != x.has_value_) {
  359. if (has_value_) {
  360. x.move(*this);
  361. } else {
  362. move(x);
  363. }
  364. } else if (has_value_) {
  365. boost::core::invoke_swap(value_.value(), x.value_.value());
  366. }
  367. }
  368. friend void swap(optional<T>& x, optional<T>& y) { x.swap(y); }
  369. };
  370. } // namespace detail
  371. } // namespace unordered
  372. } // namespace boost
  373. ////////////////////////////////////////////////////////////////////////////////
  374. //
  375. // Allocator traits
  376. //
  377. namespace boost {
  378. namespace unordered {
  379. namespace detail {
  380. template <typename Alloc>
  381. struct allocator_traits : boost::allocator_traits<Alloc>
  382. {
  383. };
  384. template <typename Alloc, typename T>
  385. struct rebind_wrap : boost::allocator_rebind<Alloc, T>
  386. {
  387. };
  388. } // namespace detail
  389. } // namespace unordered
  390. } // namespace boost
  391. namespace boost {
  392. namespace unordered {
  393. namespace detail {
  394. namespace func {
  395. ////////////////////////////////////////////////////////////////////////
  396. // Trait to check for piecewise construction.
  397. template <typename A0> struct use_piecewise
  398. {
  399. static choice1::type test(choice1, std::piecewise_construct_t);
  400. static choice2::type test(choice2, ...);
  401. enum
  402. {
  403. value = sizeof(choice1::type) ==
  404. sizeof(test(choose(), boost::unordered::detail::make<A0>()))
  405. };
  406. };
  407. ////////////////////////////////////////////////////////////////////////
  408. // Construct from variadic parameters
  409. template <typename Alloc, typename T, typename... Args>
  410. inline void construct_from_args(
  411. Alloc& alloc, T* address, Args&&... args)
  412. {
  413. boost::allocator_construct(
  414. alloc, address, std::forward<Args>(args)...);
  415. }
  416. // For backwards compatibility, implement a special case for
  417. // piecewise_construct with boost::tuple
  418. template <typename A0> struct detect_std_tuple
  419. {
  420. template <class... Args>
  421. static choice1::type test(choice1, std::tuple<Args...> const&);
  422. static choice2::type test(choice2, ...);
  423. enum
  424. {
  425. value = sizeof(choice1::type) ==
  426. sizeof(test(choose(), boost::unordered::detail::make<A0>()))
  427. };
  428. };
  429. // Special case for piecewise_construct
  430. template <template <class...> class Tuple, class... Args,
  431. std::size_t... Is, class... TupleArgs>
  432. std::tuple<typename std::add_lvalue_reference<Args>::type...>
  433. to_std_tuple_impl(boost::mp11::mp_list<Args...>,
  434. Tuple<TupleArgs...>& tuple, boost::mp11::index_sequence<Is...>)
  435. {
  436. (void)tuple;
  437. using std::get;
  438. return std::tuple<typename std::add_lvalue_reference<Args>::type...>(
  439. get<Is>(tuple)...);
  440. }
  441. template <class T>
  442. using add_lvalue_reference_t =
  443. typename std::add_lvalue_reference<T>::type;
  444. template <template <class...> class Tuple, class... Args>
  445. boost::mp11::mp_transform<add_lvalue_reference_t,
  446. boost::mp11::mp_remove<std::tuple<Args...>,
  447. boost::tuples::null_type> >
  448. to_std_tuple(Tuple<Args...>& tuple)
  449. {
  450. using list = boost::mp11::mp_remove<boost::mp11::mp_list<Args...>,
  451. boost::tuples::null_type>;
  452. using list_size = boost::mp11::mp_size<list>;
  453. using index_seq = boost::mp11::make_index_sequence<list_size::value>;
  454. return to_std_tuple_impl(list{}, tuple, index_seq{});
  455. }
  456. template <typename Alloc, typename A, typename B, typename A0,
  457. typename A1, typename A2>
  458. inline typename std::enable_if<use_piecewise<A0>::value &&
  459. !detect_std_tuple<A1>::value &&
  460. !detect_std_tuple<A2>::value,
  461. void>::type
  462. construct_from_args(
  463. Alloc& alloc, std::pair<A, B>* address, A0&&, A1&& a1, A2&& a2)
  464. {
  465. boost::allocator_construct(alloc, address, std::piecewise_construct,
  466. to_std_tuple(a1), to_std_tuple(a2));
  467. }
  468. } // namespace func
  469. } // namespace detail
  470. } // namespace unordered
  471. } // namespace boost
  472. namespace boost {
  473. namespace unordered {
  474. namespace detail {
  475. ///////////////////////////////////////////////////////////////////
  476. //
  477. // Node construction
  478. template <typename NodeAlloc> struct node_constructor
  479. {
  480. typedef NodeAlloc node_allocator;
  481. typedef boost::unordered::detail::allocator_traits<NodeAlloc>
  482. node_allocator_traits;
  483. typedef typename node_allocator_traits::value_type node;
  484. typedef typename node_allocator_traits::pointer node_pointer;
  485. typedef typename node::value_type value_type;
  486. node_allocator& alloc_;
  487. node_pointer node_;
  488. node_constructor(node_allocator& n) : alloc_(n), node_() {}
  489. ~node_constructor();
  490. void create_node();
  491. // no throw
  492. node_pointer release()
  493. {
  494. BOOST_ASSERT(node_);
  495. node_pointer p = node_;
  496. node_ = node_pointer();
  497. return p;
  498. }
  499. private:
  500. node_constructor(node_constructor const&);
  501. node_constructor& operator=(node_constructor const&);
  502. };
  503. template <typename Alloc> node_constructor<Alloc>::~node_constructor()
  504. {
  505. if (node_) {
  506. boost::unordered::detail::func::destroy(boost::to_address(node_));
  507. node_allocator_traits::deallocate(alloc_, node_, 1);
  508. }
  509. }
  510. template <typename Alloc> void node_constructor<Alloc>::create_node()
  511. {
  512. BOOST_ASSERT(!node_);
  513. node_ = node_allocator_traits::allocate(alloc_, 1);
  514. new ((void*)boost::to_address(node_)) node();
  515. }
  516. template <typename NodeAlloc> struct node_tmp
  517. {
  518. typedef typename boost::allocator_value_type<NodeAlloc>::type node;
  519. typedef typename boost::allocator_pointer<NodeAlloc>::type node_pointer;
  520. typedef typename node::value_type value_type;
  521. typedef typename boost::allocator_rebind<NodeAlloc, value_type>::type
  522. value_allocator;
  523. NodeAlloc& alloc_;
  524. node_pointer node_;
  525. explicit node_tmp(node_pointer n, NodeAlloc& a) : alloc_(a), node_(n) {}
  526. ~node_tmp();
  527. // no throw
  528. node_pointer release()
  529. {
  530. node_pointer p = node_;
  531. node_ = node_pointer();
  532. return p;
  533. }
  534. };
  535. template <typename Alloc> node_tmp<Alloc>::~node_tmp()
  536. {
  537. if (node_) {
  538. value_allocator val_alloc(alloc_);
  539. boost::allocator_destroy(val_alloc, node_->value_ptr());
  540. boost::allocator_deallocate(alloc_, node_, 1);
  541. }
  542. }
  543. } // namespace detail
  544. } // namespace unordered
  545. } // namespace boost
  546. namespace boost {
  547. namespace unordered {
  548. namespace detail {
  549. namespace func {
  550. // Some nicer construct_node functions, might try to
  551. // improve implementation later.
  552. template <typename Alloc, typename... Args>
  553. inline typename boost::allocator_pointer<Alloc>::type
  554. construct_node_from_args(Alloc& alloc, Args&&... args)
  555. {
  556. typedef typename boost::allocator_value_type<Alloc>::type node;
  557. typedef typename node::value_type value_type;
  558. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  559. value_allocator;
  560. value_allocator val_alloc(alloc);
  561. node_constructor<Alloc> a(alloc);
  562. a.create_node();
  563. construct_from_args(
  564. val_alloc, a.node_->value_ptr(), std::forward<Args>(args)...);
  565. return a.release();
  566. }
  567. template <typename Alloc, typename U>
  568. inline typename boost::allocator_pointer<Alloc>::type construct_node(
  569. Alloc& alloc, U&& x)
  570. {
  571. node_constructor<Alloc> a(alloc);
  572. a.create_node();
  573. typedef typename boost::allocator_value_type<Alloc>::type node;
  574. typedef typename node::value_type value_type;
  575. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  576. value_allocator;
  577. value_allocator val_alloc(alloc);
  578. boost::allocator_construct(
  579. val_alloc, a.node_->value_ptr(), std::forward<U>(x));
  580. return a.release();
  581. }
  582. template <typename Alloc, typename Key>
  583. inline typename boost::allocator_pointer<Alloc>::type
  584. construct_node_pair(Alloc& alloc, Key&& k)
  585. {
  586. node_constructor<Alloc> a(alloc);
  587. a.create_node();
  588. typedef typename boost::allocator_value_type<Alloc>::type node;
  589. typedef typename node::value_type value_type;
  590. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  591. value_allocator;
  592. value_allocator val_alloc(alloc);
  593. boost::allocator_construct(val_alloc, a.node_->value_ptr(),
  594. std::piecewise_construct,
  595. std::forward_as_tuple(std::forward<Key>(k)),
  596. std::forward_as_tuple());
  597. return a.release();
  598. }
  599. template <typename Alloc, typename Key, typename Mapped>
  600. inline typename boost::allocator_pointer<Alloc>::type
  601. construct_node_pair(Alloc& alloc, Key&& k, Mapped&& m)
  602. {
  603. node_constructor<Alloc> a(alloc);
  604. a.create_node();
  605. typedef typename boost::allocator_value_type<Alloc>::type node;
  606. typedef typename node::value_type value_type;
  607. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  608. value_allocator;
  609. value_allocator val_alloc(alloc);
  610. boost::allocator_construct(val_alloc, a.node_->value_ptr(),
  611. std::piecewise_construct,
  612. std::forward_as_tuple(std::forward<Key>(k)),
  613. std::forward_as_tuple(std::forward<Mapped>(m)));
  614. return a.release();
  615. }
  616. template <typename Alloc, typename Key, typename... Args>
  617. inline typename boost::allocator_pointer<Alloc>::type
  618. construct_node_pair_from_args(Alloc& alloc, Key&& k, Args&&... args)
  619. {
  620. node_constructor<Alloc> a(alloc);
  621. a.create_node();
  622. typedef typename boost::allocator_value_type<Alloc>::type node;
  623. typedef typename node::value_type value_type;
  624. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  625. value_allocator;
  626. value_allocator val_alloc(alloc);
  627. boost::allocator_construct(val_alloc, a.node_->value_ptr(),
  628. std::piecewise_construct,
  629. std::forward_as_tuple(std::forward<Key>(k)),
  630. std::forward_as_tuple(std::forward<Args>(args)...));
  631. return a.release();
  632. }
  633. template <typename T, typename Alloc, typename Key>
  634. inline typename boost::allocator_pointer<Alloc>::type
  635. construct_node_from_key(T*, Alloc& alloc, Key&& k)
  636. {
  637. return construct_node(alloc, std::forward<Key>(k));
  638. }
  639. template <typename T, typename V, typename Alloc, typename Key>
  640. inline typename boost::allocator_pointer<Alloc>::type
  641. construct_node_from_key(std::pair<T const, V>*, Alloc& alloc, Key&& k)
  642. {
  643. return construct_node_pair(alloc, std::forward<Key>(k));
  644. }
  645. } // namespace func
  646. } // namespace detail
  647. } // namespace unordered
  648. } // namespace boost
  649. #if defined(BOOST_MSVC)
  650. #pragma warning(pop)
  651. #endif
  652. namespace boost {
  653. namespace unordered {
  654. namespace detail {
  655. //////////////////////////////////////////////////////////////////////////
  656. // Functions
  657. //
  658. // This double buffers the storage for the hash function and key equality
  659. // predicate in order to have exception safe copy/swap. To do so,
  660. // use 'construct_spare' to construct in the spare space, and then when
  661. // ready to use 'switch_functions' to switch to the new functions.
  662. // If an exception is thrown between these two calls, use
  663. // 'cleanup_spare_functions' to destroy the unused constructed functions.
  664. #if defined(_GLIBCXX_HAVE_BUILTIN_LAUNDER)
  665. // gcc-12 warns when accessing the `current_functions` of our `functions`
  666. // class below with `-Wmaybe-unitialized`. By laundering the pointer, we
  667. // silence the warning and assure the compiler that a valid object exists
  668. // in that region of storage. This warning is also generated in C++03
  669. // which does not have `std::launder`. The compiler builtin is always
  670. // available, regardless of the C++ standard used when compiling.
  671. template <class T> T* launder(T* p) noexcept
  672. {
  673. return __builtin_launder(p);
  674. }
  675. #else
  676. template <class T> T* launder(T* p) noexcept { return p; }
  677. #endif
  678. template <class H, class P> class functions
  679. {
  680. public:
  681. static const bool nothrow_move_assignable =
  682. std::is_nothrow_move_assignable<H>::value &&
  683. std::is_nothrow_move_assignable<P>::value;
  684. static const bool nothrow_move_constructible =
  685. std::is_nothrow_move_constructible<H>::value &&
  686. std::is_nothrow_move_constructible<P>::value;
  687. static const bool nothrow_swappable =
  688. boost::unordered::detail::is_nothrow_swappable<H>::value &&
  689. boost::unordered::detail::is_nothrow_swappable<P>::value;
  690. private:
  691. functions& operator=(functions const&);
  692. typedef compressed<H, P> function_pair;
  693. unsigned char current_; // 0/1 - Currently active functions
  694. // +2 - Both constructed
  695. opt_storage<function_pair> funcs_[2];
  696. public:
  697. functions(H const& hf, P const& eq) : current_(0)
  698. {
  699. construct_functions(current_, hf, eq);
  700. }
  701. functions(functions const& bf) : current_(0)
  702. {
  703. construct_functions(current_, bf.current_functions());
  704. }
  705. functions(functions& bf, boost::unordered::detail::move_tag)
  706. : current_(0)
  707. {
  708. construct_functions(current_, bf.current_functions(),
  709. std::integral_constant<bool, nothrow_move_constructible>());
  710. }
  711. ~functions()
  712. {
  713. BOOST_ASSERT(!(current_ & 2));
  714. destroy_functions(current_);
  715. }
  716. H const& hash_function() const { return current_functions().first(); }
  717. P const& key_eq() const { return current_functions().second(); }
  718. function_pair const& current_functions() const
  719. {
  720. return *::boost::unordered::detail::launder(
  721. static_cast<function_pair const*>(
  722. static_cast<void const*>(funcs_[current_ & 1].address())));
  723. }
  724. function_pair& current_functions()
  725. {
  726. return *::boost::unordered::detail::launder(
  727. static_cast<function_pair*>(
  728. static_cast<void*>(funcs_[current_ & 1].address())));
  729. }
  730. void construct_spare_functions(function_pair const& f)
  731. {
  732. BOOST_ASSERT(!(current_ & 2));
  733. construct_functions(current_ ^ 1, f);
  734. current_ |= 2;
  735. }
  736. void cleanup_spare_functions()
  737. {
  738. if (current_ & 2) {
  739. current_ = static_cast<unsigned char>(current_ & 1);
  740. destroy_functions(current_ ^ 1);
  741. }
  742. }
  743. void switch_functions()
  744. {
  745. BOOST_ASSERT(current_ & 2);
  746. destroy_functions(static_cast<unsigned char>(current_ & 1));
  747. current_ ^= 3;
  748. }
  749. private:
  750. void construct_functions(unsigned char which, H const& hf, P const& eq)
  751. {
  752. BOOST_ASSERT(!(which & 2));
  753. new ((void*)&funcs_[which]) function_pair(hf, eq);
  754. }
  755. void construct_functions(
  756. unsigned char which, function_pair const& f, std::false_type = {})
  757. {
  758. BOOST_ASSERT(!(which & 2));
  759. new ((void*)&funcs_[which]) function_pair(f);
  760. }
  761. void construct_functions(
  762. unsigned char which, function_pair& f, std::true_type)
  763. {
  764. BOOST_ASSERT(!(which & 2));
  765. new ((void*)&funcs_[which])
  766. function_pair(f, boost::unordered::detail::move_tag());
  767. }
  768. void destroy_functions(unsigned char which)
  769. {
  770. BOOST_ASSERT(!(which & 2));
  771. boost::unordered::detail::func::destroy(
  772. (function_pair*)(&funcs_[which]));
  773. }
  774. };
  775. #if defined(BOOST_MSVC)
  776. #pragma warning(push)
  777. #pragma warning(disable : 4127) // conditional expression is constant
  778. #endif
  779. //////////////////////////////////////////////////////////////////////////
  780. // convert double to std::size_t
  781. inline std::size_t double_to_size(double f)
  782. {
  783. return f >= static_cast<double>(
  784. (std::numeric_limits<std::size_t>::max)())
  785. ? (std::numeric_limits<std::size_t>::max)()
  786. : static_cast<std::size_t>(f);
  787. }
  788. //////////////////////////////////////////////////////////////////////////
  789. // iterator definitions
  790. namespace iterator_detail {
  791. template <class Node, class Bucket> class c_iterator;
  792. template <class Node, class Bucket> class iterator
  793. {
  794. public:
  795. typedef typename detail::node_value_type<Node> value_type;
  796. typedef value_type element_type;
  797. typedef value_type* pointer;
  798. typedef value_type& reference;
  799. typedef std::ptrdiff_t difference_type;
  800. typedef std::forward_iterator_tag iterator_category;
  801. iterator() : p(), itb() {}
  802. reference operator*() const noexcept { return dereference(); }
  803. pointer operator->() const noexcept
  804. {
  805. pointer x = std::addressof(p->value());
  806. return x;
  807. }
  808. iterator& operator++() noexcept
  809. {
  810. increment();
  811. return *this;
  812. }
  813. iterator operator++(int) noexcept
  814. {
  815. iterator old = *this;
  816. increment();
  817. return old;
  818. }
  819. bool operator==(iterator const& other) const noexcept
  820. {
  821. return equal(other);
  822. }
  823. bool operator!=(iterator const& other) const noexcept
  824. {
  825. return !equal(other);
  826. }
  827. bool operator==(
  828. boost::unordered::detail::iterator_detail::c_iterator<Node,
  829. Bucket> const& other) const noexcept
  830. {
  831. return equal(other);
  832. }
  833. bool operator!=(
  834. boost::unordered::detail::iterator_detail::c_iterator<Node,
  835. Bucket> const& other) const noexcept
  836. {
  837. return !equal(other);
  838. }
  839. private:
  840. typedef detail::node_pointer<Node> node_pointer;
  841. typedef grouped_bucket_iterator<Bucket> bucket_iterator;
  842. node_pointer p;
  843. bucket_iterator itb;
  844. template <class Types> friend struct boost::unordered::detail::table;
  845. template <class N, class B> friend class c_iterator;
  846. iterator(node_pointer p_, bucket_iterator itb_) : p(p_), itb(itb_) {}
  847. value_type& dereference() const noexcept { return p->value(); }
  848. bool equal(const iterator& x) const noexcept { return (p == x.p); }
  849. bool equal(
  850. const boost::unordered::detail::iterator_detail::c_iterator<Node,
  851. Bucket>& x) const noexcept
  852. {
  853. return (p == x.p);
  854. }
  855. void increment() noexcept
  856. {
  857. p = p->next;
  858. if (!p) {
  859. p = (++itb)->next;
  860. }
  861. }
  862. template <typename Archive>
  863. friend void serialization_track(Archive& ar, const iterator& x)
  864. {
  865. if (x.p) {
  866. track_address(ar, x.p);
  867. serialization_track(ar, x.itb);
  868. }
  869. }
  870. friend class boost::serialization::access;
  871. template <typename Archive> void serialize(Archive& ar, unsigned int)
  872. {
  873. if (!p)
  874. itb = bucket_iterator();
  875. serialize_tracked_address(ar, p);
  876. ar& core::make_nvp("bucket_iterator", itb);
  877. }
  878. };
  879. template <class Node, class Bucket> class c_iterator
  880. {
  881. public:
  882. typedef typename detail::node_value_type<Node> value_type;
  883. typedef value_type const element_type;
  884. typedef value_type const* pointer;
  885. typedef value_type const& reference;
  886. typedef std::ptrdiff_t difference_type;
  887. typedef std::forward_iterator_tag iterator_category;
  888. c_iterator() : p(), itb() {}
  889. c_iterator(iterator<Node, Bucket> it) : p(it.p), itb(it.itb) {}
  890. reference operator*() const noexcept { return dereference(); }
  891. pointer operator->() const noexcept
  892. {
  893. pointer x = std::addressof(p->value());
  894. return x;
  895. }
  896. c_iterator& operator++() noexcept
  897. {
  898. increment();
  899. return *this;
  900. }
  901. c_iterator operator++(int) noexcept
  902. {
  903. c_iterator old = *this;
  904. increment();
  905. return old;
  906. }
  907. bool operator==(c_iterator const& other) const noexcept
  908. {
  909. return equal(other);
  910. }
  911. bool operator!=(c_iterator const& other) const noexcept
  912. {
  913. return !equal(other);
  914. }
  915. bool operator==(
  916. boost::unordered::detail::iterator_detail::iterator<Node,
  917. Bucket> const& other) const noexcept
  918. {
  919. return equal(other);
  920. }
  921. bool operator!=(
  922. boost::unordered::detail::iterator_detail::iterator<Node,
  923. Bucket> const& other) const noexcept
  924. {
  925. return !equal(other);
  926. }
  927. private:
  928. typedef detail::node_pointer<Node> node_pointer;
  929. typedef grouped_bucket_iterator<Bucket> bucket_iterator;
  930. node_pointer p;
  931. bucket_iterator itb;
  932. template <class Types> friend struct boost::unordered::detail::table;
  933. template <class, class> friend class iterator;
  934. c_iterator(node_pointer p_, bucket_iterator itb_) : p(p_), itb(itb_)
  935. {
  936. }
  937. value_type const& dereference() const noexcept { return p->value(); }
  938. bool equal(const c_iterator& x) const noexcept { return (p == x.p); }
  939. void increment() noexcept
  940. {
  941. p = p->next;
  942. if (!p) {
  943. p = (++itb)->next;
  944. }
  945. }
  946. template <typename Archive>
  947. friend void serialization_track(Archive& ar, const c_iterator& x)
  948. {
  949. if (x.p) {
  950. track_address(ar, x.p);
  951. serialization_track(ar, x.itb);
  952. }
  953. }
  954. friend class boost::serialization::access;
  955. template <typename Archive> void serialize(Archive& ar, unsigned int)
  956. {
  957. if (!p)
  958. itb = bucket_iterator();
  959. serialize_tracked_address(ar, p);
  960. ar& core::make_nvp("bucket_iterator", itb);
  961. }
  962. };
  963. } // namespace iterator_detail
  964. //////////////////////////////////////////////////////////////////////////
  965. // table structure used by the containers
  966. template <typename Types>
  967. struct table : boost::unordered::detail::functions<typename Types::hasher,
  968. typename Types::key_equal>
  969. {
  970. private:
  971. table(table const&);
  972. table& operator=(table const&);
  973. public:
  974. typedef typename Types::hasher hasher;
  975. typedef typename Types::key_equal key_equal;
  976. typedef typename Types::const_key_type const_key_type;
  977. typedef typename Types::extractor extractor;
  978. typedef typename Types::value_type value_type;
  979. typedef typename Types::table table_impl;
  980. typedef boost::unordered::detail::functions<typename Types::hasher,
  981. typename Types::key_equal>
  982. functions;
  983. typedef typename Types::value_allocator value_allocator;
  984. typedef typename boost::allocator_void_pointer<value_allocator>::type
  985. void_pointer;
  986. typedef node<value_type, void_pointer> node_type;
  987. typedef boost::unordered::detail::grouped_bucket_array<
  988. bucket<node_type, void_pointer>, value_allocator, prime_fmod_size<> >
  989. bucket_array_type;
  990. typedef
  991. typename bucket_array_type::node_allocator_type node_allocator_type;
  992. typedef typename boost::allocator_pointer<node_allocator_type>::type
  993. node_pointer;
  994. typedef boost::unordered::detail::node_constructor<node_allocator_type>
  995. node_constructor;
  996. typedef boost::unordered::detail::node_tmp<node_allocator_type>
  997. node_tmp;
  998. typedef typename bucket_array_type::bucket_type bucket_type;
  999. typedef typename bucket_array_type::iterator bucket_iterator;
  1000. typedef typename bucket_array_type::local_iterator l_iterator;
  1001. typedef typename bucket_array_type::const_local_iterator cl_iterator;
  1002. typedef std::size_t size_type;
  1003. typedef iterator_detail::iterator<node_type, bucket_type> iterator;
  1004. typedef iterator_detail::c_iterator<node_type, bucket_type> c_iterator;
  1005. typedef std::pair<iterator, bool> emplace_return;
  1006. ////////////////////////////////////////////////////////////////////////
  1007. // Members
  1008. std::size_t size_;
  1009. float mlf_;
  1010. std::size_t max_load_;
  1011. bucket_array_type buckets_;
  1012. public:
  1013. ////////////////////////////////////////////////////////////////////////
  1014. // Data access
  1015. size_type bucket_count() const { return buckets_.bucket_count(); }
  1016. template <class Key>
  1017. iterator next_group(Key const& k, c_iterator n) const
  1018. {
  1019. c_iterator last = this->end();
  1020. while (n != last && this->key_eq()(k, extractor::extract(*n))) {
  1021. ++n;
  1022. }
  1023. return iterator(n.p, n.itb);
  1024. }
  1025. template <class Key> std::size_t group_count(Key const& k) const
  1026. {
  1027. if (size_ == 0) {
  1028. return 0;
  1029. }
  1030. std::size_t c = 0;
  1031. std::size_t const key_hash = this->hash(k);
  1032. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1033. bool found = false;
  1034. for (node_pointer pos = itb->next; pos; pos = pos->next) {
  1035. if (this->key_eq()(k, this->get_key(pos))) {
  1036. ++c;
  1037. found = true;
  1038. } else if (found) {
  1039. break;
  1040. }
  1041. }
  1042. return c;
  1043. }
  1044. node_allocator_type const& node_alloc() const
  1045. {
  1046. return buckets_.get_node_allocator();
  1047. }
  1048. node_allocator_type& node_alloc()
  1049. {
  1050. return buckets_.get_node_allocator();
  1051. }
  1052. std::size_t max_bucket_count() const
  1053. {
  1054. typedef typename bucket_array_type::size_policy size_policy;
  1055. return size_policy::size(size_policy::size_index(
  1056. boost::allocator_max_size(this->node_alloc())));
  1057. }
  1058. iterator begin() const
  1059. {
  1060. if (size_ == 0) {
  1061. return end();
  1062. }
  1063. bucket_iterator itb = buckets_.begin();
  1064. return iterator(itb->next, itb);
  1065. }
  1066. iterator end() const { return iterator(); }
  1067. l_iterator begin(std::size_t bucket_index) const
  1068. {
  1069. return buckets_.begin(bucket_index);
  1070. }
  1071. std::size_t hash_to_bucket(std::size_t hash_value) const
  1072. {
  1073. return buckets_.position(hash_value);
  1074. }
  1075. std::size_t bucket_size(std::size_t index) const
  1076. {
  1077. std::size_t count = 0;
  1078. if (size_ > 0) {
  1079. bucket_iterator itb = buckets_.at(index);
  1080. node_pointer n = itb->next;
  1081. while (n) {
  1082. ++count;
  1083. n = n->next;
  1084. }
  1085. }
  1086. return count;
  1087. }
  1088. ////////////////////////////////////////////////////////////////////////
  1089. // Load methods
  1090. void recalculate_max_load()
  1091. {
  1092. // From 6.3.1/13:
  1093. // Only resize when size >= mlf_ * count
  1094. std::size_t const bc = buckets_.bucket_count();
  1095. // it's important we do the `bc == 0` check here because the `mlf_`
  1096. // can be specified to be infinity. The operation `n * INF` is `INF`
  1097. // for all `n > 0` but NaN for `n == 0`.
  1098. //
  1099. max_load_ =
  1100. bc == 0 ? 0
  1101. : boost::unordered::detail::double_to_size(
  1102. static_cast<double>(mlf_) * static_cast<double>(bc));
  1103. }
  1104. void max_load_factor(float z)
  1105. {
  1106. BOOST_ASSERT(z > 0);
  1107. mlf_ = (std::max)(z, minimum_max_load_factor);
  1108. recalculate_max_load();
  1109. }
  1110. ////////////////////////////////////////////////////////////////////////
  1111. // Constructors
  1112. table()
  1113. : functions(hasher(), key_equal()), size_(0), mlf_(1.0f),
  1114. max_load_(0)
  1115. {
  1116. }
  1117. table(std::size_t num_buckets, hasher const& hf, key_equal const& eq,
  1118. value_allocator const& a)
  1119. : functions(hf, eq), size_(0), mlf_(1.0f), max_load_(0),
  1120. buckets_(num_buckets, a)
  1121. {
  1122. recalculate_max_load();
  1123. }
  1124. table(table const& x, value_allocator const& a)
  1125. : functions(x), size_(0), mlf_(x.mlf_), max_load_(0),
  1126. buckets_(x.size_, a)
  1127. {
  1128. recalculate_max_load();
  1129. }
  1130. table(table& x, boost::unordered::detail::move_tag m)
  1131. : functions(x, m), size_(x.size_), mlf_(x.mlf_),
  1132. max_load_(x.max_load_), buckets_(std::move(x.buckets_))
  1133. {
  1134. x.size_ = 0;
  1135. x.max_load_ = 0;
  1136. }
  1137. table(table& x, value_allocator const& a,
  1138. boost::unordered::detail::move_tag m)
  1139. : functions(x, m), size_(0), mlf_(x.mlf_), max_load_(0),
  1140. buckets_(x.bucket_count(), a)
  1141. {
  1142. recalculate_max_load();
  1143. }
  1144. ////////////////////////////////////////////////////////////////////////
  1145. // Swap and Move
  1146. void swap_allocators(table& other, std::false_type)
  1147. {
  1148. boost::unordered::detail::func::ignore_unused_variable_warning(other);
  1149. // According to 23.2.1.8, if propagate_on_container_swap is
  1150. // false the behaviour is undefined unless the allocators
  1151. // are equal.
  1152. BOOST_ASSERT(node_alloc() == other.node_alloc());
  1153. }
  1154. // Not nothrow swappable
  1155. void swap(table& x, std::false_type)
  1156. {
  1157. if (this == &x) {
  1158. return;
  1159. }
  1160. this->construct_spare_functions(x.current_functions());
  1161. BOOST_TRY { x.construct_spare_functions(this->current_functions()); }
  1162. BOOST_CATCH(...)
  1163. {
  1164. this->cleanup_spare_functions();
  1165. BOOST_RETHROW
  1166. }
  1167. BOOST_CATCH_END
  1168. this->switch_functions();
  1169. x.switch_functions();
  1170. buckets_.swap(x.buckets_);
  1171. boost::core::invoke_swap(size_, x.size_);
  1172. std::swap(mlf_, x.mlf_);
  1173. std::swap(max_load_, x.max_load_);
  1174. }
  1175. // Nothrow swappable
  1176. void swap(table& x, std::true_type)
  1177. {
  1178. buckets_.swap(x.buckets_);
  1179. boost::core::invoke_swap(size_, x.size_);
  1180. std::swap(mlf_, x.mlf_);
  1181. std::swap(max_load_, x.max_load_);
  1182. this->current_functions().swap(x.current_functions());
  1183. }
  1184. // Only swaps the allocators if propagate_on_container_swap.
  1185. // If not propagate_on_container_swap and allocators aren't
  1186. // equal, behaviour is undefined.
  1187. void swap(table& x)
  1188. {
  1189. BOOST_ASSERT(boost::allocator_propagate_on_container_swap<
  1190. node_allocator_type>::type::value ||
  1191. node_alloc() == x.node_alloc());
  1192. swap(x, std::integral_constant<bool, functions::nothrow_swappable>());
  1193. }
  1194. // Only call with nodes allocated with the currect allocator, or
  1195. // one that is equal to it. (Can't assert because other's
  1196. // allocators might have already been moved).
  1197. void move_buckets_from(table& other)
  1198. {
  1199. buckets_ = std::move(other.buckets_);
  1200. size_ = other.size_;
  1201. max_load_ = other.max_load_;
  1202. other.size_ = 0;
  1203. other.max_load_ = 0;
  1204. }
  1205. // For use in the constructor when allocators might be different.
  1206. void move_construct_buckets(table& src)
  1207. {
  1208. if (this->node_alloc() == src.node_alloc()) {
  1209. move_buckets_from(src);
  1210. return;
  1211. }
  1212. if (src.size_ == 0) {
  1213. return;
  1214. }
  1215. BOOST_ASSERT(buckets_.bucket_count() == src.buckets_.bucket_count());
  1216. this->reserve(src.size_);
  1217. for (iterator pos = src.begin(); pos != src.end(); ++pos) {
  1218. node_tmp b(detail::func::construct_node(
  1219. this->node_alloc(), std::move(pos.p->value())),
  1220. this->node_alloc());
  1221. const_key_type& k = this->get_key(b.node_);
  1222. std::size_t key_hash = this->hash(k);
  1223. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1224. buckets_.insert_node(itb, b.release());
  1225. ++size_;
  1226. }
  1227. }
  1228. ////////////////////////////////////////////////////////////////////////
  1229. // Delete/destruct
  1230. ~table() { delete_buckets(); }
  1231. void delete_node(node_pointer p)
  1232. {
  1233. node_allocator_type alloc = this->node_alloc();
  1234. value_allocator val_alloc(alloc);
  1235. boost::allocator_destroy(val_alloc, p->value_ptr());
  1236. boost::unordered::detail::func::destroy(boost::to_address(p));
  1237. boost::allocator_deallocate(alloc, p, 1);
  1238. }
  1239. void delete_buckets()
  1240. {
  1241. iterator pos = begin(), last = this->end();
  1242. for (; pos != last;) {
  1243. node_pointer p = pos.p;
  1244. bucket_iterator itb = pos.itb;
  1245. ++pos;
  1246. buckets_.extract_node(itb, p);
  1247. delete_node(p);
  1248. --size_;
  1249. }
  1250. buckets_.clear();
  1251. }
  1252. ////////////////////////////////////////////////////////////////////////
  1253. // Clear
  1254. void clear_impl();
  1255. ////////////////////////////////////////////////////////////////////////
  1256. // Assignment
  1257. template <typename UniqueType>
  1258. void assign(table const& x, UniqueType is_unique)
  1259. {
  1260. typedef
  1261. typename boost::allocator_propagate_on_container_copy_assignment<
  1262. node_allocator_type>::type pocca;
  1263. if (this != &x) {
  1264. assign(x, is_unique, std::integral_constant<bool, pocca::value>());
  1265. }
  1266. }
  1267. template <typename UniqueType>
  1268. void assign(table const& x, UniqueType is_unique, std::false_type)
  1269. {
  1270. // Strong exception safety.
  1271. this->construct_spare_functions(x.current_functions());
  1272. BOOST_TRY
  1273. {
  1274. mlf_ = x.mlf_;
  1275. recalculate_max_load();
  1276. this->reserve_for_insert(x.size_);
  1277. this->clear_impl();
  1278. }
  1279. BOOST_CATCH(...)
  1280. {
  1281. this->cleanup_spare_functions();
  1282. BOOST_RETHROW
  1283. }
  1284. BOOST_CATCH_END
  1285. this->switch_functions();
  1286. copy_buckets(x, is_unique);
  1287. }
  1288. template <typename UniqueType>
  1289. void assign(table const& x, UniqueType is_unique, std::true_type)
  1290. {
  1291. if (node_alloc() == x.node_alloc()) {
  1292. buckets_.reset_allocator(x.node_alloc());
  1293. assign(x, is_unique, std::false_type());
  1294. } else {
  1295. bucket_array_type new_buckets(x.size_, x.node_alloc());
  1296. this->construct_spare_functions(x.current_functions());
  1297. this->switch_functions();
  1298. // Delete everything with current allocators before assigning
  1299. // the new ones.
  1300. delete_buckets();
  1301. buckets_.reset_allocator(x.node_alloc());
  1302. buckets_ = std::move(new_buckets);
  1303. // Copy over other data, all no throw.
  1304. mlf_ = x.mlf_;
  1305. reserve(x.size_);
  1306. // Finally copy the elements.
  1307. if (x.size_) {
  1308. copy_buckets(x, is_unique);
  1309. }
  1310. }
  1311. }
  1312. template <typename UniqueType>
  1313. void move_assign(table& x, UniqueType is_unique)
  1314. {
  1315. if (this != &x) {
  1316. move_assign(x, is_unique,
  1317. std::integral_constant<bool,
  1318. boost::allocator_propagate_on_container_move_assignment<
  1319. node_allocator_type>::type::value>());
  1320. }
  1321. }
  1322. // Propagate allocator
  1323. template <typename UniqueType>
  1324. void move_assign(table& x, UniqueType, std::true_type)
  1325. {
  1326. if (!functions::nothrow_move_assignable) {
  1327. this->construct_spare_functions(x.current_functions());
  1328. this->switch_functions();
  1329. } else {
  1330. this->current_functions().move_assign(x.current_functions());
  1331. }
  1332. delete_buckets();
  1333. buckets_.reset_allocator(x.buckets_.get_node_allocator());
  1334. mlf_ = x.mlf_;
  1335. move_buckets_from(x);
  1336. }
  1337. // Don't propagate allocator
  1338. template <typename UniqueType>
  1339. void move_assign(table& x, UniqueType is_unique, std::false_type)
  1340. {
  1341. if (node_alloc() == x.node_alloc()) {
  1342. move_assign_equal_alloc(x);
  1343. } else {
  1344. move_assign_realloc(x, is_unique);
  1345. }
  1346. }
  1347. void move_assign_equal_alloc(table& x)
  1348. {
  1349. if (!functions::nothrow_move_assignable) {
  1350. this->construct_spare_functions(x.current_functions());
  1351. this->switch_functions();
  1352. } else {
  1353. this->current_functions().move_assign(x.current_functions());
  1354. }
  1355. delete_buckets();
  1356. mlf_ = x.mlf_;
  1357. move_buckets_from(x);
  1358. }
  1359. template <typename UniqueType>
  1360. void move_assign_realloc(table& x, UniqueType is_unique)
  1361. {
  1362. this->construct_spare_functions(x.current_functions());
  1363. BOOST_TRY
  1364. {
  1365. mlf_ = x.mlf_;
  1366. recalculate_max_load();
  1367. if (x.size_ > 0) {
  1368. this->reserve_for_insert(x.size_);
  1369. }
  1370. this->clear_impl();
  1371. }
  1372. BOOST_CATCH(...)
  1373. {
  1374. this->cleanup_spare_functions();
  1375. BOOST_RETHROW
  1376. }
  1377. BOOST_CATCH_END
  1378. this->switch_functions();
  1379. move_assign_buckets(x, is_unique);
  1380. }
  1381. // Accessors
  1382. const_key_type& get_key(node_pointer n) const
  1383. {
  1384. return extractor::extract(n->value());
  1385. }
  1386. template <class Key> std::size_t hash(Key const& k) const
  1387. {
  1388. return this->hash_function()(k);
  1389. }
  1390. // Find Node
  1391. template <class Key>
  1392. node_pointer find_node_impl(Key const& x, bucket_iterator itb) const
  1393. {
  1394. node_pointer p = node_pointer();
  1395. if (itb != buckets_.end()) {
  1396. key_equal const& pred = this->key_eq();
  1397. p = itb->next;
  1398. for (; p; p = p->next) {
  1399. if (pred(x, extractor::extract(p->value()))) {
  1400. break;
  1401. }
  1402. }
  1403. }
  1404. return p;
  1405. }
  1406. template <class Key> node_pointer find_node(Key const& k) const
  1407. {
  1408. std::size_t const key_hash = this->hash(k);
  1409. return find_node_impl(k, buckets_.at(buckets_.position(key_hash)));
  1410. }
  1411. node_pointer find_node(const_key_type& k, bucket_iterator itb) const
  1412. {
  1413. return find_node_impl(k, itb);
  1414. }
  1415. template <class Key> iterator find(Key const& k) const
  1416. {
  1417. return this->transparent_find(
  1418. k, this->hash_function(), this->key_eq());
  1419. }
  1420. template <class Key, class Hash, class Pred>
  1421. inline iterator transparent_find(
  1422. Key const& k, Hash const& h, Pred const& pred) const
  1423. {
  1424. if (size_ > 0) {
  1425. std::size_t const key_hash = h(k);
  1426. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1427. for (node_pointer p = itb->next; p; p = p->next) {
  1428. if (BOOST_LIKELY(pred(k, extractor::extract(p->value())))) {
  1429. return iterator(p, itb);
  1430. }
  1431. }
  1432. }
  1433. return this->end();
  1434. }
  1435. template <class Key>
  1436. node_pointer* find_prev(Key const& key, bucket_iterator itb)
  1437. {
  1438. if (size_ > 0) {
  1439. key_equal pred = this->key_eq();
  1440. for (node_pointer* pp = std::addressof(itb->next); *pp;
  1441. pp = std::addressof((*pp)->next)) {
  1442. if (pred(key, extractor::extract((*pp)->value()))) {
  1443. return pp;
  1444. }
  1445. }
  1446. }
  1447. typedef node_pointer* node_pointer_pointer;
  1448. return node_pointer_pointer();
  1449. }
  1450. // Extract and erase
  1451. template <class Key> node_pointer extract_by_key_impl(Key const& k)
  1452. {
  1453. iterator it = this->find(k);
  1454. if (it == this->end()) {
  1455. return node_pointer();
  1456. }
  1457. buckets_.extract_node(it.itb, it.p);
  1458. --size_;
  1459. return it.p;
  1460. }
  1461. // Reserve and rehash
  1462. void transfer_node(
  1463. node_pointer p, bucket_type&, bucket_array_type& new_buckets)
  1464. {
  1465. const_key_type& key = extractor::extract(p->value());
  1466. std::size_t const h = this->hash(key);
  1467. bucket_iterator itnewb = new_buckets.at(new_buckets.position(h));
  1468. new_buckets.insert_node(itnewb, p);
  1469. }
  1470. static std::size_t min_buckets(std::size_t num_elements, float mlf)
  1471. {
  1472. std::size_t num_buckets = static_cast<std::size_t>(
  1473. std::ceil(static_cast<float>(num_elements) / mlf));
  1474. if (num_buckets == 0 && num_elements > 0) { // mlf == inf
  1475. num_buckets = 1;
  1476. }
  1477. return num_buckets;
  1478. }
  1479. void rehash(std::size_t);
  1480. void reserve(std::size_t);
  1481. void reserve_for_insert(std::size_t);
  1482. void rehash_impl(std::size_t);
  1483. ////////////////////////////////////////////////////////////////////////
  1484. // Unique keys
  1485. // equals
  1486. bool equals_unique(table const& other) const
  1487. {
  1488. if (this->size_ != other.size_)
  1489. return false;
  1490. c_iterator pos = this->begin();
  1491. c_iterator last = this->end();
  1492. while (pos != last) {
  1493. node_pointer p = pos.p;
  1494. node_pointer p2 = other.find_node(this->get_key(p));
  1495. if (!p2 || !(p->value() == p2->value())) {
  1496. return false;
  1497. }
  1498. ++pos;
  1499. }
  1500. return true;
  1501. }
  1502. // Emplace/Insert
  1503. template <typename... Args>
  1504. iterator emplace_hint_unique(
  1505. c_iterator hint, const_key_type& k, Args&&... args)
  1506. {
  1507. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  1508. return iterator(hint.p, hint.itb);
  1509. } else {
  1510. return emplace_unique(k, std::forward<Args>(args)...).first;
  1511. }
  1512. }
  1513. template <typename... Args>
  1514. emplace_return emplace_unique(const_key_type& k, Args&&... args)
  1515. {
  1516. std::size_t key_hash = this->hash(k);
  1517. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1518. node_pointer pos = this->find_node_impl(k, itb);
  1519. if (pos) {
  1520. return emplace_return(iterator(pos, itb), false);
  1521. } else {
  1522. node_tmp b(boost::unordered::detail::func::construct_node_from_args(
  1523. this->node_alloc(), std::forward<Args>(args)...),
  1524. this->node_alloc());
  1525. if (size_ + 1 > max_load_) {
  1526. reserve(size_ + 1);
  1527. itb = buckets_.at(buckets_.position(key_hash));
  1528. }
  1529. node_pointer p = b.release();
  1530. buckets_.insert_node(itb, p);
  1531. ++size_;
  1532. return emplace_return(iterator(p, itb), true);
  1533. }
  1534. }
  1535. template <typename... Args>
  1536. iterator emplace_hint_unique(c_iterator hint, no_key, Args&&... args)
  1537. {
  1538. node_tmp b(boost::unordered::detail::func::construct_node_from_args(
  1539. this->node_alloc(), std::forward<Args>(args)...),
  1540. this->node_alloc());
  1541. const_key_type& k = this->get_key(b.node_);
  1542. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  1543. return iterator(hint.p, hint.itb);
  1544. }
  1545. std::size_t const key_hash = this->hash(k);
  1546. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1547. node_pointer p = this->find_node_impl(k, itb);
  1548. if (p) {
  1549. return iterator(p, itb);
  1550. }
  1551. if (size_ + 1 > max_load_) {
  1552. this->reserve(size_ + 1);
  1553. itb = buckets_.at(buckets_.position(key_hash));
  1554. }
  1555. p = b.release();
  1556. buckets_.insert_node(itb, p);
  1557. ++size_;
  1558. return iterator(p, itb);
  1559. }
  1560. template <typename... Args>
  1561. emplace_return emplace_unique(no_key, Args&&... args)
  1562. {
  1563. node_tmp b(boost::unordered::detail::func::construct_node_from_args(
  1564. this->node_alloc(), std::forward<Args>(args)...),
  1565. this->node_alloc());
  1566. const_key_type& k = this->get_key(b.node_);
  1567. std::size_t key_hash = this->hash(k);
  1568. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1569. node_pointer pos = this->find_node_impl(k, itb);
  1570. if (pos) {
  1571. return emplace_return(iterator(pos, itb), false);
  1572. } else {
  1573. if (size_ + 1 > max_load_) {
  1574. reserve(size_ + 1);
  1575. itb = buckets_.at(buckets_.position(key_hash));
  1576. }
  1577. node_pointer p = b.release();
  1578. buckets_.insert_node(itb, p);
  1579. ++size_;
  1580. return emplace_return(iterator(p, itb), true);
  1581. }
  1582. }
  1583. template <typename K, typename V>
  1584. emplace_return emplace_unique(converting_key, K&& k, V&& v)
  1585. {
  1586. using alloc_cted = allocator_constructed<node_allocator_type,
  1587. typename Types::key_type>;
  1588. alloc_cted key(this->node_alloc(), std::forward<K>(k));
  1589. return emplace_unique(
  1590. key.value(), std::move(key.value()), std::forward<V>(v));
  1591. }
  1592. template <typename Key> emplace_return try_emplace_unique(Key&& k)
  1593. {
  1594. std::size_t key_hash = this->hash(k);
  1595. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1596. node_pointer pos = this->find_node_impl(k, itb);
  1597. if (pos) {
  1598. return emplace_return(iterator(pos, itb), false);
  1599. } else {
  1600. node_allocator_type alloc = node_alloc();
  1601. value_type* dispatch = BOOST_NULLPTR;
  1602. node_tmp tmp(detail::func::construct_node_from_key(
  1603. dispatch, alloc, std::forward<Key>(k)),
  1604. alloc);
  1605. if (size_ + 1 > max_load_) {
  1606. reserve(size_ + 1);
  1607. itb = buckets_.at(buckets_.position(key_hash));
  1608. }
  1609. node_pointer p = tmp.release();
  1610. buckets_.insert_node(itb, p);
  1611. ++size_;
  1612. return emplace_return(iterator(p, itb), true);
  1613. }
  1614. }
  1615. template <typename Key>
  1616. iterator try_emplace_hint_unique(c_iterator hint, Key&& k)
  1617. {
  1618. if (hint.p && this->key_eq()(extractor::extract(*hint), k)) {
  1619. return iterator(hint.p, hint.itb);
  1620. } else {
  1621. return try_emplace_unique(k).first;
  1622. }
  1623. }
  1624. template <typename Key, typename... Args>
  1625. emplace_return try_emplace_unique(Key&& k, Args&&... args)
  1626. {
  1627. std::size_t key_hash = this->hash(k);
  1628. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1629. node_pointer pos = this->find_node_impl(k, itb);
  1630. if (pos) {
  1631. return emplace_return(iterator(pos, itb), false);
  1632. }
  1633. node_tmp b(
  1634. boost::unordered::detail::func::construct_node_pair_from_args(
  1635. this->node_alloc(), k, std::forward<Args>(args)...),
  1636. this->node_alloc());
  1637. if (size_ + 1 > max_load_) {
  1638. reserve(size_ + 1);
  1639. itb = buckets_.at(buckets_.position(key_hash));
  1640. }
  1641. pos = b.release();
  1642. buckets_.insert_node(itb, pos);
  1643. ++size_;
  1644. return emplace_return(iterator(pos, itb), true);
  1645. }
  1646. template <typename Key, typename... Args>
  1647. iterator try_emplace_hint_unique(
  1648. c_iterator hint, Key&& k, Args&&... args)
  1649. {
  1650. if (hint.p && this->key_eq()(hint->first, k)) {
  1651. return iterator(hint.p, hint.itb);
  1652. } else {
  1653. return try_emplace_unique(k, std::forward<Args>(args)...).first;
  1654. }
  1655. }
  1656. template <typename Key, typename M>
  1657. emplace_return insert_or_assign_unique(Key&& k, M&& obj)
  1658. {
  1659. std::size_t key_hash = this->hash(k);
  1660. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1661. node_pointer p = this->find_node_impl(k, itb);
  1662. if (p) {
  1663. p->value().second = std::forward<M>(obj);
  1664. return emplace_return(iterator(p, itb), false);
  1665. }
  1666. node_tmp b(
  1667. boost::unordered::detail::func::construct_node_pair(
  1668. this->node_alloc(), std::forward<Key>(k), std::forward<M>(obj)),
  1669. node_alloc());
  1670. if (size_ + 1 > max_load_) {
  1671. reserve(size_ + 1);
  1672. itb = buckets_.at(buckets_.position(key_hash));
  1673. }
  1674. p = b.release();
  1675. buckets_.insert_node(itb, p);
  1676. ++size_;
  1677. return emplace_return(iterator(p, itb), true);
  1678. }
  1679. template <typename NodeType, typename InsertReturnType>
  1680. void move_insert_node_type_unique(
  1681. NodeType& np, InsertReturnType& result)
  1682. {
  1683. if (!np) {
  1684. result.position = this->end();
  1685. result.inserted = false;
  1686. return;
  1687. }
  1688. const_key_type& k = this->get_key(np.ptr_);
  1689. std::size_t const key_hash = this->hash(k);
  1690. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1691. node_pointer p = this->find_node_impl(k, itb);
  1692. if (p) {
  1693. iterator pos(p, itb);
  1694. result.node = std::move(np);
  1695. result.position = pos;
  1696. result.inserted = false;
  1697. return;
  1698. }
  1699. this->reserve_for_insert(size_ + 1);
  1700. p = np.ptr_;
  1701. itb = buckets_.at(buckets_.position(key_hash));
  1702. buckets_.insert_node(itb, p);
  1703. np.ptr_ = node_pointer();
  1704. ++size_;
  1705. result.position = iterator(p, itb);
  1706. result.inserted = true;
  1707. }
  1708. template <typename NodeType>
  1709. iterator move_insert_node_type_with_hint_unique(
  1710. c_iterator hint, NodeType& np)
  1711. {
  1712. if (!np) {
  1713. return this->end();
  1714. }
  1715. const_key_type& k = this->get_key(np.ptr_);
  1716. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  1717. return iterator(hint.p, hint.itb);
  1718. }
  1719. std::size_t const key_hash = this->hash(k);
  1720. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1721. node_pointer p = this->find_node_impl(k, itb);
  1722. if (p) {
  1723. return iterator(p, itb);
  1724. }
  1725. p = np.ptr_;
  1726. if (size_ + 1 > max_load_) {
  1727. this->reserve(size_ + 1);
  1728. itb = buckets_.at(buckets_.position(key_hash));
  1729. }
  1730. buckets_.insert_node(itb, p);
  1731. ++size_;
  1732. np.ptr_ = node_pointer();
  1733. return iterator(p, itb);
  1734. }
  1735. template <typename Types2>
  1736. void merge_unique(boost::unordered::detail::table<Types2>& other)
  1737. {
  1738. typedef boost::unordered::detail::table<Types2> other_table;
  1739. BOOST_UNORDERED_STATIC_ASSERT(
  1740. (std::is_same<node_type, typename other_table::node_type>::value));
  1741. BOOST_ASSERT(this->node_alloc() == other.node_alloc());
  1742. if (other.size_ == 0) {
  1743. return;
  1744. }
  1745. this->reserve_for_insert(size_ + other.size_);
  1746. iterator last = other.end();
  1747. for (iterator pos = other.begin(); pos != last;) {
  1748. const_key_type& key = other.get_key(pos.p);
  1749. std::size_t const key_hash = this->hash(key);
  1750. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1751. if (this->find_node_impl(key, itb)) {
  1752. ++pos;
  1753. continue;
  1754. }
  1755. iterator old = pos;
  1756. ++pos;
  1757. node_pointer p = other.extract_by_iterator_unique(old);
  1758. buckets_.insert_node(itb, p);
  1759. ++size_;
  1760. }
  1761. }
  1762. ////////////////////////////////////////////////////////////////////////
  1763. // Insert range methods
  1764. //
  1765. // if hash function throws, or inserting > 1 element, basic exception
  1766. // safety strong otherwise
  1767. template <class InputIt>
  1768. void insert_range_unique(no_key, InputIt i, InputIt j)
  1769. {
  1770. hasher const& hf = this->hash_function();
  1771. node_allocator_type alloc = this->node_alloc();
  1772. for (; i != j; ++i) {
  1773. node_tmp tmp(detail::func::construct_node(alloc, *i), alloc);
  1774. value_type const& value = tmp.node_->value();
  1775. const_key_type& key = extractor::extract(value);
  1776. std::size_t const h = hf(key);
  1777. bucket_iterator itb = buckets_.at(buckets_.position(h));
  1778. node_pointer it = find_node_impl(key, itb);
  1779. if (it) {
  1780. continue;
  1781. }
  1782. if (size_ + 1 > max_load_) {
  1783. reserve(size_ + 1);
  1784. itb = buckets_.at(buckets_.position(h));
  1785. }
  1786. node_pointer nptr = tmp.release();
  1787. buckets_.insert_node(itb, nptr);
  1788. ++size_;
  1789. }
  1790. }
  1791. ////////////////////////////////////////////////////////////////////////
  1792. // Extract
  1793. inline node_pointer extract_by_iterator_unique(c_iterator i)
  1794. {
  1795. node_pointer p = i.p;
  1796. bucket_iterator itb = i.itb;
  1797. buckets_.extract_node(itb, p);
  1798. --size_;
  1799. return p;
  1800. }
  1801. ////////////////////////////////////////////////////////////////////////
  1802. // Erase
  1803. //
  1804. template <class Key> std::size_t erase_key_unique_impl(Key const& k)
  1805. {
  1806. bucket_iterator itb = buckets_.at(buckets_.position(this->hash(k)));
  1807. node_pointer* pp = this->find_prev(k, itb);
  1808. if (!pp) {
  1809. return 0;
  1810. }
  1811. node_pointer p = *pp;
  1812. buckets_.extract_node_after(itb, pp);
  1813. this->delete_node(p);
  1814. --size_;
  1815. return 1;
  1816. }
  1817. iterator erase_node(c_iterator pos)
  1818. {
  1819. c_iterator next = pos;
  1820. ++next;
  1821. bucket_iterator itb = pos.itb;
  1822. node_pointer* pp = std::addressof(itb->next);
  1823. while (*pp != pos.p) {
  1824. pp = std::addressof((*pp)->next);
  1825. }
  1826. buckets_.extract_node_after(itb, pp);
  1827. this->delete_node(pos.p);
  1828. --size_;
  1829. return iterator(next.p, next.itb);
  1830. }
  1831. iterator erase_nodes_range(c_iterator first, c_iterator last)
  1832. {
  1833. if (first == last) {
  1834. return iterator(last.p, last.itb);
  1835. }
  1836. // though `first` stores of a copy of a pointer to a node, we wish to
  1837. // mutate the pointers stored internally by the singly-linked list in
  1838. // each bucket group so we have to retrieve it manually by iterating
  1839. //
  1840. bucket_iterator itb = first.itb;
  1841. node_pointer* pp = std::addressof(itb->next);
  1842. while (*pp != first.p) {
  1843. pp = std::addressof((*pp)->next);
  1844. }
  1845. while (*pp != last.p) {
  1846. node_pointer p = *pp;
  1847. *pp = (*pp)->next;
  1848. this->delete_node(p);
  1849. --size_;
  1850. bool const at_end = !(*pp);
  1851. bool const is_empty_bucket = !itb->next;
  1852. if (at_end) {
  1853. if (is_empty_bucket) {
  1854. buckets_.unlink_bucket(itb++);
  1855. } else {
  1856. ++itb;
  1857. }
  1858. pp = std::addressof(itb->next);
  1859. }
  1860. }
  1861. return iterator(last.p, last.itb);
  1862. }
  1863. ////////////////////////////////////////////////////////////////////////
  1864. // fill_buckets_unique
  1865. void copy_buckets(table const& src, std::true_type)
  1866. {
  1867. BOOST_ASSERT(size_ == 0);
  1868. this->reserve_for_insert(src.size_);
  1869. for (iterator pos = src.begin(); pos != src.end(); ++pos) {
  1870. value_type const& value = *pos;
  1871. const_key_type& key = extractor::extract(value);
  1872. std::size_t const key_hash = this->hash(key);
  1873. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1874. node_allocator_type alloc = this->node_alloc();
  1875. node_tmp tmp(detail::func::construct_node(alloc, value), alloc);
  1876. buckets_.insert_node(itb, tmp.release());
  1877. ++size_;
  1878. }
  1879. }
  1880. void move_assign_buckets(table& src, std::true_type)
  1881. {
  1882. BOOST_ASSERT(size_ == 0);
  1883. BOOST_ASSERT(max_load_ >= src.size_);
  1884. iterator last = src.end();
  1885. node_allocator_type alloc = this->node_alloc();
  1886. for (iterator pos = src.begin(); pos != last; ++pos) {
  1887. value_type value = std::move(*pos);
  1888. const_key_type& key = extractor::extract(value);
  1889. std::size_t const key_hash = this->hash(key);
  1890. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1891. node_tmp tmp(
  1892. detail::func::construct_node(alloc, std::move(value)), alloc);
  1893. buckets_.insert_node(itb, tmp.release());
  1894. ++size_;
  1895. }
  1896. }
  1897. ////////////////////////////////////////////////////////////////////////
  1898. // Equivalent keys
  1899. // Equality
  1900. bool equals_equiv(table const& other) const
  1901. {
  1902. if (this->size_ != other.size_)
  1903. return false;
  1904. iterator last = this->end();
  1905. for (iterator n1 = this->begin(); n1 != last;) {
  1906. const_key_type& k = extractor::extract(*n1);
  1907. iterator n2 = other.find(k);
  1908. if (n2 == other.end()) {
  1909. return false;
  1910. }
  1911. iterator end1 = this->next_group(k, n1);
  1912. iterator end2 = other.next_group(k, n2);
  1913. if (!group_equals_equiv(n1, end1, n2, end2)) {
  1914. return false;
  1915. }
  1916. n1 = end1;
  1917. }
  1918. return true;
  1919. }
  1920. static bool group_equals_equiv(
  1921. iterator n1, iterator end1, iterator n2, iterator end2)
  1922. {
  1923. for (;;) {
  1924. if (*n1 != *n2)
  1925. break;
  1926. ++n1;
  1927. ++n2;
  1928. if (n1 == end1)
  1929. return n2 == end2;
  1930. if (n2 == end2)
  1931. return false;
  1932. }
  1933. for (iterator n1a = n1, n2a = n2;;) {
  1934. ++n1a;
  1935. ++n2a;
  1936. if (n1a == end1) {
  1937. if (n2a == end2)
  1938. break;
  1939. else
  1940. return false;
  1941. }
  1942. if (n2a == end2)
  1943. return false;
  1944. }
  1945. iterator start = n1;
  1946. for (; n1 != end1; ++n1) {
  1947. value_type const& v = *n1;
  1948. if (!find_equiv(start, n1, v)) {
  1949. std::size_t matches = count_equal_equiv(n2, end2, v);
  1950. if (!matches)
  1951. return false;
  1952. iterator t = n1;
  1953. if (matches != 1 + count_equal_equiv(++t, end1, v))
  1954. return false;
  1955. }
  1956. }
  1957. return true;
  1958. }
  1959. static bool find_equiv(iterator n, iterator last, value_type const& v)
  1960. {
  1961. for (; n != last; ++n)
  1962. if (*n == v)
  1963. return true;
  1964. return false;
  1965. }
  1966. static std::size_t count_equal_equiv(
  1967. iterator n, iterator last, value_type const& v)
  1968. {
  1969. std::size_t count = 0;
  1970. for (; n != last; ++n)
  1971. if (*n == v)
  1972. ++count;
  1973. return count;
  1974. }
  1975. // Emplace/Insert
  1976. iterator emplace_equiv(node_pointer n)
  1977. {
  1978. node_tmp a(n, this->node_alloc());
  1979. const_key_type& k = this->get_key(a.node_);
  1980. std::size_t key_hash = this->hash(k);
  1981. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  1982. node_pointer hint = this->find_node_impl(k, itb);
  1983. if (size_ + 1 > max_load_) {
  1984. this->reserve(size_ + 1);
  1985. itb = buckets_.at(buckets_.position(key_hash));
  1986. }
  1987. node_pointer p = a.release();
  1988. buckets_.insert_node_hint(itb, p, hint);
  1989. ++size_;
  1990. return iterator(p, itb);
  1991. }
  1992. iterator emplace_hint_equiv(c_iterator hint, node_pointer n)
  1993. {
  1994. node_tmp a(n, this->node_alloc());
  1995. const_key_type& k = this->get_key(a.node_);
  1996. bucket_iterator itb = hint.itb;
  1997. node_pointer p = hint.p;
  1998. std::size_t key_hash = 0u;
  1999. bool const needs_rehash = (size_ + 1 > max_load_);
  2000. bool const usable_hint = (p && this->key_eq()(k, this->get_key(p)));
  2001. if (!usable_hint) {
  2002. key_hash = this->hash(k);
  2003. itb = buckets_.at(buckets_.position(key_hash));
  2004. p = this->find_node_impl(k, itb);
  2005. } else if (usable_hint && needs_rehash) {
  2006. key_hash = this->hash(k);
  2007. }
  2008. if (needs_rehash) {
  2009. this->reserve(size_ + 1);
  2010. itb = buckets_.at(buckets_.position(key_hash));
  2011. }
  2012. a.release();
  2013. buckets_.insert_node_hint(itb, n, p);
  2014. ++size_;
  2015. return iterator(n, itb);
  2016. }
  2017. void emplace_no_rehash_equiv(node_pointer n)
  2018. {
  2019. BOOST_ASSERT(size_ + 1 <= max_load_);
  2020. node_tmp a(n, this->node_alloc());
  2021. const_key_type& k = this->get_key(a.node_);
  2022. std::size_t key_hash = this->hash(k);
  2023. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2024. node_pointer hint = this->find_node_impl(k, itb);
  2025. node_pointer p = a.release();
  2026. buckets_.insert_node_hint(itb, p, hint);
  2027. ++size_;
  2028. }
  2029. template <typename NodeType>
  2030. iterator move_insert_node_type_equiv(NodeType& np)
  2031. {
  2032. iterator result;
  2033. if (np) {
  2034. this->reserve_for_insert(size_ + 1);
  2035. const_key_type& k = this->get_key(np.ptr_);
  2036. std::size_t key_hash = this->hash(k);
  2037. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2038. node_pointer hint = this->find_node_impl(k, itb);
  2039. buckets_.insert_node_hint(itb, np.ptr_, hint);
  2040. ++size_;
  2041. result = iterator(np.ptr_, itb);
  2042. np.ptr_ = node_pointer();
  2043. }
  2044. return result;
  2045. }
  2046. template <typename NodeType>
  2047. iterator move_insert_node_type_with_hint_equiv(
  2048. c_iterator hint, NodeType& np)
  2049. {
  2050. iterator result;
  2051. if (np) {
  2052. bucket_iterator itb = hint.itb;
  2053. node_pointer pos = hint.p;
  2054. const_key_type& k = this->get_key(np.ptr_);
  2055. std::size_t key_hash = this->hash(k);
  2056. if (size_ + 1 > max_load_) {
  2057. this->reserve(size_ + 1);
  2058. itb = buckets_.at(buckets_.position(key_hash));
  2059. }
  2060. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  2061. } else {
  2062. itb = buckets_.at(buckets_.position(key_hash));
  2063. pos = this->find_node_impl(k, itb);
  2064. }
  2065. buckets_.insert_node_hint(itb, np.ptr_, pos);
  2066. ++size_;
  2067. result = iterator(np.ptr_, itb);
  2068. np.ptr_ = node_pointer();
  2069. }
  2070. return result;
  2071. }
  2072. ////////////////////////////////////////////////////////////////////////
  2073. // Insert range methods
  2074. // if hash function throws, or inserting > 1 element, basic exception
  2075. // safety. Strong otherwise
  2076. template <class I>
  2077. typename boost::unordered::detail::enable_if_forward<I, void>::type
  2078. insert_range_equiv(I i, I j)
  2079. {
  2080. if (i == j)
  2081. return;
  2082. std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
  2083. if (distance == 1) {
  2084. emplace_equiv(boost::unordered::detail::func::construct_node(
  2085. this->node_alloc(), *i));
  2086. } else {
  2087. // Only require basic exception safety here
  2088. this->reserve_for_insert(size_ + distance);
  2089. for (; i != j; ++i) {
  2090. emplace_no_rehash_equiv(
  2091. boost::unordered::detail::func::construct_node(
  2092. this->node_alloc(), *i));
  2093. }
  2094. }
  2095. }
  2096. template <class I>
  2097. typename boost::unordered::detail::disable_if_forward<I, void>::type
  2098. insert_range_equiv(I i, I j)
  2099. {
  2100. for (; i != j; ++i) {
  2101. emplace_equiv(boost::unordered::detail::func::construct_node(
  2102. this->node_alloc(), *i));
  2103. }
  2104. }
  2105. ////////////////////////////////////////////////////////////////////////
  2106. // Extract
  2107. inline node_pointer extract_by_iterator_equiv(c_iterator n)
  2108. {
  2109. node_pointer p = n.p;
  2110. bucket_iterator itb = n.itb;
  2111. buckets_.extract_node(itb, p);
  2112. --size_;
  2113. return p;
  2114. }
  2115. ////////////////////////////////////////////////////////////////////////
  2116. // Erase
  2117. //
  2118. // no throw
  2119. template <class Key> std::size_t erase_key_equiv_impl(Key const& k)
  2120. {
  2121. std::size_t deleted_count = 0;
  2122. bucket_iterator itb = buckets_.at(buckets_.position(this->hash(k)));
  2123. node_pointer* pp = this->find_prev(k, itb);
  2124. if (pp) {
  2125. while (*pp && this->key_eq()(this->get_key(*pp), k)) {
  2126. node_pointer p = *pp;
  2127. *pp = (*pp)->next;
  2128. this->delete_node(p);
  2129. --size_;
  2130. ++deleted_count;
  2131. }
  2132. if (!itb->next) {
  2133. buckets_.unlink_bucket(itb);
  2134. }
  2135. }
  2136. return deleted_count;
  2137. }
  2138. std::size_t erase_key_equiv(const_key_type& k)
  2139. {
  2140. return this->erase_key_equiv_impl(k);
  2141. }
  2142. ////////////////////////////////////////////////////////////////////////
  2143. // fill_buckets
  2144. void copy_buckets(table const& src, std::false_type)
  2145. {
  2146. BOOST_ASSERT(size_ == 0);
  2147. this->reserve_for_insert(src.size_);
  2148. iterator last = src.end();
  2149. for (iterator pos = src.begin(); pos != last; ++pos) {
  2150. value_type const& value = *pos;
  2151. const_key_type& key = extractor::extract(value);
  2152. std::size_t const key_hash = this->hash(key);
  2153. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2154. node_allocator_type alloc = this->node_alloc();
  2155. node_tmp tmp(detail::func::construct_node(alloc, value), alloc);
  2156. node_pointer hint = this->find_node_impl(key, itb);
  2157. buckets_.insert_node_hint(itb, tmp.release(), hint);
  2158. ++size_;
  2159. }
  2160. }
  2161. void move_assign_buckets(table& src, std::false_type)
  2162. {
  2163. BOOST_ASSERT(size_ == 0);
  2164. BOOST_ASSERT(max_load_ >= src.size_);
  2165. iterator last = src.end();
  2166. node_allocator_type alloc = this->node_alloc();
  2167. for (iterator pos = src.begin(); pos != last; ++pos) {
  2168. value_type value = std::move(*pos);
  2169. const_key_type& key = extractor::extract(value);
  2170. std::size_t const key_hash = this->hash(key);
  2171. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2172. node_pointer hint = this->find_node_impl(key, itb);
  2173. node_tmp tmp(
  2174. detail::func::construct_node(alloc, std::move(value)), alloc);
  2175. buckets_.insert_node_hint(itb, tmp.release(), hint);
  2176. ++size_;
  2177. }
  2178. }
  2179. };
  2180. //////////////////////////////////////////////////////////////////////////
  2181. // Clear
  2182. template <typename Types> inline void table<Types>::clear_impl()
  2183. {
  2184. bucket_iterator itb = buckets_.begin(), last = buckets_.end();
  2185. for (; itb != last;) {
  2186. bucket_iterator next_itb = itb;
  2187. ++next_itb;
  2188. node_pointer* pp = std::addressof(itb->next);
  2189. while (*pp) {
  2190. node_pointer p = *pp;
  2191. buckets_.extract_node_after(itb, pp);
  2192. this->delete_node(p);
  2193. --size_;
  2194. }
  2195. itb = next_itb;
  2196. }
  2197. }
  2198. //////////////////////////////////////////////////////////////////////////
  2199. // Reserve & Rehash
  2200. // if hash function throws, basic exception safety
  2201. // strong otherwise.
  2202. template <typename Types>
  2203. inline void table<Types>::rehash(std::size_t num_buckets)
  2204. {
  2205. num_buckets = buckets_.bucket_count_for(
  2206. (std::max)(min_buckets(size_, mlf_), num_buckets));
  2207. if (num_buckets != this->bucket_count()) {
  2208. this->rehash_impl(num_buckets);
  2209. }
  2210. }
  2211. template <class Types>
  2212. inline void table<Types>::reserve(std::size_t num_elements)
  2213. {
  2214. std::size_t num_buckets = min_buckets(num_elements, mlf_);
  2215. this->rehash(num_buckets);
  2216. }
  2217. template <class Types>
  2218. inline void table<Types>::reserve_for_insert(std::size_t num_elements)
  2219. {
  2220. if (num_elements > max_load_) {
  2221. std::size_t const num_buckets = static_cast<std::size_t>(
  2222. 1.0f + std::ceil(static_cast<float>(num_elements) / mlf_));
  2223. this->rehash_impl(num_buckets);
  2224. }
  2225. }
  2226. template <class Types>
  2227. inline void table<Types>::rehash_impl(std::size_t num_buckets)
  2228. {
  2229. bucket_array_type new_buckets(
  2230. num_buckets, buckets_.get_allocator());
  2231. BOOST_TRY
  2232. {
  2233. boost::unordered::detail::span<bucket_type> bspan = buckets_.raw();
  2234. bucket_type* pos = bspan.data;
  2235. std::size_t size = bspan.size;
  2236. bucket_type* last = pos + size;
  2237. for (; pos != last; ++pos) {
  2238. bucket_type& b = *pos;
  2239. for (node_pointer p = b.next; p;) {
  2240. node_pointer next_p = p->next;
  2241. transfer_node(p, b, new_buckets);
  2242. p = next_p;
  2243. b.next = p;
  2244. }
  2245. }
  2246. }
  2247. BOOST_CATCH(...)
  2248. {
  2249. for (bucket_iterator pos = new_buckets.begin();
  2250. pos != new_buckets.end(); ++pos) {
  2251. bucket_type& b = *pos;
  2252. for (node_pointer p = b.next; p;) {
  2253. node_pointer next_p = p->next;
  2254. delete_node(p);
  2255. --size_;
  2256. p = next_p;
  2257. }
  2258. }
  2259. buckets_.unlink_empty_buckets();
  2260. BOOST_RETHROW
  2261. }
  2262. BOOST_CATCH_END
  2263. buckets_ = std::move(new_buckets);
  2264. recalculate_max_load();
  2265. }
  2266. #if defined(BOOST_MSVC)
  2267. #pragma warning(pop)
  2268. #endif
  2269. ////////////////////////////////////////////////////////////////////////
  2270. // key extractors
  2271. //
  2272. // no throw
  2273. //
  2274. // 'extract_key' is called with the emplace parameters to return a
  2275. // key if available or 'no_key' is one isn't and will need to be
  2276. // constructed. This could be done by overloading the emplace
  2277. // implementation
  2278. // for the different cases, but that's a bit tricky on compilers without
  2279. // variadic templates.
  2280. template <typename Key, typename T> struct is_key
  2281. {
  2282. template <typename T2> static choice1::type test(T2 const&);
  2283. static choice2::type test(Key const&);
  2284. enum
  2285. {
  2286. value = sizeof(test(boost::unordered::detail::make<T>())) ==
  2287. sizeof(choice2::type)
  2288. };
  2289. typedef typename std::conditional<value, Key const&, no_key>::type type;
  2290. };
  2291. template <class ValueType> struct set_extractor
  2292. {
  2293. typedef ValueType value_type;
  2294. typedef ValueType key_type;
  2295. static key_type const& extract(value_type const& v) { return v; }
  2296. static key_type const& extract(value_type&& v) { return v; }
  2297. static no_key extract() { return no_key(); }
  2298. template <class Arg> static no_key extract(Arg const&)
  2299. {
  2300. return no_key();
  2301. }
  2302. template <class Arg1, class Arg2, class... Args>
  2303. static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
  2304. {
  2305. return no_key();
  2306. }
  2307. };
  2308. template <class ValueType> struct map_extractor
  2309. {
  2310. typedef ValueType value_type;
  2311. typedef typename std::remove_const<typename boost::unordered::detail::
  2312. pair_traits<ValueType>::first_type>::type key_type;
  2313. static key_type const& extract(value_type const& v) { return v.first; }
  2314. template <class Second>
  2315. static key_type const& extract(std::pair<key_type, Second> const& v)
  2316. {
  2317. return v.first;
  2318. }
  2319. template <class Second>
  2320. static key_type const& extract(
  2321. std::pair<key_type const, Second> const& v)
  2322. {
  2323. return v.first;
  2324. }
  2325. template <class Arg1>
  2326. static key_type const& extract(key_type const& k, Arg1 const&)
  2327. {
  2328. return k;
  2329. }
  2330. static no_key extract() { return no_key(); }
  2331. template <class Arg> static no_key extract(Arg const&)
  2332. {
  2333. return no_key();
  2334. }
  2335. template <class Arg1, class Arg2>
  2336. static typename std::conditional<
  2337. (is_similar<Arg1, key_type>::value ||
  2338. is_complete_and_move_constructible<key_type>::value),
  2339. converting_key, no_key>::type
  2340. extract(Arg1 const&, Arg2 const&)
  2341. {
  2342. return {};
  2343. }
  2344. template <class Arg1, class Arg2, class Arg3, class... Args>
  2345. static no_key extract(
  2346. Arg1 const&, Arg2 const&, Arg3 const&, Args const&...)
  2347. {
  2348. return no_key();
  2349. }
  2350. template <template <class...> class Tuple, typename T2>
  2351. static no_key extract(
  2352. std::piecewise_construct_t, Tuple<> const&, T2 const&)
  2353. {
  2354. return no_key();
  2355. }
  2356. template <template <typename...> class Tuple, typename T, typename T2,
  2357. typename... Args>
  2358. static auto extract(
  2359. std::piecewise_construct_t, Tuple<T, Args...> const& k, T2 const&) ->
  2360. typename std::enable_if<
  2361. !std::is_same<T, boost::tuples::null_type>::value,
  2362. typename is_key<key_type, T>::type>::type
  2363. {
  2364. using std::get;
  2365. return typename is_key<key_type, T>::type(get<0>(k));
  2366. }
  2367. };
  2368. template <class Container, class Predicate>
  2369. typename Container::size_type erase_if(Container& c, Predicate& pred)
  2370. {
  2371. typedef typename Container::size_type size_type;
  2372. typedef typename Container::iterator iterator;
  2373. size_type const size = c.size();
  2374. for (iterator pos = c.begin(), last = c.end(); pos != last;) {
  2375. if (pred(*pos)) {
  2376. pos = c.erase(pos);
  2377. } else {
  2378. ++pos;
  2379. }
  2380. }
  2381. return (size - c.size());
  2382. }
  2383. } // namespace detail
  2384. } // namespace unordered
  2385. } // namespace boost
  2386. #endif