implementation.hpp 115 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691
  1. // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
  2. // Copyright (C) 2005-2016 Daniel James
  3. // Copyright (C) 2022 Joaquin M Lopez Munoz.
  4. // Copyright (C) 2022 Christian Mazakas
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
  9. #define BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
  10. #include <boost/config.hpp>
  11. #if defined(BOOST_HAS_PRAGMA_ONCE)
  12. #pragma once
  13. #endif
  14. #include <boost/assert.hpp>
  15. #include <boost/core/allocator_traits.hpp>
  16. #include <boost/core/bit.hpp>
  17. #include <boost/core/no_exceptions_support.hpp>
  18. #include <boost/core/pointer_traits.hpp>
  19. #include <boost/limits.hpp>
  20. #include <boost/move/move.hpp>
  21. #include <boost/preprocessor/arithmetic/inc.hpp>
  22. #include <boost/preprocessor/cat.hpp>
  23. #include <boost/preprocessor/repetition/enum.hpp>
  24. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  25. #include <boost/preprocessor/repetition/enum_params.hpp>
  26. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  27. #include <boost/preprocessor/seq/enum.hpp>
  28. #include <boost/preprocessor/seq/size.hpp>
  29. #include <boost/swap.hpp>
  30. #include <boost/throw_exception.hpp>
  31. #include <boost/tuple/tuple.hpp>
  32. #include <boost/type_traits/add_lvalue_reference.hpp>
  33. #include <boost/type_traits/aligned_storage.hpp>
  34. #include <boost/type_traits/alignment_of.hpp>
  35. #include <boost/type_traits/integral_constant.hpp>
  36. #include <boost/type_traits/is_base_of.hpp>
  37. #include <boost/type_traits/is_class.hpp>
  38. #include <boost/type_traits/is_convertible.hpp>
  39. #include <boost/type_traits/is_empty.hpp>
  40. #include <boost/type_traits/is_nothrow_move_assignable.hpp>
  41. #include <boost/type_traits/is_nothrow_move_constructible.hpp>
  42. #include <boost/type_traits/is_nothrow_swappable.hpp>
  43. #include <boost/type_traits/is_same.hpp>
  44. #include <boost/type_traits/make_void.hpp>
  45. #include <boost/type_traits/remove_const.hpp>
  46. #include <boost/unordered/detail/fca.hpp>
  47. #include <boost/unordered/detail/type_traits.hpp>
  48. #include <boost/unordered/detail/fwd.hpp>
  49. #include <boost/utility/addressof.hpp>
  50. #include <boost/utility/enable_if.hpp>
  51. #include <cmath>
  52. #include <iterator>
  53. #include <stdexcept>
  54. #include <utility>
  55. #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
  56. #include <type_traits>
  57. #endif
  58. ////////////////////////////////////////////////////////////////////////////////
  59. // Configuration
  60. //
  61. // Unless documented elsewhere these configuration macros should be considered
  62. // an implementation detail, I'll try not to break them, but you never know.
  63. // Use Sun C++ workarounds
  64. // I'm not sure which versions of the compiler require these workarounds, so
  65. // I'm just using them of everything older than the current test compilers
  66. // (as of May 2017).
  67. #if !defined(BOOST_UNORDERED_SUN_WORKAROUNDS1)
  68. #if BOOST_COMP_SUNPRO && BOOST_COMP_SUNPRO < BOOST_VERSION_NUMBER(5, 20, 0)
  69. #define BOOST_UNORDERED_SUN_WORKAROUNDS1 1
  70. #else
  71. #define BOOST_UNORDERED_SUN_WORKAROUNDS1 0
  72. #endif
  73. #endif
  74. // BOOST_UNORDERED_EMPLACE_LIMIT = The maximum number of parameters in
  75. // emplace (not including things like hints). Don't set it to a lower value, as
  76. // that might break something.
  77. #if !defined BOOST_UNORDERED_EMPLACE_LIMIT
  78. #define BOOST_UNORDERED_EMPLACE_LIMIT 10
  79. #endif
  80. // BOOST_UNORDERED_TUPLE_ARGS
  81. //
  82. // Maximum number of std::tuple members to support, or 0 if std::tuple
  83. // isn't avaiable. More are supported when full C++11 is used.
  84. // Already defined, so do nothing
  85. #if defined(BOOST_UNORDERED_TUPLE_ARGS)
  86. // Assume if we have C++11 tuple it's properly variadic,
  87. // and just use a max number of 10 arguments.
  88. #elif !defined(BOOST_NO_CXX11_HDR_TUPLE)
  89. #define BOOST_UNORDERED_TUPLE_ARGS 10
  90. // Visual C++ has a decent enough tuple for piecewise construction,
  91. // so use that if available, using _VARIADIC_MAX for the maximum
  92. // number of parameters. Note that this comes after the check
  93. // for a full C++11 tuple.
  94. #elif defined(BOOST_MSVC)
  95. #if !BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
  96. #define BOOST_UNORDERED_TUPLE_ARGS 0
  97. #elif defined(_VARIADIC_MAX)
  98. #define BOOST_UNORDERED_TUPLE_ARGS _VARIADIC_MAX
  99. #else
  100. #define BOOST_UNORDERED_TUPLE_ARGS 5
  101. #endif
  102. // Assume that we don't have std::tuple
  103. #else
  104. #define BOOST_UNORDERED_TUPLE_ARGS 0
  105. #endif
  106. #if BOOST_UNORDERED_TUPLE_ARGS
  107. #include <tuple>
  108. #endif
  109. // BOOST_UNORDERED_CXX11_CONSTRUCTION
  110. //
  111. // Use C++11 construction, requires variadic arguments, good construct support
  112. // in allocator_traits and piecewise construction of std::pair
  113. // Otherwise allocators aren't used for construction/destruction
  114. #if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT && \
  115. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && BOOST_UNORDERED_TUPLE_ARGS
  116. #if BOOST_COMP_SUNPRO && BOOST_LIB_STD_GNU
  117. // Sun C++ std::pair piecewise construction doesn't seem to be exception safe.
  118. // (At least for Sun C++ 12.5 using libstdc++).
  119. #define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
  120. #elif BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 7, 0)
  121. // Piecewise construction in GCC 4.6 doesn't work for uncopyable types.
  122. #define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
  123. #elif !defined(BOOST_NO_CXX11_ALLOCATOR)
  124. #define BOOST_UNORDERED_CXX11_CONSTRUCTION 1
  125. #endif
  126. #endif
  127. #if !defined(BOOST_UNORDERED_CXX11_CONSTRUCTION)
  128. #define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
  129. #endif
  130. #if BOOST_UNORDERED_CXX11_CONSTRUCTION
  131. #include <boost/mp11/list.hpp>
  132. #include <boost/mp11/algorithm.hpp>
  133. #endif
  134. // BOOST_UNORDERED_SUPPRESS_DEPRECATED
  135. //
  136. // Define to stop deprecation attributes
  137. #if defined(BOOST_UNORDERED_SUPPRESS_DEPRECATED)
  138. #define BOOST_UNORDERED_DEPRECATED(msg)
  139. #endif
  140. // BOOST_UNORDERED_DEPRECATED
  141. //
  142. // Wrapper around various depreaction attributes.
  143. #if defined(__has_cpp_attribute) && \
  144. (!defined(__cplusplus) || __cplusplus >= 201402)
  145. #if __has_cpp_attribute(deprecated) && !defined(BOOST_UNORDERED_DEPRECATED)
  146. #define BOOST_UNORDERED_DEPRECATED(msg) [[deprecated(msg)]]
  147. #endif
  148. #endif
  149. #if !defined(BOOST_UNORDERED_DEPRECATED)
  150. #if defined(__GNUC__) && __GNUC__ >= 4
  151. #define BOOST_UNORDERED_DEPRECATED(msg) __attribute__((deprecated))
  152. #elif defined(_MSC_VER) && _MSC_VER >= 1400
  153. #define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated(msg))
  154. #elif defined(_MSC_VER) && _MSC_VER >= 1310
  155. #define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated)
  156. #else
  157. #define BOOST_UNORDERED_DEPRECATED(msg)
  158. #endif
  159. #endif
  160. namespace boost {
  161. namespace unordered {
  162. namespace detail {
  163. template <typename Types> struct table;
  164. static const float minimum_max_load_factor = 1e-3f;
  165. static const std::size_t default_bucket_count = 0;
  166. struct move_tag
  167. {
  168. };
  169. struct empty_emplace
  170. {
  171. };
  172. struct no_key
  173. {
  174. no_key() {}
  175. template <class T> no_key(T const&) {}
  176. };
  177. namespace func {
  178. template <class T> inline void ignore_unused_variable_warning(T const&)
  179. {
  180. }
  181. }
  182. //////////////////////////////////////////////////////////////////////////
  183. // iterator SFINAE
  184. template <typename I>
  185. struct is_forward : boost::is_base_of<std::forward_iterator_tag,
  186. typename std::iterator_traits<I>::iterator_category>
  187. {
  188. };
  189. template <typename I, typename ReturnType>
  190. struct enable_if_forward
  191. : boost::enable_if_c<boost::unordered::detail::is_forward<I>::value,
  192. ReturnType>
  193. {
  194. };
  195. template <typename I, typename ReturnType>
  196. struct disable_if_forward
  197. : boost::disable_if_c<boost::unordered::detail::is_forward<I>::value,
  198. ReturnType>
  199. {
  200. };
  201. }
  202. }
  203. }
  204. namespace boost {
  205. namespace unordered {
  206. namespace detail {
  207. //////////////////////////////////////////////////////////////////////////
  208. // insert_size/initial_size
  209. template <class I>
  210. inline typename boost::unordered::detail::enable_if_forward<I,
  211. std::size_t>::type
  212. insert_size(I i, I j)
  213. {
  214. return static_cast<std::size_t>(std::distance(i, j));
  215. }
  216. template <class I>
  217. inline typename boost::unordered::detail::disable_if_forward<I,
  218. std::size_t>::type insert_size(I, I)
  219. {
  220. return 1;
  221. }
  222. template <class I>
  223. inline std::size_t initial_size(I i, I j,
  224. std::size_t num_buckets =
  225. boost::unordered::detail::default_bucket_count)
  226. {
  227. return (std::max)(
  228. boost::unordered::detail::insert_size(i, j), num_buckets);
  229. }
  230. //////////////////////////////////////////////////////////////////////////
  231. // compressed
  232. template <typename T, int Index>
  233. struct compressed_base : boost::empty_value<T>
  234. {
  235. compressed_base(T const& x) : empty_value<T>(boost::empty_init_t(), x)
  236. {
  237. }
  238. compressed_base(T& x, move_tag)
  239. : empty_value<T>(boost::empty_init_t(), boost::move(x))
  240. {
  241. }
  242. T& get() { return empty_value<T>::get(); }
  243. T const& get() const { return empty_value<T>::get(); }
  244. };
  245. template <typename T, int Index>
  246. struct generate_base : boost::unordered::detail::compressed_base<T, Index>
  247. {
  248. typedef compressed_base<T, Index> type;
  249. generate_base() : type() {}
  250. };
  251. template <typename T1, typename T2>
  252. struct compressed
  253. : private boost::unordered::detail::generate_base<T1, 1>::type,
  254. private boost::unordered::detail::generate_base<T2, 2>::type
  255. {
  256. typedef typename generate_base<T1, 1>::type base1;
  257. typedef typename generate_base<T2, 2>::type base2;
  258. typedef T1 first_type;
  259. typedef T2 second_type;
  260. first_type& first() { return static_cast<base1*>(this)->get(); }
  261. first_type const& first() const
  262. {
  263. return static_cast<base1 const*>(this)->get();
  264. }
  265. second_type& second() { return static_cast<base2*>(this)->get(); }
  266. second_type const& second() const
  267. {
  268. return static_cast<base2 const*>(this)->get();
  269. }
  270. template <typename First, typename Second>
  271. compressed(First const& x1, Second const& x2) : base1(x1), base2(x2)
  272. {
  273. }
  274. compressed(compressed const& x) : base1(x.first()), base2(x.second()) {}
  275. compressed(compressed& x, move_tag m)
  276. : base1(x.first(), m), base2(x.second(), m)
  277. {
  278. }
  279. void assign(compressed const& x)
  280. {
  281. first() = x.first();
  282. second() = x.second();
  283. }
  284. void move_assign(compressed& x)
  285. {
  286. first() = boost::move(x.first());
  287. second() = boost::move(x.second());
  288. }
  289. void swap(compressed& x)
  290. {
  291. boost::swap(first(), x.first());
  292. boost::swap(second(), x.second());
  293. }
  294. private:
  295. // Prevent assignment just to make use of assign or
  296. // move_assign explicit.
  297. compressed& operator=(compressed const&);
  298. };
  299. //////////////////////////////////////////////////////////////////////////
  300. // pair_traits
  301. //
  302. // Used to get the types from a pair without instantiating it.
  303. template <typename Pair> struct pair_traits
  304. {
  305. typedef typename Pair::first_type first_type;
  306. typedef typename Pair::second_type second_type;
  307. };
  308. template <typename T1, typename T2> struct pair_traits<std::pair<T1, T2> >
  309. {
  310. typedef T1 first_type;
  311. typedef T2 second_type;
  312. };
  313. #if defined(BOOST_MSVC)
  314. #pragma warning(push)
  315. #pragma warning(disable : 4512) // assignment operator could not be generated.
  316. #pragma warning(disable : 4345) // behavior change: an object of POD type
  317. // constructed with an initializer of the form ()
  318. // will be default-initialized.
  319. #endif
  320. //////////////////////////////////////////////////////////////////////////
  321. // Bits and pieces for implementing traits
  322. template <typename T>
  323. typename boost::add_lvalue_reference<T>::type make();
  324. struct choice9
  325. {
  326. typedef char (&type)[9];
  327. };
  328. struct choice8 : choice9
  329. {
  330. typedef char (&type)[8];
  331. };
  332. struct choice7 : choice8
  333. {
  334. typedef char (&type)[7];
  335. };
  336. struct choice6 : choice7
  337. {
  338. typedef char (&type)[6];
  339. };
  340. struct choice5 : choice6
  341. {
  342. typedef char (&type)[5];
  343. };
  344. struct choice4 : choice5
  345. {
  346. typedef char (&type)[4];
  347. };
  348. struct choice3 : choice4
  349. {
  350. typedef char (&type)[3];
  351. };
  352. struct choice2 : choice3
  353. {
  354. typedef char (&type)[2];
  355. };
  356. struct choice1 : choice2
  357. {
  358. typedef char (&type)[1];
  359. };
  360. choice1 choose();
  361. typedef choice1::type yes_type;
  362. typedef choice2::type no_type;
  363. struct private_type
  364. {
  365. private_type const& operator,(int) const;
  366. };
  367. template <typename T> no_type is_private_type(T const&);
  368. yes_type is_private_type(private_type const&);
  369. struct convert_from_anything
  370. {
  371. template <typename T> convert_from_anything(T const&);
  372. };
  373. }
  374. }
  375. }
  376. ////////////////////////////////////////////////////////////////////////////
  377. // emplace_args
  378. //
  379. // Either forwarding variadic arguments, or storing the arguments in
  380. // emplace_args##n
  381. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  382. #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
  383. #define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
  384. #define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
  385. #else
  386. #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
  387. #define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
  388. #define BOOST_UNORDERED_EMPLACE_FORWARD args
  389. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  390. #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
  391. typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
  392. BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
  393. #else
  394. #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
  395. typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
  396. BOOST_PP_CAT(Arg, n); \
  397. BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
  398. #endif
  399. #define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
  400. BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
  401. #define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
  402. boost::forward<BOOST_PP_CAT(A, i)>(BOOST_PP_CAT(a, i))
  403. #define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
  404. BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
  405. #define BOOST_UNORDERED_EARGS(z, n, _) \
  406. template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
  407. struct BOOST_PP_CAT(emplace_args, n) \
  408. { \
  409. BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) BOOST_PP_CAT( \
  410. emplace_args, n)(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b)) \
  411. : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
  412. { \
  413. } \
  414. }; \
  415. \
  416. template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
  417. inline BOOST_PP_CAT(emplace_args, n)<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> \
  418. create_emplace_args(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b)) \
  419. { \
  420. BOOST_PP_CAT(emplace_args, n)<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> e( \
  421. BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
  422. return e; \
  423. }
  424. namespace boost {
  425. namespace unordered {
  426. namespace detail {
  427. template <typename A0> struct emplace_args1
  428. {
  429. BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
  430. explicit emplace_args1(Arg0 b0) : a0(b0) {}
  431. };
  432. template <typename A0>
  433. inline emplace_args1<A0> create_emplace_args(BOOST_FWD_REF(A0) b0)
  434. {
  435. emplace_args1<A0> e(b0);
  436. return e;
  437. }
  438. template <typename A0, typename A1> struct emplace_args2
  439. {
  440. BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
  441. BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
  442. emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {}
  443. };
  444. template <typename A0, typename A1>
  445. inline emplace_args2<A0, A1> create_emplace_args(
  446. BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1)
  447. {
  448. emplace_args2<A0, A1> e(b0, b1);
  449. return e;
  450. }
  451. template <typename A0, typename A1, typename A2> struct emplace_args3
  452. {
  453. BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
  454. BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
  455. BOOST_UNORDERED_EARGS_MEMBER(1, 2, _)
  456. emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {}
  457. };
  458. template <typename A0, typename A1, typename A2>
  459. inline emplace_args3<A0, A1, A2> create_emplace_args(
  460. BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1, BOOST_FWD_REF(A2) b2)
  461. {
  462. emplace_args3<A0, A1, A2> e(b0, b1, b2);
  463. return e;
  464. }
  465. BOOST_UNORDERED_EARGS(1, 4, _)
  466. BOOST_UNORDERED_EARGS(1, 5, _)
  467. BOOST_UNORDERED_EARGS(1, 6, _)
  468. BOOST_UNORDERED_EARGS(1, 7, _)
  469. BOOST_UNORDERED_EARGS(1, 8, _)
  470. BOOST_UNORDERED_EARGS(1, 9, _)
  471. BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
  472. BOOST_UNORDERED_EARGS, _)
  473. }
  474. }
  475. }
  476. #undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
  477. #undef BOOST_UNORDERED_EARGS_MEMBER
  478. #undef BOOST_UNORDERED_EARGS_INIT
  479. #endif
  480. ////////////////////////////////////////////////////////////////////////////////
  481. //
  482. // Some utilities for implementing allocator_traits, but useful elsewhere so
  483. // they're always defined.
  484. namespace boost {
  485. namespace unordered {
  486. namespace detail {
  487. ////////////////////////////////////////////////////////////////////////////
  488. // Integral_constrant, true_type, false_type
  489. //
  490. // Uses the standard versions if available.
  491. #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
  492. using std::integral_constant;
  493. using std::true_type;
  494. using std::false_type;
  495. #else
  496. template <typename T, T Value> struct integral_constant
  497. {
  498. enum
  499. {
  500. value = Value
  501. };
  502. };
  503. typedef boost::unordered::detail::integral_constant<bool, true> true_type;
  504. typedef boost::unordered::detail::integral_constant<bool, false>
  505. false_type;
  506. #endif
  507. ////////////////////////////////////////////////////////////////////////////
  508. // Explicitly call a destructor
  509. #if defined(BOOST_MSVC)
  510. #pragma warning(push)
  511. #pragma warning(disable : 4100) // unreferenced formal parameter
  512. #endif
  513. namespace func {
  514. template <class T> inline void destroy(T* x) { x->~T(); }
  515. }
  516. #if defined(BOOST_MSVC)
  517. #pragma warning(pop)
  518. #endif
  519. //////////////////////////////////////////////////////////////////////////
  520. // value_base
  521. //
  522. // Space used to store values.
  523. template <typename ValueType> struct value_base
  524. {
  525. typedef ValueType value_type;
  526. typename boost::aligned_storage<sizeof(value_type),
  527. boost::alignment_of<value_type>::value>::type data_;
  528. value_base() : data_() {}
  529. void* address() { return this; }
  530. value_type& value() { return *(ValueType*)this; }
  531. value_type const& value() const { return *(ValueType const*)this; }
  532. value_type* value_ptr() { return (ValueType*)this; }
  533. value_type const* value_ptr() const { return (ValueType const*)this; }
  534. private:
  535. value_base& operator=(value_base const&);
  536. };
  537. //////////////////////////////////////////////////////////////////////////
  538. // optional
  539. // TODO: Use std::optional when available.
  540. template <typename T> class optional
  541. {
  542. BOOST_MOVABLE_BUT_NOT_COPYABLE(optional)
  543. boost::unordered::detail::value_base<T> value_;
  544. bool has_value_;
  545. void destroy()
  546. {
  547. if (has_value_) {
  548. boost::unordered::detail::func::destroy(value_.value_ptr());
  549. has_value_ = false;
  550. }
  551. }
  552. void move(optional<T>& x)
  553. {
  554. BOOST_ASSERT(!has_value_ && x.has_value_);
  555. new (value_.value_ptr()) T(boost::move(x.value_.value()));
  556. boost::unordered::detail::func::destroy(x.value_.value_ptr());
  557. has_value_ = true;
  558. x.has_value_ = false;
  559. }
  560. public:
  561. optional() BOOST_NOEXCEPT : has_value_(false) {}
  562. optional(BOOST_RV_REF(optional<T>) x) : has_value_(false)
  563. {
  564. if (x.has_value_) {
  565. move(x);
  566. }
  567. }
  568. explicit optional(T const& x) : has_value_(true)
  569. {
  570. new (value_.value_ptr()) T(x);
  571. }
  572. optional& operator=(BOOST_RV_REF(optional<T>) x)
  573. {
  574. destroy();
  575. if (x.has_value_) {
  576. move(x);
  577. }
  578. return *this;
  579. }
  580. ~optional() { destroy(); }
  581. bool has_value() const { return has_value_; }
  582. T& operator*() { return value_.value(); }
  583. T const& operator*() const { return value_.value(); }
  584. T* operator->() { return value_.value_ptr(); }
  585. T const* operator->() const { return value_.value_ptr(); }
  586. bool operator==(optional<T> const& x) const
  587. {
  588. return has_value_ ? x.has_value_ && value_.value() == x.value_.value()
  589. : !x.has_value_;
  590. }
  591. bool operator!=(optional<T> const& x) const { return !((*this) == x); }
  592. void swap(optional<T>& x)
  593. {
  594. if (has_value_ != x.has_value_) {
  595. if (has_value_) {
  596. x.move(*this);
  597. } else {
  598. move(x);
  599. }
  600. } else if (has_value_) {
  601. boost::swap(value_.value(), x.value_.value());
  602. }
  603. }
  604. friend void swap(optional<T>& x, optional<T>& y) { x.swap(y); }
  605. };
  606. }
  607. }
  608. }
  609. ////////////////////////////////////////////////////////////////////////////////
  610. //
  611. // Allocator traits
  612. //
  613. namespace boost {
  614. namespace unordered {
  615. namespace detail {
  616. template <typename Alloc>
  617. struct allocator_traits : boost::allocator_traits<Alloc>
  618. {
  619. };
  620. template <typename Alloc, typename T>
  621. struct rebind_wrap : boost::allocator_rebind<Alloc, T>
  622. {
  623. };
  624. }
  625. }
  626. }
  627. ////////////////////////////////////////////////////////////////////////////
  628. // Functions used to construct nodes. Emulates variadic construction,
  629. // piecewise construction etc.
  630. ////////////////////////////////////////////////////////////////////////////
  631. // construct_value
  632. //
  633. // Only use allocator_traits::construct, allocator_traits::destroy when full
  634. // C++11 support is available.
  635. #if BOOST_UNORDERED_CXX11_CONSTRUCTION
  636. #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  637. namespace boost {
  638. namespace unordered {
  639. namespace detail {
  640. namespace func {
  641. template <typename T, typename... Args>
  642. inline void construct_value(T* address, BOOST_FWD_REF(Args)... args)
  643. {
  644. new ((void*)address) T(boost::forward<Args>(args)...);
  645. }
  646. }
  647. }
  648. }
  649. }
  650. #else
  651. namespace boost {
  652. namespace unordered {
  653. namespace detail {
  654. namespace func {
  655. template <typename T> inline void construct_value(T* address)
  656. {
  657. new ((void*)address) T();
  658. }
  659. template <typename T, typename A0>
  660. inline void construct_value(T* address, BOOST_FWD_REF(A0) a0)
  661. {
  662. new ((void*)address) T(boost::forward<A0>(a0));
  663. }
  664. }
  665. }
  666. }
  667. }
  668. #endif
  669. ////////////////////////////////////////////////////////////////////////////
  670. // Construct from tuple
  671. //
  672. // Used to emulate piecewise construction.
  673. #define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(z, n, namespace_) \
  674. template <typename Alloc, typename T, \
  675. BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
  676. void construct_from_tuple(Alloc&, T* ptr, \
  677. namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
  678. { \
  679. new ((void*)ptr) \
  680. T(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_)); \
  681. }
  682. #define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_::get<n>(x)
  683. // construct_from_tuple for boost::tuple
  684. // The workaround for old Sun compilers comes later in the file.
  685. #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
  686. namespace boost {
  687. namespace unordered {
  688. namespace detail {
  689. namespace func {
  690. template <typename Alloc, typename T>
  691. void construct_from_tuple(Alloc&, T* ptr, boost::tuple<>)
  692. {
  693. new ((void*)ptr) T();
  694. }
  695. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, boost)
  696. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, boost)
  697. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, boost)
  698. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, boost)
  699. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, boost)
  700. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 6, boost)
  701. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 7, boost)
  702. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 8, boost)
  703. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 9, boost)
  704. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 10, boost)
  705. }
  706. }
  707. }
  708. }
  709. #endif
  710. // construct_from_tuple for std::tuple
  711. #if !BOOST_UNORDERED_CXX11_CONSTRUCTION && BOOST_UNORDERED_TUPLE_ARGS
  712. namespace boost {
  713. namespace unordered {
  714. namespace detail {
  715. namespace func {
  716. template <typename Alloc, typename T>
  717. void construct_from_tuple(Alloc&, T* ptr, std::tuple<>)
  718. {
  719. new ((void*)ptr) T();
  720. }
  721. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, std)
  722. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, std)
  723. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, std)
  724. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, std)
  725. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, std)
  726. #if BOOST_UNORDERED_TUPLE_ARGS >= 6
  727. BOOST_PP_REPEAT_FROM_TO(6, BOOST_PP_INC(BOOST_UNORDERED_TUPLE_ARGS),
  728. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE, std)
  729. #endif
  730. }
  731. }
  732. }
  733. }
  734. #endif
  735. #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
  736. #undef BOOST_UNORDERED_GET_TUPLE_ARG
  737. // construct_from_tuple for boost::tuple on old versions of sunpro.
  738. //
  739. // Old versions of Sun C++ had problems with template overloads of
  740. // boost::tuple, so to fix it I added a distinct type for each length to
  741. // the overloads. That means there's no possible ambiguity between the
  742. // different overloads, so that the compiler doesn't get confused
  743. #if BOOST_UNORDERED_SUN_WORKAROUNDS1
  744. #define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(z, n, namespace_) \
  745. template <typename Alloc, typename T, \
  746. BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
  747. void construct_from_tuple_impl(boost::unordered::detail::func::length<n>, \
  748. Alloc&, T* ptr, \
  749. namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
  750. { \
  751. new ((void*)ptr) \
  752. T(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_)); \
  753. }
  754. #define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_::get<n>(x)
  755. namespace boost {
  756. namespace unordered {
  757. namespace detail {
  758. namespace func {
  759. template <int N> struct length
  760. {
  761. };
  762. template <typename Alloc, typename T>
  763. void construct_from_tuple_impl(
  764. boost::unordered::detail::func::length<0>, Alloc&, T* ptr,
  765. boost::tuple<>)
  766. {
  767. new ((void*)ptr) T();
  768. }
  769. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, boost)
  770. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, boost)
  771. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, boost)
  772. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, boost)
  773. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, boost)
  774. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 6, boost)
  775. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 7, boost)
  776. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 8, boost)
  777. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 9, boost)
  778. BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 10, boost)
  779. template <typename Alloc, typename T, typename Tuple>
  780. void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
  781. {
  782. construct_from_tuple_impl(boost::unordered::detail::func::length<
  783. boost::tuples::length<Tuple>::value>(),
  784. alloc, ptr, x);
  785. }
  786. }
  787. }
  788. }
  789. }
  790. #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
  791. #undef BOOST_UNORDERED_GET_TUPLE_ARG
  792. #endif
  793. namespace boost {
  794. namespace unordered {
  795. namespace detail {
  796. namespace func {
  797. ////////////////////////////////////////////////////////////////////////
  798. // Trait to check for piecewise construction.
  799. template <typename A0> struct use_piecewise
  800. {
  801. static choice1::type test(
  802. choice1, boost::unordered::piecewise_construct_t);
  803. static choice2::type test(choice2, ...);
  804. enum
  805. {
  806. value = sizeof(choice1::type) ==
  807. sizeof(test(choose(), boost::unordered::detail::make<A0>()))
  808. };
  809. };
  810. #if BOOST_UNORDERED_CXX11_CONSTRUCTION
  811. ////////////////////////////////////////////////////////////////////////
  812. // Construct from variadic parameters
  813. template <typename Alloc, typename T, typename... Args>
  814. inline void construct_from_args(
  815. Alloc& alloc, T* address, BOOST_FWD_REF(Args)... args)
  816. {
  817. boost::allocator_construct(
  818. alloc, address, boost::forward<Args>(args)...);
  819. }
  820. // For backwards compatibility, implement a special case for
  821. // piecewise_construct with boost::tuple
  822. template <typename A0> struct detect_boost_tuple
  823. {
  824. template <typename T0, typename T1, typename T2, typename T3,
  825. typename T4, typename T5, typename T6, typename T7, typename T8,
  826. typename T9>
  827. static choice1::type test(choice1,
  828. boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> const&);
  829. static choice2::type test(choice2, ...);
  830. enum
  831. {
  832. value = sizeof(choice1::type) ==
  833. sizeof(test(choose(), boost::unordered::detail::make<A0>()))
  834. };
  835. };
  836. // Special case for piecewise_construct
  837. template <class... Args, std::size_t... Is, class... TupleArgs>
  838. std::tuple<typename std::add_lvalue_reference<Args>::type...>
  839. to_std_tuple_impl(boost::mp11::mp_list<Args...>,
  840. boost::tuple<TupleArgs...>& tuple, boost::mp11::index_sequence<Is...>)
  841. {
  842. (void) tuple;
  843. return std::tuple<typename std::add_lvalue_reference<Args>::type...>(
  844. boost::get<Is>(tuple)...);
  845. }
  846. template <class T>
  847. using add_lvalue_reference_t =
  848. typename std::add_lvalue_reference<T>::type;
  849. template <class... Args>
  850. boost::mp11::mp_transform<add_lvalue_reference_t,
  851. boost::mp11::mp_remove<std::tuple<Args...>,
  852. boost::tuples::null_type> >
  853. to_std_tuple(boost::tuple<Args...>& tuple)
  854. {
  855. using list = boost::mp11::mp_remove<boost::mp11::mp_list<Args...>,
  856. boost::tuples::null_type>;
  857. using list_size = boost::mp11::mp_size<list>;
  858. using index_seq = boost::mp11::make_index_sequence<list_size::value>;
  859. return to_std_tuple_impl(list{}, tuple, index_seq{});
  860. }
  861. template <typename Alloc, typename A, typename B, typename A0,
  862. typename A1, typename A2>
  863. inline typename boost::enable_if_c<use_piecewise<A0>::value &&
  864. detect_boost_tuple<A1>::value &&
  865. detect_boost_tuple<A2>::value,
  866. void>::type
  867. construct_from_args(Alloc& alloc, std::pair<A, B>* address,
  868. BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
  869. {
  870. boost::allocator_construct(alloc, address, std::piecewise_construct,
  871. to_std_tuple(a1), to_std_tuple(a2));
  872. }
  873. #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  874. ////////////////////////////////////////////////////////////////////////
  875. // Construct from variadic parameters
  876. template <typename Alloc, typename T, typename... Args>
  877. inline void construct_from_args(
  878. Alloc&, T* address, BOOST_FWD_REF(Args)... args)
  879. {
  880. new ((void*)address) T(boost::forward<Args>(args)...);
  881. }
  882. // Special case for piecewise_construct
  883. template <typename Alloc, typename A, typename B, typename A0,
  884. typename A1, typename A2>
  885. inline typename enable_if<use_piecewise<A0>, void>::type
  886. construct_from_args(Alloc& alloc, std::pair<A, B>* address,
  887. BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
  888. {
  889. boost::unordered::detail::func::construct_from_tuple(
  890. alloc, boost::addressof(address->first), boost::forward<A1>(a1));
  891. BOOST_TRY
  892. {
  893. boost::unordered::detail::func::construct_from_tuple(
  894. alloc, boost::addressof(address->second), boost::forward<A2>(a2));
  895. }
  896. BOOST_CATCH(...)
  897. {
  898. boost::unordered::detail::func::destroy(
  899. boost::addressof(address->first));
  900. BOOST_RETHROW
  901. }
  902. BOOST_CATCH_END
  903. }
  904. #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
  905. ////////////////////////////////////////////////////////////////////////
  906. // Construct from emplace_args
  907. // Explicitly write out first three overloads for the sake of sane
  908. // error messages.
  909. template <typename Alloc, typename T, typename A0>
  910. inline void construct_from_args(
  911. Alloc&, T* address, emplace_args1<A0> const& args)
  912. {
  913. new ((void*)address) T(boost::forward<A0>(args.a0));
  914. }
  915. template <typename Alloc, typename T, typename A0, typename A1>
  916. inline void construct_from_args(
  917. Alloc&, T* address, emplace_args2<A0, A1> const& args)
  918. {
  919. new ((void*)address)
  920. T(boost::forward<A0>(args.a0), boost::forward<A1>(args.a1));
  921. }
  922. template <typename Alloc, typename T, typename A0, typename A1,
  923. typename A2>
  924. inline void construct_from_args(
  925. Alloc&, T* address, emplace_args3<A0, A1, A2> const& args)
  926. {
  927. new ((void*)address) T(boost::forward<A0>(args.a0),
  928. boost::forward<A1>(args.a1), boost::forward<A2>(args.a2));
  929. }
  930. // Use a macro for the rest.
  931. #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
  932. template <typename Alloc, typename T, \
  933. BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)> \
  934. inline void construct_from_args(Alloc&, T* address, \
  935. boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
  936. BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) > const& args) \
  937. { \
  938. new ((void*)address) \
  939. T(BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, args.a)); \
  940. }
  941. BOOST_UNORDERED_CONSTRUCT_IMPL(1, 4, _)
  942. BOOST_UNORDERED_CONSTRUCT_IMPL(1, 5, _)
  943. BOOST_UNORDERED_CONSTRUCT_IMPL(1, 6, _)
  944. BOOST_UNORDERED_CONSTRUCT_IMPL(1, 7, _)
  945. BOOST_UNORDERED_CONSTRUCT_IMPL(1, 8, _)
  946. BOOST_UNORDERED_CONSTRUCT_IMPL(1, 9, _)
  947. BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
  948. BOOST_UNORDERED_CONSTRUCT_IMPL, _)
  949. #undef BOOST_UNORDERED_CONSTRUCT_IMPL
  950. // Construct with piecewise_construct
  951. template <typename Alloc, typename A, typename B, typename A0,
  952. typename A1, typename A2>
  953. inline typename enable_if<use_piecewise<A0>, void>::type
  954. construct_from_args(Alloc& alloc, std::pair<A, B>* address,
  955. boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
  956. {
  957. boost::unordered::detail::func::construct_from_tuple(
  958. alloc, boost::addressof(address->first), args.a1);
  959. BOOST_TRY
  960. {
  961. boost::unordered::detail::func::construct_from_tuple(
  962. alloc, boost::addressof(address->second), args.a2);
  963. }
  964. BOOST_CATCH(...)
  965. {
  966. boost::unordered::detail::func::destroy(
  967. boost::addressof(address->first));
  968. BOOST_RETHROW
  969. }
  970. BOOST_CATCH_END
  971. }
  972. #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
  973. }
  974. }
  975. }
  976. }
  977. namespace boost {
  978. namespace unordered {
  979. namespace detail {
  980. ///////////////////////////////////////////////////////////////////
  981. //
  982. // Node construction
  983. template <typename NodeAlloc> struct node_constructor
  984. {
  985. typedef NodeAlloc node_allocator;
  986. typedef boost::unordered::detail::allocator_traits<NodeAlloc>
  987. node_allocator_traits;
  988. typedef typename node_allocator_traits::value_type node;
  989. typedef typename node_allocator_traits::pointer node_pointer;
  990. typedef typename node::value_type value_type;
  991. node_allocator& alloc_;
  992. node_pointer node_;
  993. node_constructor(node_allocator& n) : alloc_(n), node_() {}
  994. ~node_constructor();
  995. void create_node();
  996. // no throw
  997. node_pointer release()
  998. {
  999. BOOST_ASSERT(node_);
  1000. node_pointer p = node_;
  1001. node_ = node_pointer();
  1002. return p;
  1003. }
  1004. private:
  1005. node_constructor(node_constructor const&);
  1006. node_constructor& operator=(node_constructor const&);
  1007. };
  1008. template <typename Alloc> node_constructor<Alloc>::~node_constructor()
  1009. {
  1010. if (node_) {
  1011. boost::unordered::detail::func::destroy(boost::to_address(node_));
  1012. node_allocator_traits::deallocate(alloc_, node_, 1);
  1013. }
  1014. }
  1015. template <typename Alloc> void node_constructor<Alloc>::create_node()
  1016. {
  1017. BOOST_ASSERT(!node_);
  1018. node_ = node_allocator_traits::allocate(alloc_, 1);
  1019. new ((void*)boost::to_address(node_)) node();
  1020. }
  1021. template <typename NodeAlloc> struct node_tmp
  1022. {
  1023. typedef typename boost::allocator_value_type<NodeAlloc>::type node;
  1024. typedef typename boost::allocator_pointer<NodeAlloc>::type node_pointer;
  1025. typedef typename node::value_type value_type;
  1026. typedef typename boost::allocator_rebind<NodeAlloc, value_type>::type
  1027. value_allocator;
  1028. NodeAlloc& alloc_;
  1029. node_pointer node_;
  1030. explicit node_tmp(node_pointer n, NodeAlloc& a) : alloc_(a), node_(n) {}
  1031. ~node_tmp();
  1032. // no throw
  1033. node_pointer release()
  1034. {
  1035. node_pointer p = node_;
  1036. node_ = node_pointer();
  1037. return p;
  1038. }
  1039. };
  1040. template <typename Alloc> node_tmp<Alloc>::~node_tmp()
  1041. {
  1042. if (node_) {
  1043. value_allocator val_alloc(alloc_);
  1044. boost::allocator_destroy(val_alloc, node_->value_ptr());
  1045. boost::allocator_deallocate(alloc_, node_, 1);
  1046. }
  1047. }
  1048. }
  1049. }
  1050. }
  1051. namespace boost {
  1052. namespace unordered {
  1053. namespace detail {
  1054. namespace func {
  1055. // Some nicer construct_node functions, might try to
  1056. // improve implementation later.
  1057. template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
  1058. inline typename boost::allocator_pointer<Alloc>::type
  1059. construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
  1060. {
  1061. typedef typename boost::allocator_value_type<Alloc>::type node;
  1062. typedef typename node::value_type value_type;
  1063. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  1064. value_allocator;
  1065. value_allocator val_alloc(alloc);
  1066. node_constructor<Alloc> a(alloc);
  1067. a.create_node();
  1068. construct_from_args(
  1069. val_alloc, a.node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
  1070. return a.release();
  1071. }
  1072. template <typename Alloc, typename U>
  1073. inline typename boost::allocator_pointer<Alloc>::type construct_node(
  1074. Alloc& alloc, BOOST_FWD_REF(U) x)
  1075. {
  1076. node_constructor<Alloc> a(alloc);
  1077. a.create_node();
  1078. typedef typename boost::allocator_value_type<Alloc>::type node;
  1079. typedef typename node::value_type value_type;
  1080. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  1081. value_allocator;
  1082. value_allocator val_alloc(alloc);
  1083. boost::allocator_construct(
  1084. val_alloc, a.node_->value_ptr(), boost::forward<U>(x));
  1085. return a.release();
  1086. }
  1087. #if BOOST_UNORDERED_CXX11_CONSTRUCTION
  1088. template <typename Alloc, typename Key>
  1089. inline typename boost::allocator_pointer<Alloc>::type
  1090. construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
  1091. {
  1092. node_constructor<Alloc> a(alloc);
  1093. a.create_node();
  1094. typedef typename boost::allocator_value_type<Alloc>::type node;
  1095. typedef typename node::value_type value_type;
  1096. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  1097. value_allocator;
  1098. value_allocator val_alloc(alloc);
  1099. boost::allocator_construct(
  1100. val_alloc, a.node_->value_ptr(), std::piecewise_construct,
  1101. std::forward_as_tuple(boost::forward<Key>(k)),
  1102. std::forward_as_tuple());
  1103. return a.release();
  1104. }
  1105. template <typename Alloc, typename Key, typename Mapped>
  1106. inline typename boost::allocator_pointer<Alloc>::type
  1107. construct_node_pair(
  1108. Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
  1109. {
  1110. node_constructor<Alloc> a(alloc);
  1111. a.create_node();
  1112. typedef typename boost::allocator_value_type<Alloc>::type node;
  1113. typedef typename node::value_type value_type;
  1114. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  1115. value_allocator;
  1116. value_allocator val_alloc(alloc);
  1117. boost::allocator_construct(val_alloc, a.node_->value_ptr(),
  1118. std::piecewise_construct,
  1119. std::forward_as_tuple(boost::forward<Key>(k)),
  1120. std::forward_as_tuple(boost::forward<Mapped>(m)));
  1121. return a.release();
  1122. }
  1123. template <typename Alloc, typename Key, typename... Args>
  1124. inline typename boost::allocator_pointer<Alloc>::type
  1125. construct_node_pair_from_args(
  1126. Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Args)... args)
  1127. {
  1128. node_constructor<Alloc> a(alloc);
  1129. a.create_node();
  1130. typedef typename boost::allocator_value_type<Alloc>::type node;
  1131. typedef typename node::value_type value_type;
  1132. typedef typename boost::allocator_rebind<Alloc, value_type>::type
  1133. value_allocator;
  1134. value_allocator val_alloc(alloc);
  1135. #if !(BOOST_COMP_CLANG && BOOST_COMP_CLANG < BOOST_VERSION_NUMBER(3, 8, 0) && \
  1136. defined(BOOST_LIBSTDCXX11))
  1137. boost::allocator_construct(val_alloc, a.node_->value_ptr(),
  1138. std::piecewise_construct,
  1139. std::forward_as_tuple(boost::forward<Key>(k)),
  1140. std::forward_as_tuple(boost::forward<Args>(args)...));
  1141. #else
  1142. // It doesn't seem to be possible to construct a tuple with 3 variadic
  1143. // rvalue reference members when using older versions of clang with
  1144. // libstdc++, so just use std::make_tuple instead of
  1145. // std::forward_as_tuple.
  1146. boost::allocator_construct(val_alloc, a.node_->value_ptr(),
  1147. std::piecewise_construct,
  1148. std::forward_as_tuple(boost::forward<Key>(k)),
  1149. std::make_tuple(boost::forward<Args>(args)...));
  1150. #endif
  1151. return a.release();
  1152. }
  1153. #else
  1154. template <typename Alloc, typename Key>
  1155. inline
  1156. typename boost::unordered::detail::allocator_traits<Alloc>::pointer
  1157. construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
  1158. {
  1159. node_constructor<Alloc> a(alloc);
  1160. a.create_node();
  1161. boost::unordered::detail::func::construct_value(
  1162. boost::addressof(a.node_->value_ptr()->first),
  1163. boost::forward<Key>(k));
  1164. BOOST_TRY
  1165. {
  1166. boost::unordered::detail::func::construct_value(
  1167. boost::addressof(a.node_->value_ptr()->second));
  1168. }
  1169. BOOST_CATCH(...)
  1170. {
  1171. boost::unordered::detail::func::destroy(
  1172. boost::addressof(a.node_->value_ptr()->first));
  1173. BOOST_RETHROW
  1174. }
  1175. BOOST_CATCH_END
  1176. return a.release();
  1177. }
  1178. template <typename Alloc, typename Key, typename Mapped>
  1179. inline
  1180. typename boost::unordered::detail::allocator_traits<Alloc>::pointer
  1181. construct_node_pair(
  1182. Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
  1183. {
  1184. node_constructor<Alloc> a(alloc);
  1185. a.create_node();
  1186. boost::unordered::detail::func::construct_value(
  1187. boost::addressof(a.node_->value_ptr()->first),
  1188. boost::forward<Key>(k));
  1189. BOOST_TRY
  1190. {
  1191. boost::unordered::detail::func::construct_value(
  1192. boost::addressof(a.node_->value_ptr()->second),
  1193. boost::forward<Mapped>(m));
  1194. }
  1195. BOOST_CATCH(...)
  1196. {
  1197. boost::unordered::detail::func::destroy(
  1198. boost::addressof(a.node_->value_ptr()->first));
  1199. BOOST_RETHROW
  1200. }
  1201. BOOST_CATCH_END
  1202. return a.release();
  1203. }
  1204. template <typename Alloc, typename Key,
  1205. BOOST_UNORDERED_EMPLACE_TEMPLATE>
  1206. inline
  1207. typename boost::unordered::detail::allocator_traits<Alloc>::pointer
  1208. construct_node_pair_from_args(
  1209. Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
  1210. {
  1211. node_constructor<Alloc> a(alloc);
  1212. a.create_node();
  1213. boost::unordered::detail::func::construct_value(
  1214. boost::addressof(a.node_->value_ptr()->first),
  1215. boost::forward<Key>(k));
  1216. BOOST_TRY
  1217. {
  1218. boost::unordered::detail::func::construct_from_args(alloc,
  1219. boost::addressof(a.node_->value_ptr()->second),
  1220. BOOST_UNORDERED_EMPLACE_FORWARD);
  1221. }
  1222. BOOST_CATCH(...)
  1223. {
  1224. boost::unordered::detail::func::destroy(
  1225. boost::addressof(a.node_->value_ptr()->first));
  1226. BOOST_RETHROW
  1227. }
  1228. BOOST_CATCH_END
  1229. return a.release();
  1230. }
  1231. #endif
  1232. template <typename T, typename Alloc, typename Key>
  1233. inline typename boost::allocator_pointer<Alloc>::type
  1234. construct_node_from_key(T*, Alloc& alloc, BOOST_FWD_REF(Key) k)
  1235. {
  1236. return construct_node(alloc, boost::forward<Key>(k));
  1237. }
  1238. template <typename T, typename V, typename Alloc, typename Key>
  1239. inline typename boost::allocator_pointer<Alloc>::type
  1240. construct_node_from_key(
  1241. std::pair<T const, V>*, Alloc& alloc, BOOST_FWD_REF(Key) k)
  1242. {
  1243. return construct_node_pair(alloc, boost::forward<Key>(k));
  1244. }
  1245. } // namespace func
  1246. }
  1247. }
  1248. }
  1249. #if defined(BOOST_MSVC)
  1250. #pragma warning(pop)
  1251. #endif
  1252. namespace boost {
  1253. namespace unordered {
  1254. namespace detail {
  1255. //////////////////////////////////////////////////////////////////////////
  1256. // Functions
  1257. //
  1258. // This double buffers the storage for the hash function and key equality
  1259. // predicate in order to have exception safe copy/swap. To do so,
  1260. // use 'construct_spare' to construct in the spare space, and then when
  1261. // ready to use 'switch_functions' to switch to the new functions.
  1262. // If an exception is thrown between these two calls, use
  1263. // 'cleanup_spare_functions' to destroy the unused constructed functions.
  1264. #if defined(_GLIBCXX_HAVE_BUILTIN_LAUNDER)
  1265. // gcc-12 warns when accessing the `current_functions` of our `functions`
  1266. // class below with `-Wmaybe-unitialized`. By laundering the pointer, we
  1267. // silence the warning and assure the compiler that a valid object exists
  1268. // in that region of storage. This warning is also generated in C++03
  1269. // which does not have `std::launder`. The compiler builtin is always
  1270. // available, regardless of the C++ standard used when compiling.
  1271. template <class T> T* launder(T* p) BOOST_NOEXCEPT
  1272. {
  1273. return __builtin_launder(p);
  1274. }
  1275. #else
  1276. template <class T> T* launder(T* p) BOOST_NOEXCEPT { return p; }
  1277. #endif
  1278. template <class H, class P> class functions
  1279. {
  1280. public:
  1281. static const bool nothrow_move_assignable =
  1282. boost::is_nothrow_move_assignable<H>::value &&
  1283. boost::is_nothrow_move_assignable<P>::value;
  1284. static const bool nothrow_move_constructible =
  1285. boost::is_nothrow_move_constructible<H>::value &&
  1286. boost::is_nothrow_move_constructible<P>::value;
  1287. static const bool nothrow_swappable =
  1288. boost::is_nothrow_swappable<H>::value &&
  1289. boost::is_nothrow_swappable<P>::value;
  1290. private:
  1291. functions& operator=(functions const&);
  1292. typedef compressed<H, P> function_pair;
  1293. typedef typename boost::aligned_storage<sizeof(function_pair),
  1294. boost::alignment_of<function_pair>::value>::type aligned_function;
  1295. unsigned char current_; // 0/1 - Currently active functions
  1296. // +2 - Both constructed
  1297. aligned_function funcs_[2];
  1298. public:
  1299. functions(H const& hf, P const& eq) : current_(0)
  1300. {
  1301. construct_functions(current_, hf, eq);
  1302. }
  1303. functions(functions const& bf) : current_(0)
  1304. {
  1305. construct_functions(current_, bf.current_functions());
  1306. }
  1307. functions(functions& bf, boost::unordered::detail::move_tag)
  1308. : current_(0)
  1309. {
  1310. construct_functions(current_, bf.current_functions(),
  1311. boost::unordered::detail::integral_constant<bool,
  1312. nothrow_move_constructible>());
  1313. }
  1314. ~functions()
  1315. {
  1316. BOOST_ASSERT(!(current_ & 2));
  1317. destroy_functions(current_);
  1318. }
  1319. H const& hash_function() const { return current_functions().first(); }
  1320. P const& key_eq() const { return current_functions().second(); }
  1321. function_pair const& current_functions() const
  1322. {
  1323. return *::boost::unordered::detail::launder(
  1324. static_cast<function_pair const*>(
  1325. static_cast<void const*>(funcs_[current_ & 1].address())));
  1326. }
  1327. function_pair& current_functions()
  1328. {
  1329. return *::boost::unordered::detail::launder(
  1330. static_cast<function_pair*>(
  1331. static_cast<void*>(funcs_[current_ & 1].address())));
  1332. }
  1333. void construct_spare_functions(function_pair const& f)
  1334. {
  1335. BOOST_ASSERT(!(current_ & 2));
  1336. construct_functions(current_ ^ 1, f);
  1337. current_ |= 2;
  1338. }
  1339. void cleanup_spare_functions()
  1340. {
  1341. if (current_ & 2) {
  1342. current_ = static_cast<unsigned char>(current_ & 1);
  1343. destroy_functions(current_ ^ 1);
  1344. }
  1345. }
  1346. void switch_functions()
  1347. {
  1348. BOOST_ASSERT(current_ & 2);
  1349. destroy_functions(static_cast<unsigned char>(current_ & 1));
  1350. current_ ^= 3;
  1351. }
  1352. private:
  1353. void construct_functions(unsigned char which, H const& hf, P const& eq)
  1354. {
  1355. BOOST_ASSERT(!(which & 2));
  1356. new ((void*)&funcs_[which]) function_pair(hf, eq);
  1357. }
  1358. void construct_functions(unsigned char which, function_pair const& f,
  1359. boost::unordered::detail::false_type =
  1360. boost::unordered::detail::false_type())
  1361. {
  1362. BOOST_ASSERT(!(which & 2));
  1363. new ((void*)&funcs_[which]) function_pair(f);
  1364. }
  1365. void construct_functions(unsigned char which, function_pair& f,
  1366. boost::unordered::detail::true_type)
  1367. {
  1368. BOOST_ASSERT(!(which & 2));
  1369. new ((void*)&funcs_[which])
  1370. function_pair(f, boost::unordered::detail::move_tag());
  1371. }
  1372. void destroy_functions(unsigned char which)
  1373. {
  1374. BOOST_ASSERT(!(which & 2));
  1375. boost::unordered::detail::func::destroy(
  1376. (function_pair*)(&funcs_[which]));
  1377. }
  1378. };
  1379. ////////////////////////////////////////////////////////////////////////////
  1380. // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
  1381. // e.g. for int
  1382. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  1383. #define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
  1384. #else
  1385. struct please_ignore_this_overload
  1386. {
  1387. typedef please_ignore_this_overload type;
  1388. };
  1389. template <typename T> struct rv_ref_impl
  1390. {
  1391. typedef BOOST_RV_REF(T) type;
  1392. };
  1393. template <typename T>
  1394. struct rv_ref : boost::conditional<boost::is_class<T>::value,
  1395. boost::unordered::detail::rv_ref_impl<T>,
  1396. please_ignore_this_overload>::type
  1397. {
  1398. };
  1399. #define BOOST_UNORDERED_RV_REF(T) \
  1400. typename boost::unordered::detail::rv_ref<T>::type
  1401. #endif
  1402. #if defined(BOOST_MSVC)
  1403. #pragma warning(push)
  1404. #pragma warning(disable : 4127) // conditional expression is constant
  1405. #endif
  1406. //////////////////////////////////////////////////////////////////////////
  1407. // convert double to std::size_t
  1408. inline std::size_t double_to_size(double f)
  1409. {
  1410. return f >= static_cast<double>(
  1411. (std::numeric_limits<std::size_t>::max)())
  1412. ? (std::numeric_limits<std::size_t>::max)()
  1413. : static_cast<std::size_t>(f);
  1414. }
  1415. //////////////////////////////////////////////////////////////////////////
  1416. // iterator definitions
  1417. namespace iterator_detail {
  1418. template <class Node, class Bucket> class c_iterator;
  1419. template <class Node, class Bucket> class iterator
  1420. {
  1421. public:
  1422. typedef typename Node::value_type value_type;
  1423. typedef value_type element_type;
  1424. typedef value_type* pointer;
  1425. typedef value_type& reference;
  1426. typedef std::ptrdiff_t difference_type;
  1427. typedef std::forward_iterator_tag iterator_category;
  1428. iterator() : p(), itb(){};
  1429. reference operator*() const BOOST_NOEXCEPT { return dereference(); }
  1430. pointer operator->() const BOOST_NOEXCEPT
  1431. {
  1432. pointer x = boost::addressof(p->value());
  1433. return x;
  1434. }
  1435. iterator& operator++() BOOST_NOEXCEPT
  1436. {
  1437. increment();
  1438. return *this;
  1439. }
  1440. iterator operator++(int) BOOST_NOEXCEPT
  1441. {
  1442. iterator old = *this;
  1443. increment();
  1444. return old;
  1445. }
  1446. bool operator==(iterator const& other) const BOOST_NOEXCEPT
  1447. {
  1448. return equal(other);
  1449. }
  1450. bool operator!=(iterator const& other) const BOOST_NOEXCEPT
  1451. {
  1452. return !equal(other);
  1453. }
  1454. bool operator==(
  1455. boost::unordered::detail::iterator_detail::c_iterator<Node,
  1456. Bucket> const& other) const BOOST_NOEXCEPT
  1457. {
  1458. return equal(other);
  1459. }
  1460. bool operator!=(
  1461. boost::unordered::detail::iterator_detail::c_iterator<Node,
  1462. Bucket> const& other) const BOOST_NOEXCEPT
  1463. {
  1464. return !equal(other);
  1465. }
  1466. private:
  1467. typedef typename Node::node_pointer node_pointer;
  1468. typedef grouped_bucket_iterator<Bucket> bucket_iterator;
  1469. node_pointer p;
  1470. bucket_iterator itb;
  1471. template <class Types> friend struct boost::unordered::detail::table;
  1472. template <class N, class B> friend class c_iterator;
  1473. iterator(node_pointer p_, bucket_iterator itb_) : p(p_), itb(itb_) {}
  1474. value_type& dereference() const BOOST_NOEXCEPT { return p->value(); }
  1475. bool equal(const iterator& x) const BOOST_NOEXCEPT
  1476. {
  1477. return (p == x.p);
  1478. }
  1479. bool equal(
  1480. const boost::unordered::detail::iterator_detail::c_iterator<Node,
  1481. Bucket>& x) const BOOST_NOEXCEPT
  1482. {
  1483. return (p == x.p);
  1484. }
  1485. void increment() BOOST_NOEXCEPT
  1486. {
  1487. p = p->next;
  1488. if (!p) {
  1489. p = (++itb)->next;
  1490. }
  1491. }
  1492. };
  1493. template <class Node, class Bucket> class c_iterator
  1494. {
  1495. public:
  1496. typedef typename Node::value_type value_type;
  1497. typedef value_type const element_type;
  1498. typedef value_type const* pointer;
  1499. typedef value_type const& reference;
  1500. typedef std::ptrdiff_t difference_type;
  1501. typedef std::forward_iterator_tag iterator_category;
  1502. c_iterator() : p(), itb(){};
  1503. c_iterator(iterator<Node, Bucket> it) : p(it.p), itb(it.itb) {}
  1504. reference operator*() const BOOST_NOEXCEPT { return dereference(); }
  1505. pointer operator->() const BOOST_NOEXCEPT
  1506. {
  1507. pointer x = boost::addressof(p->value());
  1508. return x;
  1509. }
  1510. c_iterator& operator++() BOOST_NOEXCEPT
  1511. {
  1512. increment();
  1513. return *this;
  1514. }
  1515. c_iterator operator++(int) BOOST_NOEXCEPT
  1516. {
  1517. c_iterator old = *this;
  1518. increment();
  1519. return old;
  1520. }
  1521. bool operator==(c_iterator const& other) const BOOST_NOEXCEPT
  1522. {
  1523. return equal(other);
  1524. }
  1525. bool operator!=(c_iterator const& other) const BOOST_NOEXCEPT
  1526. {
  1527. return !equal(other);
  1528. }
  1529. bool operator==(
  1530. boost::unordered::detail::iterator_detail::iterator<Node,
  1531. Bucket> const& other) const BOOST_NOEXCEPT
  1532. {
  1533. return equal(other);
  1534. }
  1535. bool operator!=(
  1536. boost::unordered::detail::iterator_detail::iterator<Node,
  1537. Bucket> const& other) const BOOST_NOEXCEPT
  1538. {
  1539. return !equal(other);
  1540. }
  1541. private:
  1542. typedef typename Node::node_pointer node_pointer;
  1543. typedef grouped_bucket_iterator<Bucket> bucket_iterator;
  1544. node_pointer p;
  1545. bucket_iterator itb;
  1546. template <class Types> friend struct boost::unordered::detail::table;
  1547. template <class, class> friend class iterator;
  1548. c_iterator(node_pointer p_, bucket_iterator itb_) : p(p_), itb(itb_)
  1549. {
  1550. }
  1551. value_type const& dereference() const BOOST_NOEXCEPT
  1552. {
  1553. return p->value();
  1554. }
  1555. bool equal(const c_iterator& x) const BOOST_NOEXCEPT
  1556. {
  1557. return (p == x.p);
  1558. }
  1559. void increment() BOOST_NOEXCEPT
  1560. {
  1561. p = p->next;
  1562. if (!p) {
  1563. p = (++itb)->next;
  1564. }
  1565. }
  1566. };
  1567. } // namespace iterator_detail
  1568. //////////////////////////////////////////////////////////////////////////
  1569. // table structure used by the containers
  1570. template <typename Types>
  1571. struct table : boost::unordered::detail::functions<typename Types::hasher,
  1572. typename Types::key_equal>
  1573. {
  1574. private:
  1575. table(table const&);
  1576. table& operator=(table const&);
  1577. public:
  1578. typedef typename Types::hasher hasher;
  1579. typedef typename Types::key_equal key_equal;
  1580. typedef typename Types::const_key_type const_key_type;
  1581. typedef typename Types::extractor extractor;
  1582. typedef typename Types::value_type value_type;
  1583. typedef typename Types::table table_impl;
  1584. typedef boost::unordered::detail::functions<typename Types::hasher,
  1585. typename Types::key_equal>
  1586. functions;
  1587. typedef typename Types::value_allocator value_allocator;
  1588. typedef typename boost::allocator_void_pointer<value_allocator>::type void_pointer;
  1589. typedef node<value_type, void_pointer> node_type;
  1590. typedef boost::unordered::detail::grouped_bucket_array<
  1591. bucket<node_type, void_pointer>, value_allocator, prime_fmod_size<> >
  1592. bucket_array_type;
  1593. typedef typename bucket_array_type::node_allocator_type
  1594. node_allocator_type;
  1595. typedef typename boost::allocator_pointer<node_allocator_type>::type node_pointer;
  1596. typedef boost::unordered::detail::node_constructor<node_allocator_type>
  1597. node_constructor;
  1598. typedef boost::unordered::detail::node_tmp<node_allocator_type> node_tmp;
  1599. typedef typename bucket_array_type::bucket_type bucket_type;
  1600. typedef typename bucket_array_type::iterator bucket_iterator;
  1601. typedef typename bucket_array_type::local_iterator l_iterator;
  1602. typedef typename bucket_array_type::const_local_iterator cl_iterator;
  1603. typedef std::size_t size_type;
  1604. typedef iterator_detail::iterator<node_type, bucket_type> iterator;
  1605. typedef iterator_detail::c_iterator<node_type, bucket_type> c_iterator;
  1606. typedef std::pair<iterator, bool> emplace_return;
  1607. ////////////////////////////////////////////////////////////////////////
  1608. // Members
  1609. std::size_t size_;
  1610. float mlf_;
  1611. std::size_t max_load_;
  1612. bucket_array_type buckets_;
  1613. public:
  1614. ////////////////////////////////////////////////////////////////////////
  1615. // Data access
  1616. size_type bucket_count() const { return buckets_.bucket_count(); }
  1617. template <class Key>
  1618. iterator next_group(Key const& k, c_iterator n) const
  1619. {
  1620. c_iterator last = this->end();
  1621. while (n != last && this->key_eq()(k, extractor::extract(*n))) {
  1622. ++n;
  1623. }
  1624. return iterator(n.p, n.itb);
  1625. }
  1626. template <class Key> std::size_t group_count(Key const& k) const
  1627. {
  1628. if (size_ == 0) {
  1629. return 0;
  1630. }
  1631. std::size_t c = 0;
  1632. std::size_t const key_hash = this->hash(k);
  1633. bucket_iterator itb =
  1634. buckets_.at(buckets_.position(key_hash));
  1635. bool found = false;
  1636. for (node_pointer pos = itb->next; pos; pos = pos->next) {
  1637. if (this->key_eq()(k, this->get_key(pos))) {
  1638. ++c;
  1639. found = true;
  1640. } else if (found) {
  1641. break;
  1642. }
  1643. }
  1644. return c;
  1645. }
  1646. node_allocator_type const& node_alloc() const
  1647. {
  1648. return buckets_.get_node_allocator();
  1649. }
  1650. node_allocator_type& node_alloc()
  1651. {
  1652. return buckets_.get_node_allocator();
  1653. }
  1654. std::size_t max_bucket_count() const
  1655. {
  1656. typedef typename bucket_array_type::size_policy size_policy;
  1657. return size_policy::size(size_policy::size_index(
  1658. boost::allocator_max_size(this->node_alloc())));
  1659. }
  1660. iterator begin() const
  1661. {
  1662. if (size_ == 0) {
  1663. return end();
  1664. }
  1665. bucket_iterator itb = buckets_.begin();
  1666. return iterator(itb->next, itb);
  1667. }
  1668. iterator end() const
  1669. {
  1670. return iterator();
  1671. }
  1672. l_iterator begin(std::size_t bucket_index) const
  1673. {
  1674. return buckets_.begin(bucket_index);
  1675. }
  1676. std::size_t hash_to_bucket(std::size_t hash_value) const
  1677. {
  1678. return buckets_.position(hash_value);
  1679. }
  1680. std::size_t bucket_size(std::size_t index) const
  1681. {
  1682. std::size_t count = 0;
  1683. if (size_ > 0) {
  1684. bucket_iterator itb = buckets_.at(index);
  1685. node_pointer n = itb->next;
  1686. while (n) {
  1687. ++count;
  1688. n = n->next;
  1689. }
  1690. }
  1691. return count;
  1692. }
  1693. ////////////////////////////////////////////////////////////////////////
  1694. // Load methods
  1695. void recalculate_max_load()
  1696. {
  1697. // From 6.3.1/13:
  1698. // Only resize when size >= mlf_ * count
  1699. std::size_t const bc = buckets_.bucket_count();
  1700. // it's important we do the `bc == 0` check here because the `mlf_`
  1701. // can be specified to be infinity. The operation `n * INF` is `INF`
  1702. // for all `n > 0` but NaN for `n == 0`.
  1703. //
  1704. max_load_ =
  1705. bc == 0 ? 0
  1706. : boost::unordered::detail::double_to_size(
  1707. static_cast<double>(mlf_) * static_cast<double>(bc));
  1708. }
  1709. void max_load_factor(float z)
  1710. {
  1711. BOOST_ASSERT(z > 0);
  1712. mlf_ = (std::max)(z, minimum_max_load_factor);
  1713. recalculate_max_load();
  1714. }
  1715. ////////////////////////////////////////////////////////////////////////
  1716. // Constructors
  1717. table()
  1718. : functions(hasher(), key_equal()), size_(0), mlf_(1.0f),
  1719. max_load_(0)
  1720. {
  1721. }
  1722. table(std::size_t num_buckets, hasher const& hf, key_equal const& eq,
  1723. node_allocator_type const& a)
  1724. : functions(hf, eq), size_(0), mlf_(1.0f), max_load_(0),
  1725. buckets_(num_buckets, a)
  1726. {
  1727. recalculate_max_load();
  1728. }
  1729. table(table const& x, node_allocator_type const& a)
  1730. : functions(x), size_(0), mlf_(x.mlf_), max_load_(0),
  1731. buckets_(x.size_, a)
  1732. {
  1733. recalculate_max_load();
  1734. }
  1735. table(table& x, boost::unordered::detail::move_tag m)
  1736. : functions(x, m), size_(x.size_), mlf_(x.mlf_),
  1737. max_load_(x.max_load_), buckets_(boost::move(x.buckets_))
  1738. {
  1739. x.size_ = 0;
  1740. x.max_load_ = 0;
  1741. }
  1742. table(table& x, node_allocator_type const& a,
  1743. boost::unordered::detail::move_tag m)
  1744. : functions(x, m), size_(0), mlf_(x.mlf_), max_load_(0),
  1745. buckets_(x.bucket_count(), a)
  1746. {
  1747. recalculate_max_load();
  1748. }
  1749. ////////////////////////////////////////////////////////////////////////
  1750. // Swap and Move
  1751. void swap_allocators(table& other, false_type)
  1752. {
  1753. boost::unordered::detail::func::ignore_unused_variable_warning(other);
  1754. // According to 23.2.1.8, if propagate_on_container_swap is
  1755. // false the behaviour is undefined unless the allocators
  1756. // are equal.
  1757. BOOST_ASSERT(node_alloc() == other.node_alloc());
  1758. }
  1759. // Not nothrow swappable
  1760. void swap(table& x, false_type)
  1761. {
  1762. if (this == &x) {
  1763. return;
  1764. }
  1765. this->construct_spare_functions(x.current_functions());
  1766. BOOST_TRY { x.construct_spare_functions(this->current_functions()); }
  1767. BOOST_CATCH(...)
  1768. {
  1769. this->cleanup_spare_functions();
  1770. BOOST_RETHROW
  1771. }
  1772. BOOST_CATCH_END
  1773. this->switch_functions();
  1774. x.switch_functions();
  1775. buckets_.swap(x.buckets_);
  1776. boost::swap(size_, x.size_);
  1777. std::swap(mlf_, x.mlf_);
  1778. std::swap(max_load_, x.max_load_);
  1779. }
  1780. // Nothrow swappable
  1781. void swap(table& x, true_type)
  1782. {
  1783. buckets_.swap(x.buckets_);
  1784. boost::swap(size_, x.size_);
  1785. std::swap(mlf_, x.mlf_);
  1786. std::swap(max_load_, x.max_load_);
  1787. this->current_functions().swap(x.current_functions());
  1788. }
  1789. // Only swaps the allocators if propagate_on_container_swap.
  1790. // If not propagate_on_container_swap and allocators aren't
  1791. // equal, behaviour is undefined.
  1792. void swap(table& x)
  1793. {
  1794. BOOST_ASSERT(boost::allocator_propagate_on_container_swap<
  1795. node_allocator_type>::type::value ||
  1796. node_alloc() == x.node_alloc());
  1797. swap(x, boost::unordered::detail::integral_constant<bool,
  1798. functions::nothrow_swappable>());
  1799. }
  1800. // Only call with nodes allocated with the currect allocator, or
  1801. // one that is equal to it. (Can't assert because other's
  1802. // allocators might have already been moved).
  1803. void move_buckets_from(table& other)
  1804. {
  1805. buckets_ = boost::move(other.buckets_);
  1806. size_ = other.size_;
  1807. max_load_ = other.max_load_;
  1808. other.size_ = 0;
  1809. other.max_load_ = 0;
  1810. }
  1811. // For use in the constructor when allocators might be different.
  1812. void move_construct_buckets(table& src)
  1813. {
  1814. if (this->node_alloc() == src.node_alloc()) {
  1815. move_buckets_from(src);
  1816. return;
  1817. }
  1818. if (src.size_ == 0) {
  1819. return;
  1820. }
  1821. BOOST_ASSERT(
  1822. buckets_.bucket_count() == src.buckets_.bucket_count());
  1823. this->reserve(src.size_);
  1824. for (iterator pos = src.begin(); pos != src.end(); ++pos) {
  1825. node_tmp b(detail::func::construct_node(
  1826. this->node_alloc(), boost::move(pos.p->value())),
  1827. this->node_alloc());
  1828. const_key_type& k = this->get_key(b.node_);
  1829. std::size_t key_hash = this->hash(k);
  1830. bucket_iterator itb =
  1831. buckets_.at(buckets_.position(key_hash));
  1832. buckets_.insert_node(itb, b.release());
  1833. ++size_;
  1834. }
  1835. }
  1836. ////////////////////////////////////////////////////////////////////////
  1837. // Delete/destruct
  1838. ~table() { delete_buckets(); }
  1839. void delete_node(node_pointer p)
  1840. {
  1841. node_allocator_type alloc = this->node_alloc();
  1842. value_allocator val_alloc(alloc);
  1843. boost::allocator_destroy(val_alloc, p->value_ptr());
  1844. boost::allocator_deallocate(alloc, p, 1);
  1845. }
  1846. void delete_buckets()
  1847. {
  1848. iterator pos = begin(), last = this->end();
  1849. for (; pos != last;) {
  1850. node_pointer p = pos.p;
  1851. bucket_iterator itb = pos.itb;
  1852. ++pos;
  1853. buckets_.extract_node(itb, p);
  1854. delete_node(p);
  1855. --size_;
  1856. }
  1857. buckets_.clear();
  1858. }
  1859. ////////////////////////////////////////////////////////////////////////
  1860. // Clear
  1861. void clear_impl();
  1862. ////////////////////////////////////////////////////////////////////////
  1863. // Assignment
  1864. template <typename UniqueType>
  1865. void assign(table const& x, UniqueType is_unique)
  1866. {
  1867. typedef typename boost::allocator_propagate_on_container_copy_assignment<node_allocator_type>::type pocca;
  1868. if (this != &x) {
  1869. assign(x, is_unique,
  1870. boost::unordered::detail::integral_constant<bool,
  1871. pocca::value>());
  1872. }
  1873. }
  1874. template <typename UniqueType>
  1875. void assign(table const &x, UniqueType is_unique, false_type)
  1876. {
  1877. // Strong exception safety.
  1878. this->construct_spare_functions(x.current_functions());
  1879. BOOST_TRY
  1880. {
  1881. mlf_ = x.mlf_;
  1882. recalculate_max_load();
  1883. this->reserve_for_insert(x.size_);
  1884. this->clear_impl();
  1885. }
  1886. BOOST_CATCH(...)
  1887. {
  1888. this->cleanup_spare_functions();
  1889. BOOST_RETHROW
  1890. }
  1891. BOOST_CATCH_END
  1892. this->switch_functions();
  1893. copy_buckets(x, is_unique);
  1894. }
  1895. template <typename UniqueType>
  1896. void assign(table const &x, UniqueType is_unique, true_type)
  1897. {
  1898. if (node_alloc() == x.node_alloc())
  1899. {
  1900. buckets_.reset_allocator(x.node_alloc());
  1901. assign(x, is_unique, false_type());
  1902. }
  1903. else
  1904. {
  1905. bucket_array_type new_buckets(x.size_, x.node_alloc());
  1906. this->construct_spare_functions(x.current_functions());
  1907. this->switch_functions();
  1908. // Delete everything with current allocators before assigning
  1909. // the new ones.
  1910. delete_buckets();
  1911. buckets_.reset_allocator(x.node_alloc());
  1912. buckets_ = boost::move(new_buckets);
  1913. // Copy over other data, all no throw.
  1914. mlf_ = x.mlf_;
  1915. reserve(x.size_);
  1916. // Finally copy the elements.
  1917. if (x.size_)
  1918. {
  1919. copy_buckets(x, is_unique);
  1920. }
  1921. }
  1922. }
  1923. template <typename UniqueType>
  1924. void move_assign(table& x, UniqueType is_unique)
  1925. {
  1926. if (this != &x) {
  1927. move_assign(x, is_unique,
  1928. boost::unordered::detail::integral_constant<bool,
  1929. boost::allocator_propagate_on_container_move_assignment<
  1930. node_allocator_type>::type::value>());
  1931. }
  1932. }
  1933. // Propagate allocator
  1934. template <typename UniqueType>
  1935. void move_assign(table& x, UniqueType, true_type)
  1936. {
  1937. if (!functions::nothrow_move_assignable) {
  1938. this->construct_spare_functions(x.current_functions());
  1939. this->switch_functions();
  1940. } else {
  1941. this->current_functions().move_assign(x.current_functions());
  1942. }
  1943. delete_buckets();
  1944. buckets_.reset_allocator(x.buckets_.get_node_allocator());
  1945. mlf_ = x.mlf_;
  1946. move_buckets_from(x);
  1947. }
  1948. // Don't propagate allocator
  1949. template <typename UniqueType>
  1950. void move_assign(table& x, UniqueType is_unique, false_type)
  1951. {
  1952. if (node_alloc() == x.node_alloc()) {
  1953. move_assign_equal_alloc(x);
  1954. } else {
  1955. move_assign_realloc(x, is_unique);
  1956. }
  1957. }
  1958. void move_assign_equal_alloc(table& x)
  1959. {
  1960. if (!functions::nothrow_move_assignable) {
  1961. this->construct_spare_functions(x.current_functions());
  1962. this->switch_functions();
  1963. } else {
  1964. this->current_functions().move_assign(x.current_functions());
  1965. }
  1966. delete_buckets();
  1967. mlf_ = x.mlf_;
  1968. move_buckets_from(x);
  1969. }
  1970. template <typename UniqueType>
  1971. void move_assign_realloc(table& x, UniqueType is_unique)
  1972. {
  1973. this->construct_spare_functions(x.current_functions());
  1974. BOOST_TRY
  1975. {
  1976. mlf_ = x.mlf_;
  1977. recalculate_max_load();
  1978. if (x.size_ > 0) {
  1979. this->reserve_for_insert(x.size_);
  1980. }
  1981. this->clear_impl();
  1982. }
  1983. BOOST_CATCH(...)
  1984. {
  1985. this->cleanup_spare_functions();
  1986. BOOST_RETHROW
  1987. }
  1988. BOOST_CATCH_END
  1989. this->switch_functions();
  1990. move_assign_buckets(x, is_unique);
  1991. }
  1992. // Accessors
  1993. const_key_type& get_key(node_pointer n) const
  1994. {
  1995. return extractor::extract(n->value());
  1996. }
  1997. template <class Key>
  1998. std::size_t hash(Key const& k) const
  1999. {
  2000. return this->hash_function()(k);
  2001. }
  2002. // Find Node
  2003. template <class Key>
  2004. node_pointer find_node_impl(
  2005. Key const& x, bucket_iterator itb) const
  2006. {
  2007. node_pointer p = node_pointer();
  2008. if (itb != buckets_.end()) {
  2009. key_equal const& pred = this->key_eq();
  2010. p = itb->next;
  2011. for (; p; p = p->next) {
  2012. if (pred(x, extractor::extract(p->value()))) {
  2013. break;
  2014. }
  2015. }
  2016. }
  2017. return p;
  2018. }
  2019. template <class Key> node_pointer find_node(Key const& k) const
  2020. {
  2021. std::size_t const key_hash = this->hash(k);
  2022. return find_node_impl(
  2023. k, buckets_.at(buckets_.position(key_hash)));
  2024. }
  2025. node_pointer find_node(
  2026. const_key_type& k, bucket_iterator itb) const
  2027. {
  2028. return find_node_impl(k, itb);
  2029. }
  2030. template <class Key> iterator find(Key const& k) const
  2031. {
  2032. return this->transparent_find(
  2033. k, this->hash_function(), this->key_eq());
  2034. }
  2035. template <class Key, class Hash, class Pred>
  2036. inline iterator transparent_find(
  2037. Key const& k, Hash const& h, Pred const& pred) const
  2038. {
  2039. if (size_ > 0) {
  2040. std::size_t const key_hash = h(k);
  2041. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2042. for (node_pointer p = itb->next; p; p = p->next) {
  2043. if (BOOST_LIKELY(pred(k, extractor::extract(p->value())))) {
  2044. return iterator(p, itb);
  2045. }
  2046. }
  2047. }
  2048. return this->end();
  2049. }
  2050. template <class Key>
  2051. node_pointer* find_prev(Key const& key, bucket_iterator itb)
  2052. {
  2053. if (size_ > 0) {
  2054. key_equal pred = this->key_eq();
  2055. for (node_pointer* pp = boost::addressof(itb->next); *pp;
  2056. pp = boost::addressof((*pp)->next)) {
  2057. if (pred(key, extractor::extract((*pp)->value()))) {
  2058. return pp;
  2059. }
  2060. }
  2061. }
  2062. typedef node_pointer* node_pointer_pointer;
  2063. return node_pointer_pointer();
  2064. }
  2065. // Extract and erase
  2066. template <class Key> node_pointer extract_by_key_impl(Key const& k)
  2067. {
  2068. iterator it = this->find(k);
  2069. if (it == this->end()) {
  2070. return node_pointer();
  2071. }
  2072. buckets_.extract_node(it.itb, it.p);
  2073. --size_;
  2074. return it.p;
  2075. }
  2076. // Reserve and rehash
  2077. void transfer_node(
  2078. node_pointer p, bucket_type&, bucket_array_type& new_buckets)
  2079. {
  2080. const_key_type& key = extractor::extract(p->value());
  2081. std::size_t const h = this->hash(key);
  2082. bucket_iterator itnewb = new_buckets.at(new_buckets.position(h));
  2083. new_buckets.insert_node(itnewb, p);
  2084. }
  2085. static std::size_t min_buckets(std::size_t num_elements, float mlf)
  2086. {
  2087. std::size_t num_buckets = static_cast<std::size_t>(
  2088. std::ceil(static_cast<float>(num_elements) / mlf));
  2089. if (num_buckets == 0 && num_elements > 0) { // mlf == inf
  2090. num_buckets = 1;
  2091. }
  2092. return num_buckets;
  2093. }
  2094. void rehash(std::size_t);
  2095. void reserve(std::size_t);
  2096. void reserve_for_insert(std::size_t);
  2097. void rehash_impl(std::size_t);
  2098. ////////////////////////////////////////////////////////////////////////
  2099. // Unique keys
  2100. // equals
  2101. bool equals_unique(table const& other) const
  2102. {
  2103. if (this->size_ != other.size_)
  2104. return false;
  2105. c_iterator pos = this->begin();
  2106. c_iterator last = this->end();
  2107. while (pos != last) {
  2108. node_pointer p = pos.p;
  2109. node_pointer p2 = other.find_node(this->get_key(p));
  2110. if (!p2 || !(p->value() == p2->value())) {
  2111. return false;
  2112. }
  2113. ++pos;
  2114. }
  2115. return true;
  2116. }
  2117. // Emplace/Insert
  2118. template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
  2119. iterator emplace_hint_unique(
  2120. c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
  2121. {
  2122. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  2123. return iterator(hint.p, hint.itb);
  2124. } else {
  2125. return emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
  2126. }
  2127. }
  2128. template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
  2129. emplace_return emplace_unique(
  2130. const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
  2131. {
  2132. std::size_t key_hash = this->hash(k);
  2133. bucket_iterator itb =
  2134. buckets_.at(buckets_.position(key_hash));
  2135. node_pointer pos = this->find_node_impl(k, itb);
  2136. if (pos) {
  2137. return emplace_return(iterator(pos, itb), false);
  2138. } else {
  2139. node_tmp b(boost::unordered::detail::func::construct_node_from_args(
  2140. this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
  2141. this->node_alloc());
  2142. if (size_ + 1 > max_load_) {
  2143. reserve(size_ + 1);
  2144. itb = buckets_.at(buckets_.position(key_hash));
  2145. }
  2146. node_pointer p = b.release();
  2147. buckets_.insert_node(itb, p);
  2148. ++size_;
  2149. return emplace_return(iterator(p, itb), true);
  2150. }
  2151. }
  2152. template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
  2153. iterator emplace_hint_unique(
  2154. c_iterator hint, no_key, BOOST_UNORDERED_EMPLACE_ARGS)
  2155. {
  2156. node_tmp b(boost::unordered::detail::func::construct_node_from_args(
  2157. this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
  2158. this->node_alloc());
  2159. const_key_type& k = this->get_key(b.node_);
  2160. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  2161. return iterator(hint.p, hint.itb);
  2162. }
  2163. std::size_t const key_hash = this->hash(k);
  2164. bucket_iterator itb =
  2165. buckets_.at(buckets_.position(key_hash));
  2166. node_pointer p = this->find_node_impl(k, itb);
  2167. if (p) {
  2168. return iterator(p, itb);
  2169. }
  2170. if (size_ + 1 > max_load_) {
  2171. this->reserve(size_ + 1);
  2172. itb = buckets_.at(buckets_.position(key_hash));
  2173. }
  2174. p = b.release();
  2175. buckets_.insert_node(itb, p);
  2176. ++size_;
  2177. return iterator(p, itb);
  2178. }
  2179. template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
  2180. emplace_return emplace_unique(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
  2181. {
  2182. node_tmp b(boost::unordered::detail::func::construct_node_from_args(
  2183. this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
  2184. this->node_alloc());
  2185. const_key_type& k = this->get_key(b.node_);
  2186. std::size_t key_hash = this->hash(k);
  2187. bucket_iterator itb =
  2188. buckets_.at(buckets_.position(key_hash));
  2189. node_pointer pos = this->find_node_impl(k, itb);
  2190. if (pos) {
  2191. return emplace_return(iterator(pos, itb), false);
  2192. } else {
  2193. if (size_ + 1 > max_load_) {
  2194. reserve(size_ + 1);
  2195. itb = buckets_.at(buckets_.position(key_hash));
  2196. }
  2197. node_pointer p = b.release();
  2198. buckets_.insert_node(itb, p);
  2199. ++size_;
  2200. return emplace_return(iterator(p, itb), true);
  2201. }
  2202. }
  2203. template <typename Key>
  2204. emplace_return try_emplace_unique(BOOST_FWD_REF(Key) k)
  2205. {
  2206. std::size_t key_hash = this->hash(k);
  2207. bucket_iterator itb =
  2208. buckets_.at(buckets_.position(key_hash));
  2209. node_pointer pos = this->find_node_impl(k, itb);
  2210. if (pos) {
  2211. return emplace_return(iterator(pos, itb), false);
  2212. } else {
  2213. node_allocator_type alloc = node_alloc();
  2214. value_type* dispatch = BOOST_NULLPTR;
  2215. node_tmp tmp(detail::func::construct_node_from_key(
  2216. dispatch, alloc, boost::forward<Key>(k)),
  2217. alloc);
  2218. if (size_ + 1 > max_load_) {
  2219. reserve(size_ + 1);
  2220. itb = buckets_.at(buckets_.position(key_hash));
  2221. }
  2222. node_pointer p = tmp.release();
  2223. buckets_.insert_node(itb, p);
  2224. ++size_;
  2225. return emplace_return(iterator(p, itb), true);
  2226. }
  2227. }
  2228. template <typename Key>
  2229. iterator try_emplace_hint_unique(c_iterator hint, BOOST_FWD_REF(Key) k)
  2230. {
  2231. if (hint.p && this->key_eq()(extractor::extract(*hint), k)) {
  2232. return iterator(hint.p, hint.itb);
  2233. } else {
  2234. return try_emplace_unique(k).first;
  2235. }
  2236. }
  2237. template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
  2238. emplace_return try_emplace_unique(
  2239. BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
  2240. {
  2241. std::size_t key_hash = this->hash(k);
  2242. bucket_iterator itb =
  2243. buckets_.at(buckets_.position(key_hash));
  2244. node_pointer pos = this->find_node_impl(k, itb);
  2245. if (pos) {
  2246. return emplace_return(iterator(pos, itb), false);
  2247. }
  2248. node_tmp b(
  2249. boost::unordered::detail::func::construct_node_pair_from_args(
  2250. this->node_alloc(), k, BOOST_UNORDERED_EMPLACE_FORWARD),
  2251. this->node_alloc());
  2252. if (size_ + 1 > max_load_) {
  2253. reserve(size_ + 1);
  2254. itb = buckets_.at(buckets_.position(key_hash));
  2255. }
  2256. pos = b.release();
  2257. buckets_.insert_node(itb, pos);
  2258. ++size_;
  2259. return emplace_return(iterator(pos, itb), true);
  2260. }
  2261. template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
  2262. iterator try_emplace_hint_unique(
  2263. c_iterator hint, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
  2264. {
  2265. if (hint.p && this->key_eq()(hint->first, k)) {
  2266. return iterator(hint.p, hint.itb);
  2267. } else {
  2268. return try_emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
  2269. }
  2270. }
  2271. template <typename Key, typename M>
  2272. emplace_return insert_or_assign_unique(
  2273. BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
  2274. {
  2275. std::size_t key_hash = this->hash(k);
  2276. bucket_iterator itb =
  2277. buckets_.at(buckets_.position(key_hash));
  2278. node_pointer p = this->find_node_impl(k, itb);
  2279. if (p) {
  2280. p->value().second = boost::forward<M>(obj);
  2281. return emplace_return(iterator(p, itb), false);
  2282. }
  2283. node_tmp b(boost::unordered::detail::func::construct_node_pair(
  2284. this->node_alloc(), boost::forward<Key>(k),
  2285. boost::forward<M>(obj)),
  2286. node_alloc());
  2287. if (size_ + 1 > max_load_) {
  2288. reserve(size_ + 1);
  2289. itb = buckets_.at(buckets_.position(key_hash));
  2290. }
  2291. p = b.release();
  2292. buckets_.insert_node(itb, p);
  2293. ++size_;
  2294. return emplace_return(iterator(p, itb), true);
  2295. }
  2296. template <typename NodeType, typename InsertReturnType>
  2297. void move_insert_node_type_unique(
  2298. NodeType& np, InsertReturnType& result)
  2299. {
  2300. if (!np) {
  2301. result.position = this->end();
  2302. result.inserted = false;
  2303. return;
  2304. }
  2305. const_key_type& k = this->get_key(np.ptr_);
  2306. std::size_t const key_hash = this->hash(k);
  2307. bucket_iterator itb =
  2308. buckets_.at(buckets_.position(key_hash));
  2309. node_pointer p = this->find_node_impl(k, itb);
  2310. if (p) {
  2311. iterator pos(p, itb);
  2312. result.node = boost::move(np);
  2313. result.position = pos;
  2314. result.inserted = false;
  2315. return;
  2316. }
  2317. this->reserve_for_insert(size_ + 1);
  2318. p = np.ptr_;
  2319. itb = buckets_.at(buckets_.position(key_hash));
  2320. buckets_.insert_node(itb, p);
  2321. np.ptr_ = node_pointer();
  2322. ++size_;
  2323. result.position = iterator(p, itb);
  2324. result.inserted = true;
  2325. }
  2326. template <typename NodeType>
  2327. iterator move_insert_node_type_with_hint_unique(
  2328. c_iterator hint, NodeType& np)
  2329. {
  2330. if (!np) {
  2331. return this->end();
  2332. }
  2333. const_key_type& k = this->get_key(np.ptr_);
  2334. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  2335. return iterator(hint.p, hint.itb);
  2336. }
  2337. std::size_t const key_hash = this->hash(k);
  2338. bucket_iterator itb =
  2339. buckets_.at(buckets_.position(key_hash));
  2340. node_pointer p = this->find_node_impl(k, itb);
  2341. if (p) {
  2342. return iterator(p, itb);
  2343. }
  2344. p = np.ptr_;
  2345. if (size_ + 1 > max_load_) {
  2346. this->reserve(size_ + 1);
  2347. itb = buckets_.at(buckets_.position(key_hash));
  2348. }
  2349. buckets_.insert_node(itb, p);
  2350. ++size_;
  2351. np.ptr_ = node_pointer();
  2352. return iterator(p, itb);
  2353. }
  2354. template <typename Types2>
  2355. void merge_unique(boost::unordered::detail::table<Types2>& other)
  2356. {
  2357. typedef boost::unordered::detail::table<Types2> other_table;
  2358. BOOST_STATIC_ASSERT((boost::is_same<node_type,
  2359. typename other_table::node_type>::value));
  2360. BOOST_ASSERT(this->node_alloc() == other.node_alloc());
  2361. if (other.size_ == 0) {
  2362. return;
  2363. }
  2364. this->reserve_for_insert(size_ + other.size_);
  2365. iterator last = other.end();
  2366. for (iterator pos = other.begin(); pos != last;) {
  2367. const_key_type& key = other.get_key(pos.p);
  2368. std::size_t const key_hash = this->hash(key);
  2369. bucket_iterator itb =
  2370. buckets_.at(buckets_.position(key_hash));
  2371. if (this->find_node_impl(key, itb)) {
  2372. ++pos;
  2373. continue;
  2374. }
  2375. iterator old = pos;
  2376. ++pos;
  2377. node_pointer p = other.extract_by_iterator_unique(old);
  2378. buckets_.insert_node(itb, p);
  2379. ++size_;
  2380. }
  2381. }
  2382. ////////////////////////////////////////////////////////////////////////
  2383. // Insert range methods
  2384. //
  2385. // if hash function throws, or inserting > 1 element, basic exception
  2386. // safety strong otherwise
  2387. template <class InputIt>
  2388. void insert_range_unique(no_key, InputIt i, InputIt j)
  2389. {
  2390. hasher const& hf = this->hash_function();
  2391. node_allocator_type alloc = this->node_alloc();
  2392. for (; i != j; ++i) {
  2393. node_tmp tmp(detail::func::construct_node(alloc, *i), alloc);
  2394. value_type const& value = tmp.node_->value();
  2395. const_key_type& key = extractor::extract(value);
  2396. std::size_t const h = hf(key);
  2397. bucket_iterator itb = buckets_.at(buckets_.position(h));
  2398. node_pointer it = find_node_impl(key, itb);
  2399. if (it) {
  2400. continue;
  2401. }
  2402. if (size_ + 1 > max_load_) {
  2403. reserve(size_ + 1);
  2404. itb = buckets_.at(buckets_.position(h));
  2405. }
  2406. node_pointer nptr = tmp.release();
  2407. buckets_.insert_node(itb, nptr);
  2408. ++size_;
  2409. }
  2410. }
  2411. ////////////////////////////////////////////////////////////////////////
  2412. // Extract
  2413. inline node_pointer extract_by_iterator_unique(c_iterator i)
  2414. {
  2415. node_pointer p = i.p;
  2416. bucket_iterator itb = i.itb;
  2417. buckets_.extract_node(itb, p);
  2418. --size_;
  2419. return p;
  2420. }
  2421. ////////////////////////////////////////////////////////////////////////
  2422. // Erase
  2423. //
  2424. template <class Key> std::size_t erase_key_unique_impl(Key const& k)
  2425. {
  2426. bucket_iterator itb = buckets_.at(buckets_.position(this->hash(k)));
  2427. node_pointer* pp = this->find_prev(k, itb);
  2428. if (!pp) {
  2429. return 0;
  2430. }
  2431. node_pointer p = *pp;
  2432. buckets_.extract_node_after(itb, pp);
  2433. this->delete_node(p);
  2434. --size_;
  2435. return 1;
  2436. }
  2437. iterator erase_node(c_iterator pos) {
  2438. c_iterator next = pos;
  2439. ++next;
  2440. bucket_iterator itb = pos.itb;
  2441. node_pointer* pp = boost::addressof(itb->next);
  2442. while (*pp != pos.p) {
  2443. pp = boost::addressof((*pp)->next);
  2444. }
  2445. buckets_.extract_node_after(itb, pp);
  2446. this->delete_node(pos.p);
  2447. --size_;
  2448. return iterator(next.p, next.itb);
  2449. }
  2450. iterator erase_nodes_range(c_iterator first, c_iterator last)
  2451. {
  2452. if (first == last) {
  2453. return iterator(last.p, last.itb);
  2454. }
  2455. // though `first` stores of a copy of a pointer to a node, we wish to
  2456. // mutate the pointers stored internally by the singly-linked list in
  2457. // each bucket group so we have to retrieve it manually by iterating
  2458. //
  2459. bucket_iterator itb = first.itb;
  2460. node_pointer* pp = boost::addressof(itb->next);
  2461. while (*pp != first.p) {
  2462. pp = boost::addressof((*pp)->next);
  2463. }
  2464. while (*pp != last.p) {
  2465. node_pointer p = *pp;
  2466. *pp = (*pp)->next;
  2467. this->delete_node(p);
  2468. --size_;
  2469. bool const at_end = !(*pp);
  2470. bool const is_empty_bucket = !itb->next;
  2471. if (at_end) {
  2472. if (is_empty_bucket) {
  2473. buckets_.unlink_bucket(itb++);
  2474. } else {
  2475. ++itb;
  2476. }
  2477. pp = boost::addressof(itb->next);
  2478. }
  2479. }
  2480. return iterator(last.p, last.itb);
  2481. }
  2482. ////////////////////////////////////////////////////////////////////////
  2483. // fill_buckets_unique
  2484. void copy_buckets(table const& src, true_type)
  2485. {
  2486. BOOST_ASSERT(size_ == 0);
  2487. this->reserve_for_insert(src.size_);
  2488. for (iterator pos = src.begin(); pos != src.end(); ++pos) {
  2489. value_type const& value = *pos;
  2490. const_key_type& key = extractor::extract(value);
  2491. std::size_t const key_hash = this->hash(key);
  2492. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2493. node_allocator_type alloc = this->node_alloc();
  2494. node_tmp tmp(detail::func::construct_node(alloc, value), alloc);
  2495. buckets_.insert_node(itb, tmp.release());
  2496. ++size_;
  2497. }
  2498. }
  2499. void move_assign_buckets(table& src, true_type)
  2500. {
  2501. BOOST_ASSERT(size_ == 0);
  2502. BOOST_ASSERT(max_load_ >= src.size_);
  2503. iterator last = src.end();
  2504. node_allocator_type alloc = this->node_alloc();
  2505. for (iterator pos = src.begin(); pos != last; ++pos) {
  2506. value_type value = boost::move(*pos);
  2507. const_key_type& key = extractor::extract(value);
  2508. std::size_t const key_hash = this->hash(key);
  2509. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2510. node_tmp tmp(
  2511. detail::func::construct_node(alloc, boost::move(value)), alloc);
  2512. buckets_.insert_node(itb, tmp.release());
  2513. ++size_;
  2514. }
  2515. }
  2516. ////////////////////////////////////////////////////////////////////////
  2517. // Equivalent keys
  2518. // Equality
  2519. bool equals_equiv(table const& other) const
  2520. {
  2521. if (this->size_ != other.size_)
  2522. return false;
  2523. iterator last = this->end();
  2524. for (iterator n1 = this->begin(); n1 != last;) {
  2525. const_key_type& k = extractor::extract(*n1);
  2526. iterator n2 = other.find(k);
  2527. if (n2 == other.end()) {
  2528. return false;
  2529. }
  2530. iterator end1 = this->next_group(k, n1);
  2531. iterator end2 = other.next_group(k, n2);
  2532. if (!group_equals_equiv(n1, end1, n2, end2)) {
  2533. return false;
  2534. }
  2535. n1 = end1;
  2536. }
  2537. return true;
  2538. }
  2539. static bool group_equals_equiv(iterator n1, iterator end1,
  2540. iterator n2, iterator end2)
  2541. {
  2542. for (;;) {
  2543. if (*n1 != *n2)
  2544. break;
  2545. ++n1;
  2546. ++n2;
  2547. if (n1 == end1)
  2548. return n2 == end2;
  2549. if (n2 == end2)
  2550. return false;
  2551. }
  2552. for (iterator n1a = n1, n2a = n2;;) {
  2553. ++n1a;
  2554. ++n2a;
  2555. if (n1a == end1) {
  2556. if (n2a == end2)
  2557. break;
  2558. else
  2559. return false;
  2560. }
  2561. if (n2a == end2)
  2562. return false;
  2563. }
  2564. iterator start = n1;
  2565. for (; n1 != end1; ++n1) {
  2566. value_type const& v = *n1;
  2567. if (!find_equiv(start, n1, v)) {
  2568. std::size_t matches = count_equal_equiv(n2, end2, v);
  2569. if (!matches)
  2570. return false;
  2571. iterator t = n1;
  2572. if (matches != 1 + count_equal_equiv(++t, end1, v))
  2573. return false;
  2574. }
  2575. }
  2576. return true;
  2577. }
  2578. static bool find_equiv(
  2579. iterator n, iterator last, value_type const& v)
  2580. {
  2581. for (; n != last; ++n)
  2582. if (*n == v)
  2583. return true;
  2584. return false;
  2585. }
  2586. static std::size_t count_equal_equiv(
  2587. iterator n, iterator last, value_type const& v)
  2588. {
  2589. std::size_t count = 0;
  2590. for (; n != last; ++n)
  2591. if (*n == v)
  2592. ++count;
  2593. return count;
  2594. }
  2595. // Emplace/Insert
  2596. iterator emplace_equiv(node_pointer n)
  2597. {
  2598. node_tmp a(n, this->node_alloc());
  2599. const_key_type& k = this->get_key(a.node_);
  2600. std::size_t key_hash = this->hash(k);
  2601. bucket_iterator itb =
  2602. buckets_.at(buckets_.position(key_hash));
  2603. node_pointer hint = this->find_node_impl(k, itb);
  2604. if (size_ + 1 > max_load_) {
  2605. this->reserve(size_ + 1);
  2606. itb = buckets_.at(buckets_.position(key_hash));
  2607. }
  2608. node_pointer p = a.release();
  2609. buckets_.insert_node_hint(itb, p, hint);
  2610. ++size_;
  2611. return iterator(p, itb);
  2612. }
  2613. iterator emplace_hint_equiv(c_iterator hint, node_pointer n)
  2614. {
  2615. node_tmp a(n, this->node_alloc());
  2616. const_key_type& k = this->get_key(a.node_);
  2617. bucket_iterator itb = hint.itb;
  2618. node_pointer p = hint.p;
  2619. std::size_t key_hash = 0u;
  2620. bool const needs_rehash = (size_ + 1 > max_load_);
  2621. bool const usable_hint = (p && this->key_eq()(k, this->get_key(p)));
  2622. if (!usable_hint) {
  2623. key_hash = this->hash(k);
  2624. itb = buckets_.at(buckets_.position(key_hash));
  2625. p = this->find_node_impl(k, itb);
  2626. } else if (usable_hint && needs_rehash) {
  2627. key_hash = this->hash(k);
  2628. }
  2629. if (needs_rehash) {
  2630. this->reserve(size_ + 1);
  2631. itb = buckets_.at(buckets_.position(key_hash));
  2632. }
  2633. a.release();
  2634. buckets_.insert_node_hint(itb, n, p);
  2635. ++size_;
  2636. return iterator(n, itb);
  2637. }
  2638. void emplace_no_rehash_equiv(node_pointer n)
  2639. {
  2640. BOOST_ASSERT(size_ + 1 <= max_load_);
  2641. node_tmp a(n, this->node_alloc());
  2642. const_key_type& k = this->get_key(a.node_);
  2643. std::size_t key_hash = this->hash(k);
  2644. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2645. node_pointer hint = this->find_node_impl(k, itb);
  2646. node_pointer p = a.release();
  2647. buckets_.insert_node_hint(itb, p, hint);
  2648. ++size_;
  2649. }
  2650. template <typename NodeType>
  2651. iterator move_insert_node_type_equiv(NodeType& np)
  2652. {
  2653. iterator result;
  2654. if (np) {
  2655. this->reserve_for_insert(size_ + 1);
  2656. const_key_type& k = this->get_key(np.ptr_);
  2657. std::size_t key_hash = this->hash(k);
  2658. bucket_iterator itb =
  2659. buckets_.at(buckets_.position(key_hash));
  2660. node_pointer hint = this->find_node_impl(k, itb);
  2661. buckets_.insert_node_hint(itb, np.ptr_, hint);
  2662. ++size_;
  2663. result = iterator(np.ptr_, itb);
  2664. np.ptr_ = node_pointer();
  2665. }
  2666. return result;
  2667. }
  2668. template <typename NodeType>
  2669. iterator move_insert_node_type_with_hint_equiv(
  2670. c_iterator hint, NodeType& np)
  2671. {
  2672. iterator result;
  2673. if (np) {
  2674. bucket_iterator itb = hint.itb;
  2675. node_pointer pos = hint.p;
  2676. const_key_type& k = this->get_key(np.ptr_);
  2677. std::size_t key_hash = this->hash(k);
  2678. if (size_ + 1 > max_load_) {
  2679. this->reserve(size_ + 1);
  2680. itb = buckets_.at(buckets_.position(key_hash));
  2681. }
  2682. if (hint.p && this->key_eq()(k, this->get_key(hint.p))) {
  2683. } else {
  2684. itb = buckets_.at(buckets_.position(key_hash));
  2685. pos = this->find_node_impl(k, itb);
  2686. }
  2687. buckets_.insert_node_hint(itb, np.ptr_, pos);
  2688. ++size_;
  2689. result = iterator(np.ptr_, itb);
  2690. np.ptr_ = node_pointer();
  2691. }
  2692. return result;
  2693. }
  2694. ////////////////////////////////////////////////////////////////////////
  2695. // Insert range methods
  2696. // if hash function throws, or inserting > 1 element, basic exception
  2697. // safety. Strong otherwise
  2698. template <class I>
  2699. typename boost::unordered::detail::enable_if_forward<I, void>::type
  2700. insert_range_equiv(I i, I j)
  2701. {
  2702. if (i == j)
  2703. return;
  2704. std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
  2705. if (distance == 1) {
  2706. emplace_equiv(boost::unordered::detail::func::construct_node(
  2707. this->node_alloc(), *i));
  2708. } else {
  2709. // Only require basic exception safety here
  2710. this->reserve_for_insert(size_ + distance);
  2711. for (; i != j; ++i) {
  2712. emplace_no_rehash_equiv(
  2713. boost::unordered::detail::func::construct_node(
  2714. this->node_alloc(), *i));
  2715. }
  2716. }
  2717. }
  2718. template <class I>
  2719. typename boost::unordered::detail::disable_if_forward<I, void>::type
  2720. insert_range_equiv(I i, I j)
  2721. {
  2722. for (; i != j; ++i) {
  2723. emplace_equiv(boost::unordered::detail::func::construct_node(
  2724. this->node_alloc(), *i));
  2725. }
  2726. }
  2727. ////////////////////////////////////////////////////////////////////////
  2728. // Extract
  2729. inline node_pointer extract_by_iterator_equiv(c_iterator n)
  2730. {
  2731. node_pointer p = n.p;
  2732. bucket_iterator itb = n.itb;
  2733. buckets_.extract_node(itb, p);
  2734. --size_;
  2735. return p;
  2736. }
  2737. ////////////////////////////////////////////////////////////////////////
  2738. // Erase
  2739. //
  2740. // no throw
  2741. template <class Key> std::size_t erase_key_equiv_impl(Key const& k)
  2742. {
  2743. std::size_t deleted_count = 0;
  2744. bucket_iterator itb = buckets_.at(buckets_.position(this->hash(k)));
  2745. node_pointer* pp = this->find_prev(k, itb);
  2746. if (pp) {
  2747. while (*pp && this->key_eq()(this->get_key(*pp), k)) {
  2748. node_pointer p = *pp;
  2749. *pp = (*pp)->next;
  2750. this->delete_node(p);
  2751. --size_;
  2752. ++deleted_count;
  2753. }
  2754. if (!itb->next) {
  2755. buckets_.unlink_bucket(itb);
  2756. }
  2757. }
  2758. return deleted_count;
  2759. }
  2760. std::size_t erase_key_equiv(const_key_type& k)
  2761. {
  2762. return this->erase_key_equiv_impl(k);
  2763. }
  2764. ////////////////////////////////////////////////////////////////////////
  2765. // fill_buckets
  2766. void copy_buckets(table const& src, false_type)
  2767. {
  2768. BOOST_ASSERT(size_ == 0);
  2769. this->reserve_for_insert(src.size_);
  2770. iterator last = src.end();
  2771. for (iterator pos = src.begin(); pos != last; ++pos) {
  2772. value_type const& value = *pos;
  2773. const_key_type& key = extractor::extract(value);
  2774. std::size_t const key_hash = this->hash(key);
  2775. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2776. node_allocator_type alloc = this->node_alloc();
  2777. node_tmp tmp(detail::func::construct_node(alloc, value), alloc);
  2778. node_pointer hint = this->find_node_impl(key, itb);
  2779. buckets_.insert_node_hint(itb, tmp.release(), hint);
  2780. ++size_;
  2781. }
  2782. }
  2783. void move_assign_buckets(table& src, false_type)
  2784. {
  2785. BOOST_ASSERT(size_ == 0);
  2786. BOOST_ASSERT(max_load_ >= src.size_);
  2787. iterator last = src.end();
  2788. node_allocator_type alloc = this->node_alloc();
  2789. for (iterator pos = src.begin(); pos != last; ++pos) {
  2790. value_type value = boost::move(*pos);
  2791. const_key_type& key = extractor::extract(value);
  2792. std::size_t const key_hash = this->hash(key);
  2793. bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
  2794. node_pointer hint = this->find_node_impl(key, itb);
  2795. node_tmp tmp(
  2796. detail::func::construct_node(alloc, boost::move(value)), alloc);
  2797. buckets_.insert_node_hint(itb, tmp.release(), hint);
  2798. ++size_;
  2799. }
  2800. }
  2801. };
  2802. //////////////////////////////////////////////////////////////////////////
  2803. // Clear
  2804. template <typename Types> inline void table<Types>::clear_impl()
  2805. {
  2806. bucket_iterator itb = buckets_.begin(), last = buckets_.end();
  2807. for (; itb != last;) {
  2808. bucket_iterator next_itb = itb;
  2809. ++next_itb;
  2810. node_pointer* pp = boost::addressof(itb->next);
  2811. while (*pp) {
  2812. node_pointer p = *pp;
  2813. buckets_.extract_node_after(itb, pp);
  2814. this->delete_node(p);
  2815. --size_;
  2816. }
  2817. itb = next_itb;
  2818. }
  2819. }
  2820. //////////////////////////////////////////////////////////////////////////
  2821. // Reserve & Rehash
  2822. // if hash function throws, basic exception safety
  2823. // strong otherwise.
  2824. template <typename Types>
  2825. inline void table<Types>::rehash(std::size_t num_buckets)
  2826. {
  2827. num_buckets = buckets_.bucket_count_for(
  2828. (std::max)(min_buckets(size_, mlf_), num_buckets));
  2829. if (num_buckets != this->bucket_count()) {
  2830. this->rehash_impl(num_buckets);
  2831. }
  2832. }
  2833. template <class Types>
  2834. inline void table<Types>::reserve(std::size_t num_elements)
  2835. {
  2836. std::size_t num_buckets = min_buckets(num_elements, mlf_);
  2837. this->rehash(num_buckets);
  2838. }
  2839. template <class Types>
  2840. inline void table<Types>::reserve_for_insert(std::size_t num_elements)
  2841. {
  2842. if (num_elements > max_load_) {
  2843. std::size_t const num_buckets = static_cast<std::size_t>(
  2844. 1.0f + std::ceil(static_cast<float>(num_elements) / mlf_));
  2845. this->rehash_impl(num_buckets);
  2846. }
  2847. }
  2848. template <class Types>
  2849. inline void table<Types>::rehash_impl(std::size_t num_buckets)
  2850. {
  2851. bucket_array_type new_buckets(
  2852. num_buckets, buckets_.get_node_allocator());
  2853. BOOST_TRY
  2854. {
  2855. boost::unordered::detail::span<bucket_type> bspan = buckets_.raw();
  2856. bucket_type* pos = bspan.data;
  2857. std::size_t size = bspan.size;
  2858. bucket_type* last = pos + size;
  2859. for (; pos != last; ++pos) {
  2860. bucket_type& b = *pos;
  2861. for (node_pointer p = b.next; p;) {
  2862. node_pointer next_p = p->next;
  2863. transfer_node(p, b, new_buckets);
  2864. p = next_p;
  2865. b.next = p;
  2866. }
  2867. }
  2868. }
  2869. BOOST_CATCH(...)
  2870. {
  2871. for (bucket_iterator pos = new_buckets.begin();
  2872. pos != new_buckets.end(); ++pos) {
  2873. bucket_type& b = *pos;
  2874. for (node_pointer p = b.next; p;) {
  2875. node_pointer next_p = p->next;
  2876. delete_node(p);
  2877. --size_;
  2878. p = next_p;
  2879. }
  2880. }
  2881. buckets_.unlink_empty_buckets();
  2882. BOOST_RETHROW;
  2883. }
  2884. BOOST_CATCH_END
  2885. buckets_ = boost::move(new_buckets);
  2886. recalculate_max_load();
  2887. }
  2888. #if defined(BOOST_MSVC)
  2889. #pragma warning(pop)
  2890. #endif
  2891. ////////////////////////////////////////////////////////////////////////
  2892. // key extractors
  2893. //
  2894. // no throw
  2895. //
  2896. // 'extract_key' is called with the emplace parameters to return a
  2897. // key if available or 'no_key' is one isn't and will need to be
  2898. // constructed. This could be done by overloading the emplace
  2899. // implementation
  2900. // for the different cases, but that's a bit tricky on compilers without
  2901. // variadic templates.
  2902. template <typename Key, typename T> struct is_key
  2903. {
  2904. template <typename T2> static choice1::type test(T2 const&);
  2905. static choice2::type test(Key const&);
  2906. enum
  2907. {
  2908. value = sizeof(test(boost::unordered::detail::make<T>())) ==
  2909. sizeof(choice2::type)
  2910. };
  2911. typedef
  2912. typename boost::conditional<value, Key const&, no_key>::type type;
  2913. };
  2914. template <class ValueType> struct set_extractor
  2915. {
  2916. typedef ValueType value_type;
  2917. typedef ValueType key_type;
  2918. static key_type const& extract(value_type const& v) { return v; }
  2919. static key_type const& extract(BOOST_UNORDERED_RV_REF(value_type) v)
  2920. {
  2921. return v;
  2922. }
  2923. static no_key extract() { return no_key(); }
  2924. template <class Arg> static no_key extract(Arg const&)
  2925. {
  2926. return no_key();
  2927. }
  2928. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  2929. template <class Arg1, class Arg2, class... Args>
  2930. static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
  2931. {
  2932. return no_key();
  2933. }
  2934. #else
  2935. template <class Arg1, class Arg2>
  2936. static no_key extract(Arg1 const&, Arg2 const&)
  2937. {
  2938. return no_key();
  2939. }
  2940. #endif
  2941. };
  2942. template <class ValueType> struct map_extractor
  2943. {
  2944. typedef ValueType value_type;
  2945. typedef typename boost::remove_const<typename boost::unordered::detail::
  2946. pair_traits<ValueType>::first_type>::type key_type;
  2947. static key_type const& extract(value_type const& v) { return v.first; }
  2948. template <class Second>
  2949. static key_type const& extract(std::pair<key_type, Second> const& v)
  2950. {
  2951. return v.first;
  2952. }
  2953. template <class Second>
  2954. static key_type const& extract(
  2955. std::pair<key_type const, Second> const& v)
  2956. {
  2957. return v.first;
  2958. }
  2959. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  2960. template <class Second>
  2961. static key_type const& extract(
  2962. boost::rv<std::pair<key_type, Second> > const& v)
  2963. {
  2964. return v.first;
  2965. }
  2966. template <class Second>
  2967. static key_type const& extract(
  2968. boost::rv<std::pair<key_type const, Second> > const& v)
  2969. {
  2970. return v.first;
  2971. }
  2972. #endif
  2973. template <class Arg1>
  2974. static key_type const& extract(key_type const& k, Arg1 const&)
  2975. {
  2976. return k;
  2977. }
  2978. static no_key extract() { return no_key(); }
  2979. template <class Arg> static no_key extract(Arg const&)
  2980. {
  2981. return no_key();
  2982. }
  2983. template <class Arg1, class Arg2>
  2984. static no_key extract(Arg1 const&, Arg2 const&)
  2985. {
  2986. return no_key();
  2987. }
  2988. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  2989. template <class Arg1, class Arg2, class Arg3, class... Args>
  2990. static no_key extract(
  2991. Arg1 const&, Arg2 const&, Arg3 const&, Args const&...)
  2992. {
  2993. return no_key();
  2994. }
  2995. #endif
  2996. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  2997. #define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
  2998. template <typename T2> \
  2999. static no_key extract(boost::unordered::piecewise_construct_t, \
  3000. namespace_ tuple<> const&, T2 const&) \
  3001. { \
  3002. return no_key(); \
  3003. } \
  3004. \
  3005. template <typename T, typename T2> \
  3006. static typename is_key<key_type, T>::type extract( \
  3007. boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k, \
  3008. T2 const&) \
  3009. { \
  3010. return typename is_key<key_type, T>::type(namespace_ get<0>(k)); \
  3011. }
  3012. #else
  3013. #define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
  3014. static no_key extract( \
  3015. boost::unordered::piecewise_construct_t, namespace_ tuple<> const&) \
  3016. { \
  3017. return no_key(); \
  3018. } \
  3019. \
  3020. template <typename T> \
  3021. static typename is_key<key_type, T>::type extract( \
  3022. boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k) \
  3023. { \
  3024. return typename is_key<key_type, T>::type(namespace_ get<0>(k)); \
  3025. }
  3026. #endif
  3027. BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
  3028. #if BOOST_UNORDERED_TUPLE_ARGS
  3029. BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
  3030. #endif
  3031. #undef BOOST_UNORDERED_KEY_FROM_TUPLE
  3032. };
  3033. template <class Container, class Predicate>
  3034. typename Container::size_type erase_if(Container& c, Predicate& pred)
  3035. {
  3036. typedef typename Container::size_type size_type;
  3037. typedef typename Container::iterator iterator;
  3038. size_type const size = c.size();
  3039. for (iterator pos = c.begin(), last = c.end(); pos != last;) {
  3040. if (pred(*pos)) {
  3041. pos = c.erase(pos);
  3042. } else {
  3043. ++pos;
  3044. }
  3045. }
  3046. return (size - c.size());
  3047. }
  3048. }
  3049. }
  3050. }
  3051. #undef BOOST_UNORDERED_EMPLACE_TEMPLATE
  3052. #undef BOOST_UNORDERED_EMPLACE_ARGS
  3053. #undef BOOST_UNORDERED_EMPLACE_FORWARD
  3054. #endif