hashed_index.hpp 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912
  1. /* Copyright 2003-2023 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_HASHED_INDEX_HPP
  9. #define BOOST_MULTI_INDEX_HASHED_INDEX_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <algorithm>
  15. #include <boost/call_traits.hpp>
  16. #include <boost/core/addressof.hpp>
  17. #include <boost/core/no_exceptions_support.hpp>
  18. #include <boost/detail/workaround.hpp>
  19. #include <boost/limits.hpp>
  20. #include <boost/move/core.hpp>
  21. #include <boost/move/utility_core.hpp>
  22. #include <boost/mpl/bool.hpp>
  23. #include <boost/mpl/if.hpp>
  24. #include <boost/mpl/push_front.hpp>
  25. #include <boost/multi_index/detail/access_specifier.hpp>
  26. #include <boost/multi_index/detail/adl_swap.hpp>
  27. #include <boost/multi_index/detail/allocator_traits.hpp>
  28. #include <boost/multi_index/detail/auto_space.hpp>
  29. #include <boost/multi_index/detail/bucket_array.hpp>
  30. #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
  31. #include <boost/multi_index/detail/hash_index_iterator.hpp>
  32. #include <boost/multi_index/detail/index_node_base.hpp>
  33. #include <boost/multi_index/detail/invalidate_iterators.hpp>
  34. #include <boost/multi_index/detail/modify_key_adaptor.hpp>
  35. #include <boost/multi_index/detail/node_handle.hpp>
  36. #include <boost/multi_index/detail/promotes_arg.hpp>
  37. #include <boost/multi_index/detail/safe_mode.hpp>
  38. #include <boost/multi_index/detail/scope_guard.hpp>
  39. #include <boost/multi_index/detail/vartempl_support.hpp>
  40. #include <boost/multi_index/hashed_index_fwd.hpp>
  41. #include <boost/tuple/tuple.hpp>
  42. #include <boost/type_traits/is_same.hpp>
  43. #include <cmath>
  44. #include <cstddef>
  45. #include <functional>
  46. #include <iterator>
  47. #include <utility>
  48. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  49. #include <initializer_list>
  50. #endif
  51. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  52. #include <boost/core/serialization.hpp>
  53. #endif
  54. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  55. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x) \
  56. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  57. detail::make_obj_guard(x,&hashed_index::check_invariant_); \
  58. BOOST_JOIN(check_invariant_,__LINE__).touch();
  59. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT \
  60. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(*this)
  61. #else
  62. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x)
  63. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  64. #endif
  65. namespace boost{
  66. namespace multi_index{
  67. namespace detail{
  68. /* hashed_index adds a layer of hashed indexing to a given Super */
  69. /* Most of the implementation of unique and non-unique indices is
  70. * shared. We tell from one another on instantiation time by using
  71. * Category tags defined in hash_index_node.hpp.
  72. */
  73. #if defined(BOOST_MSVC)
  74. #pragma warning(push)
  75. #pragma warning(disable:4355) /* this used in base member initializer list */
  76. #endif
  77. template<
  78. typename KeyFromValue,typename Hash,typename Pred,
  79. typename SuperMeta,typename TagList,typename Category
  80. >
  81. class hashed_index:
  82. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
  83. {
  84. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  85. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  86. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  87. * lifetime of const references bound to temporaries --precisely what
  88. * scopeguards are.
  89. */
  90. #pragma parse_mfunc_templ off
  91. #endif
  92. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  93. /* cross-index access */
  94. template <typename,typename,typename> friend class index_base;
  95. #endif
  96. typedef typename SuperMeta::type super;
  97. protected:
  98. typedef hashed_index_node<
  99. typename super::index_node_type> index_node_type;
  100. private:
  101. typedef typename index_node_type::
  102. template node_alg<Category>::type node_alg;
  103. typedef typename index_node_type::impl_type node_impl_type;
  104. typedef typename node_impl_type::pointer node_impl_pointer;
  105. typedef typename node_impl_type::base_pointer node_impl_base_pointer;
  106. typedef bucket_array<
  107. typename super::final_allocator_type> bucket_array_type;
  108. public:
  109. /* types */
  110. typedef typename KeyFromValue::result_type key_type;
  111. typedef typename index_node_type::value_type value_type;
  112. typedef KeyFromValue key_from_value;
  113. typedef Hash hasher;
  114. typedef Pred key_equal;
  115. typedef typename super::final_allocator_type allocator_type;
  116. private:
  117. typedef allocator_traits<allocator_type> alloc_traits;
  118. public:
  119. typedef typename alloc_traits::pointer pointer;
  120. typedef typename alloc_traits::const_pointer const_pointer;
  121. typedef value_type& reference;
  122. typedef const value_type& const_reference;
  123. typedef typename alloc_traits::size_type size_type;
  124. typedef typename alloc_traits::difference_type difference_type;
  125. typedef tuple<size_type,
  126. key_from_value,hasher,key_equal> ctor_args;
  127. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  128. typedef safe_mode::safe_iterator<
  129. hashed_index_iterator<
  130. index_node_type,bucket_array_type,
  131. Category,
  132. hashed_index_global_iterator_tag> > iterator;
  133. #else
  134. typedef hashed_index_iterator<
  135. index_node_type,bucket_array_type,
  136. Category,hashed_index_global_iterator_tag> iterator;
  137. #endif
  138. typedef iterator const_iterator;
  139. typedef hashed_index_iterator<
  140. index_node_type,bucket_array_type,
  141. Category,hashed_index_local_iterator_tag> local_iterator;
  142. typedef local_iterator const_local_iterator;
  143. typedef typename super::final_node_handle_type node_type;
  144. typedef detail::insert_return_type<
  145. iterator,node_type> insert_return_type;
  146. typedef TagList tag_list;
  147. protected:
  148. typedef typename super::final_node_type final_node_type;
  149. typedef tuples::cons<
  150. ctor_args,
  151. typename super::ctor_args_list> ctor_args_list;
  152. typedef typename mpl::push_front<
  153. typename super::index_type_list,
  154. hashed_index>::type index_type_list;
  155. typedef typename mpl::push_front<
  156. typename super::iterator_type_list,
  157. iterator>::type iterator_type_list;
  158. typedef typename mpl::push_front<
  159. typename super::const_iterator_type_list,
  160. const_iterator>::type const_iterator_type_list;
  161. typedef typename super::copy_map_type copy_map_type;
  162. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  163. typedef typename super::index_saver_type index_saver_type;
  164. typedef typename super::index_loader_type index_loader_type;
  165. #endif
  166. private:
  167. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  168. typedef safe_mode::safe_container<iterator> safe_container;
  169. #endif
  170. typedef typename call_traits<value_type>::param_type value_param_type;
  171. typedef typename call_traits<
  172. key_type>::param_type key_param_type;
  173. /* needed to avoid commas in some macros */
  174. typedef std::pair<iterator,bool> pair_return_type;
  175. public:
  176. /* construct/destroy/copy
  177. * Default and copy ctors are in the protected section as indices are
  178. * not supposed to be created on their own. No range ctor either.
  179. */
  180. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  181. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  182. {
  183. this->final()=x.final();
  184. return *this;
  185. }
  186. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  187. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  188. std::initializer_list<value_type> list)
  189. {
  190. this->final()=list;
  191. return *this;
  192. }
  193. #endif
  194. allocator_type get_allocator()const BOOST_NOEXCEPT
  195. {
  196. return this->final().get_allocator();
  197. }
  198. /* size and capacity */
  199. bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
  200. size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
  201. size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
  202. /* iterators */
  203. iterator begin()BOOST_NOEXCEPT
  204. {
  205. return make_iterator(
  206. index_node_type::from_impl(header()->next()->prior()));
  207. }
  208. const_iterator begin()const BOOST_NOEXCEPT
  209. {
  210. return make_iterator(
  211. index_node_type::from_impl(header()->next()->prior()));
  212. }
  213. iterator end()BOOST_NOEXCEPT{return make_iterator(header());}
  214. const_iterator end()const BOOST_NOEXCEPT{return make_iterator(header());}
  215. const_iterator cbegin()const BOOST_NOEXCEPT{return begin();}
  216. const_iterator cend()const BOOST_NOEXCEPT{return end();}
  217. iterator iterator_to(const value_type& x)
  218. {
  219. return make_iterator(
  220. node_from_value<index_node_type>(boost::addressof(x)));
  221. }
  222. const_iterator iterator_to(const value_type& x)const
  223. {
  224. return make_iterator(
  225. node_from_value<index_node_type>(boost::addressof(x)));
  226. }
  227. /* modifiers */
  228. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
  229. pair_return_type,emplace,emplace_impl)
  230. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
  231. iterator,emplace_hint,emplace_hint_impl,iterator,position)
  232. std::pair<iterator,bool> insert(const value_type& x)
  233. {
  234. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  235. std::pair<final_node_type*,bool> p=this->final_insert_(x);
  236. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  237. }
  238. std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
  239. {
  240. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  241. std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
  242. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  243. }
  244. iterator insert(iterator position,const value_type& x)
  245. {
  246. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  247. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  248. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  249. std::pair<final_node_type*,bool> p=this->final_insert_(
  250. x,static_cast<final_node_type*>(position.get_node()));
  251. return make_iterator(p.first);
  252. }
  253. iterator insert(iterator position,BOOST_RV_REF(value_type) x)
  254. {
  255. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  256. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  257. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  258. std::pair<final_node_type*,bool> p=this->final_insert_rv_(
  259. x,static_cast<final_node_type*>(position.get_node()));
  260. return make_iterator(p.first);
  261. }
  262. template<typename InputIterator>
  263. void insert(InputIterator first,InputIterator last)
  264. {
  265. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  266. for(;first!=last;++first)this->final_insert_ref_(*first);
  267. }
  268. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  269. void insert(std::initializer_list<value_type> list)
  270. {
  271. insert(list.begin(),list.end());
  272. }
  273. #endif
  274. insert_return_type insert(BOOST_RV_REF(node_type) nh)
  275. {
  276. if(nh)BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,nh);
  277. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  278. std::pair<final_node_type*,bool> p=this->final_insert_nh_(nh);
  279. return insert_return_type(make_iterator(p.first),p.second,boost::move(nh));
  280. }
  281. iterator insert(const_iterator position,BOOST_RV_REF(node_type) nh)
  282. {
  283. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  284. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  285. if(nh)BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,nh);
  286. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  287. std::pair<final_node_type*,bool> p=this->final_insert_nh_(
  288. nh,static_cast<final_node_type*>(position.get_node()));
  289. return make_iterator(p.first);
  290. }
  291. node_type extract(const_iterator position)
  292. {
  293. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  294. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  295. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  296. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  297. return this->final_extract_(
  298. static_cast<final_node_type*>(position.get_node()));
  299. }
  300. node_type extract(key_param_type x)
  301. {
  302. iterator position=find(x);
  303. if(position==end())return node_type();
  304. else return extract(position);
  305. }
  306. iterator erase(iterator position)
  307. {
  308. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  309. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  310. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  311. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  312. this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
  313. return position;
  314. }
  315. size_type erase(key_param_type k)
  316. {
  317. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  318. std::size_t buc=buckets.position(hash_(k));
  319. for(node_impl_pointer x=buckets.at(buc)->prior();
  320. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  321. if(eq_(k,key(index_node_type::from_impl(x)->value()))){
  322. node_impl_pointer y=end_of_range(x);
  323. size_type s=0;
  324. do{
  325. node_impl_pointer z=node_alg::after(x);
  326. this->final_erase_(
  327. static_cast<final_node_type*>(index_node_type::from_impl(x)));
  328. x=z;
  329. ++s;
  330. }while(x!=y);
  331. return s;
  332. }
  333. }
  334. return 0;
  335. }
  336. iterator erase(iterator first,iterator last)
  337. {
  338. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  339. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  340. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  341. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  342. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  343. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  344. while(first!=last){
  345. first=erase(first);
  346. }
  347. return first;
  348. }
  349. bool replace(iterator position,const value_type& x)
  350. {
  351. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  352. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  353. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  354. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  355. return this->final_replace_(
  356. x,static_cast<final_node_type*>(position.get_node()));
  357. }
  358. bool replace(iterator position,BOOST_RV_REF(value_type) x)
  359. {
  360. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  361. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  362. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  363. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  364. return this->final_replace_rv_(
  365. x,static_cast<final_node_type*>(position.get_node()));
  366. }
  367. template<typename Modifier>
  368. bool modify(iterator position,Modifier mod)
  369. {
  370. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  371. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  372. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  373. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  374. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  375. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  376. * this is not added. Left it for all compilers as it does no
  377. * harm.
  378. */
  379. position.detach();
  380. #endif
  381. return this->final_modify_(
  382. mod,static_cast<final_node_type*>(position.get_node()));
  383. }
  384. template<typename Modifier,typename Rollback>
  385. bool modify(iterator position,Modifier mod,Rollback back_)
  386. {
  387. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  388. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  389. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  390. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  391. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  392. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  393. * this is not added. Left it for all compilers as it does no
  394. * harm.
  395. */
  396. position.detach();
  397. #endif
  398. return this->final_modify_(
  399. mod,back_,static_cast<final_node_type*>(position.get_node()));
  400. }
  401. template<typename Modifier>
  402. bool modify_key(iterator position,Modifier mod)
  403. {
  404. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  405. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  406. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  407. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  408. return modify(
  409. position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
  410. }
  411. template<typename Modifier,typename Rollback>
  412. bool modify_key(iterator position,Modifier mod,Rollback back_)
  413. {
  414. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  415. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  416. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  417. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  418. return modify(
  419. position,
  420. modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
  421. modify_key_adaptor<Rollback,value_type,KeyFromValue>(back_,key));
  422. }
  423. void clear()BOOST_NOEXCEPT
  424. {
  425. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  426. this->final_clear_();
  427. }
  428. void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  429. {
  430. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  431. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x);
  432. this->final_swap_(x.final());
  433. }
  434. template<typename Index>
  435. BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
  436. merge(Index& x)
  437. {
  438. merge(x,x.begin(),x.end());
  439. }
  440. template<typename Index>
  441. BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
  442. merge(BOOST_RV_REF(Index) x){merge(static_cast<Index&>(x));}
  443. template<typename Index>
  444. BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,pair_return_type)
  445. merge(Index& x,BOOST_DEDUCED_TYPENAME Index::iterator i)
  446. {
  447. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
  448. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
  449. BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
  450. BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,x);
  451. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  452. if(x.end().get_node()==this->header()){ /* same container */
  453. return std::pair<iterator,bool>(
  454. make_iterator(static_cast<final_node_type*>(i.get_node())),true);
  455. }
  456. else{
  457. std::pair<final_node_type*,bool> p=this->final_transfer_(
  458. x,static_cast<final_node_type*>(i.get_node()));
  459. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  460. }
  461. }
  462. template<typename Index>
  463. BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,pair_return_type)
  464. merge(BOOST_RV_REF(Index) x,BOOST_DEDUCED_TYPENAME Index::iterator i)
  465. {
  466. return merge(static_cast<Index&>(x),i);
  467. }
  468. template<typename Index>
  469. BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
  470. merge(
  471. Index& x,
  472. BOOST_DEDUCED_TYPENAME Index::iterator first,
  473. BOOST_DEDUCED_TYPENAME Index::iterator last)
  474. {
  475. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  476. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  477. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
  478. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
  479. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  480. BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,x);
  481. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  482. if(x.end().get_node()!=this->header()){ /* different containers */
  483. this->final_transfer_range_(x,first,last);
  484. }
  485. }
  486. template<typename Index>
  487. BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(hashed_index,Index,void)
  488. merge(
  489. BOOST_RV_REF(Index) x,
  490. BOOST_DEDUCED_TYPENAME Index::iterator first,
  491. BOOST_DEDUCED_TYPENAME Index::iterator last)
  492. {
  493. merge(static_cast<Index&>(x),first,last);
  494. }
  495. /* observers */
  496. key_from_value key_extractor()const{return key;}
  497. hasher hash_function()const{return hash_;}
  498. key_equal key_eq()const{return eq_;}
  499. /* lookup */
  500. /* Internally, these ops rely on const_iterator being the same
  501. * type as iterator.
  502. */
  503. /* Implementation note: When CompatibleKey is consistently promoted to
  504. * KeyFromValue::result_type for equality comparison, the promotion is made
  505. * once in advance to increase efficiency.
  506. */
  507. template<typename CompatibleKey>
  508. iterator find(const CompatibleKey& k)const
  509. {
  510. return find(k,hash_,eq_);
  511. }
  512. template<
  513. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  514. >
  515. iterator find(
  516. const CompatibleKey& k,
  517. const CompatibleHash& hash,const CompatiblePred& eq)const
  518. {
  519. return find(
  520. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  521. }
  522. template<typename CompatibleKey>
  523. size_type count(const CompatibleKey& k)const
  524. {
  525. return count(k,hash_,eq_);
  526. }
  527. template<
  528. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  529. >
  530. size_type count(
  531. const CompatibleKey& k,
  532. const CompatibleHash& hash,const CompatiblePred& eq)const
  533. {
  534. return count(
  535. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  536. }
  537. template<typename CompatibleKey>
  538. bool contains(const CompatibleKey& k)const
  539. {
  540. return contains(k,hash_,eq_);
  541. }
  542. template<
  543. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  544. >
  545. bool contains(
  546. const CompatibleKey& k,
  547. const CompatibleHash& hash,const CompatiblePred& eq)const
  548. {
  549. return find(k,hash,eq)!=end();
  550. }
  551. template<typename CompatibleKey>
  552. std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
  553. {
  554. return equal_range(k,hash_,eq_);
  555. }
  556. template<
  557. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  558. >
  559. std::pair<iterator,iterator> equal_range(
  560. const CompatibleKey& k,
  561. const CompatibleHash& hash,const CompatiblePred& eq)const
  562. {
  563. return equal_range(
  564. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  565. }
  566. /* bucket interface */
  567. size_type bucket_count()const BOOST_NOEXCEPT
  568. {
  569. return static_cast<size_type>(buckets.size());
  570. }
  571. size_type max_bucket_count()const BOOST_NOEXCEPT{return static_cast<size_type>(-1);}
  572. size_type bucket_size(size_type n)const
  573. {
  574. size_type res=0;
  575. for(node_impl_pointer x=buckets.at(n)->prior();
  576. x!=node_impl_pointer(0);x=node_alg::after_local(x)){
  577. ++res;
  578. }
  579. return res;
  580. }
  581. size_type bucket(key_param_type k)const
  582. {
  583. return static_cast<size_type>(buckets.position(hash_(k)));
  584. }
  585. local_iterator begin(size_type n)
  586. {
  587. return const_cast<const hashed_index*>(this)->begin(n);
  588. }
  589. const_local_iterator begin(size_type n)const
  590. {
  591. node_impl_pointer x=buckets.at(n)->prior();
  592. if(x==node_impl_pointer(0))return end(n);
  593. return make_local_iterator(index_node_type::from_impl(x));
  594. }
  595. local_iterator end(size_type n)
  596. {
  597. return const_cast<const hashed_index*>(this)->end(n);
  598. }
  599. const_local_iterator end(size_type)const
  600. {
  601. return make_local_iterator(0);
  602. }
  603. const_local_iterator cbegin(size_type n)const{return begin(n);}
  604. const_local_iterator cend(size_type n)const{return end(n);}
  605. local_iterator local_iterator_to(const value_type& x)
  606. {
  607. return make_local_iterator(
  608. node_from_value<index_node_type>(boost::addressof(x)));
  609. }
  610. const_local_iterator local_iterator_to(const value_type& x)const
  611. {
  612. return make_local_iterator(
  613. node_from_value<index_node_type>(boost::addressof(x)));
  614. }
  615. /* hash policy */
  616. float load_factor()const BOOST_NOEXCEPT
  617. {return static_cast<float>(size())/bucket_count();}
  618. float max_load_factor()const BOOST_NOEXCEPT{return mlf;}
  619. void max_load_factor(float z){mlf=z;calculate_max_load();}
  620. void rehash(size_type n)
  621. {
  622. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  623. if(size()<=max_load&&n<=bucket_count())return;
  624. size_type bc =(std::numeric_limits<size_type>::max)();
  625. float fbc=1.0f+static_cast<float>(size())/mlf;
  626. if(bc>fbc){
  627. bc=static_cast<size_type>(fbc);
  628. if(bc<n)bc=n;
  629. }
  630. unchecked_rehash(bc);
  631. }
  632. void reserve(size_type n)
  633. {
  634. rehash(static_cast<size_type>(std::ceil(static_cast<float>(n)/mlf)));
  635. }
  636. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  637. hashed_index(const ctor_args_list& args_list,const allocator_type& al):
  638. super(args_list.get_tail(),al),
  639. key(tuples::get<1>(args_list.get_head())),
  640. hash_(tuples::get<2>(args_list.get_head())),
  641. eq_(tuples::get<3>(args_list.get_head())),
  642. buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
  643. mlf(1.0f)
  644. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  645. ,safe(*this)
  646. #endif
  647. {
  648. calculate_max_load();
  649. }
  650. hashed_index(
  651. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
  652. super(x),
  653. key(x.key),
  654. hash_(x.hash_),
  655. eq_(x.eq_),
  656. buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
  657. mlf(x.mlf),
  658. max_load(x.max_load)
  659. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  660. ,safe(*this)
  661. #endif
  662. {
  663. /* Copy ctor just takes the internal configuration objects from x. The rest
  664. * is done in subsequent call to copy_().
  665. */
  666. }
  667. hashed_index(
  668. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  669. do_not_copy_elements_tag):
  670. super(x,do_not_copy_elements_tag()),
  671. key(x.key),
  672. hash_(x.hash_),
  673. eq_(x.eq_),
  674. buckets(x.get_allocator(),header()->impl(),0),
  675. mlf(1.0f)
  676. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  677. ,safe(*this)
  678. #endif
  679. {
  680. calculate_max_load();
  681. }
  682. ~hashed_index()
  683. {
  684. /* the container is guaranteed to be empty by now */
  685. }
  686. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  687. iterator make_iterator(index_node_type* node)
  688. {
  689. return iterator(node,&safe);
  690. }
  691. const_iterator make_iterator(index_node_type* node)const
  692. {
  693. return const_iterator(node,const_cast<safe_container*>(&safe));
  694. }
  695. #else
  696. iterator make_iterator(index_node_type* node)
  697. {
  698. return iterator(node);
  699. }
  700. const_iterator make_iterator(index_node_type* node)const
  701. {
  702. return const_iterator(node);
  703. }
  704. #endif
  705. local_iterator make_local_iterator(index_node_type* node)
  706. {
  707. return local_iterator(node);
  708. }
  709. const_local_iterator make_local_iterator(index_node_type* node)const
  710. {
  711. return const_local_iterator(node);
  712. }
  713. void copy_(
  714. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  715. const copy_map_type& map)
  716. {
  717. copy_(x,map,Category());
  718. }
  719. void copy_(
  720. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  721. const copy_map_type& map,hashed_unique_tag)
  722. {
  723. if(x.size()!=0){
  724. node_impl_pointer end_org=x.header()->impl(),
  725. org=end_org,
  726. cpy=header()->impl();
  727. do{
  728. node_impl_pointer prev_org=org->prior(),
  729. prev_cpy=
  730. static_cast<index_node_type*>(map.find(static_cast<final_node_type*>(
  731. index_node_type::from_impl(prev_org))))->impl();
  732. cpy->prior()=prev_cpy;
  733. if(node_alg::is_first_of_bucket(org)){
  734. node_impl_base_pointer buc_org=prev_org->next(),
  735. buc_cpy=
  736. buckets.begin()+(buc_org-x.buckets.begin());
  737. prev_cpy->next()=buc_cpy;
  738. buc_cpy->prior()=cpy;
  739. }
  740. else{
  741. prev_cpy->next()=node_impl_type::base_pointer_from(cpy);
  742. }
  743. org=prev_org;
  744. cpy=prev_cpy;
  745. }while(org!=end_org);
  746. }
  747. super::copy_(x,map);
  748. }
  749. void copy_(
  750. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  751. const copy_map_type& map,hashed_non_unique_tag)
  752. {
  753. if(x.size()!=0){
  754. node_impl_pointer end_org=x.header()->impl(),
  755. org=end_org,
  756. cpy=header()->impl();
  757. do{
  758. node_impl_pointer next_org=node_alg::after(org),
  759. next_cpy=
  760. static_cast<index_node_type*>(map.find(static_cast<final_node_type*>(
  761. index_node_type::from_impl(next_org))))->impl();
  762. if(node_alg::is_first_of_bucket(next_org)){
  763. node_impl_base_pointer buc_org=org->next(),
  764. buc_cpy=
  765. buckets.begin()+(buc_org-x.buckets.begin());
  766. cpy->next()=buc_cpy;
  767. buc_cpy->prior()=next_cpy;
  768. next_cpy->prior()=cpy;
  769. }
  770. else{
  771. if(org->next()==node_impl_type::base_pointer_from(next_org)){
  772. cpy->next()=node_impl_type::base_pointer_from(next_cpy);
  773. }
  774. else{
  775. cpy->next()=
  776. node_impl_type::base_pointer_from(
  777. static_cast<index_node_type*>(
  778. map.find(static_cast<final_node_type*>(
  779. index_node_type::from_impl(
  780. node_impl_type::pointer_from(org->next())))))->impl());
  781. }
  782. if(next_org->prior()!=org){
  783. next_cpy->prior()=
  784. static_cast<index_node_type*>(
  785. map.find(static_cast<final_node_type*>(
  786. index_node_type::from_impl(next_org->prior()))))->impl();
  787. }
  788. else{
  789. next_cpy->prior()=cpy;
  790. }
  791. }
  792. org=next_org;
  793. cpy=next_cpy;
  794. }while(org!=end_org);
  795. }
  796. super::copy_(x,map);
  797. }
  798. template<typename Variant>
  799. final_node_type* insert_(
  800. value_param_type v,final_node_type*& x,Variant variant)
  801. {
  802. reserve_for_insert(size()+1);
  803. std::size_t buc=find_bucket(v);
  804. link_info pos(buckets.at(buc));
  805. if(!link_point(v,pos)){
  806. return static_cast<final_node_type*>(
  807. index_node_type::from_impl(node_impl_type::pointer_from(pos)));
  808. }
  809. final_node_type* res=super::insert_(v,x,variant);
  810. if(res==x)link(static_cast<index_node_type*>(x),pos);
  811. return res;
  812. }
  813. template<typename Variant>
  814. final_node_type* insert_(
  815. value_param_type v,index_node_type* position,
  816. final_node_type*& x,Variant variant)
  817. {
  818. reserve_for_insert(size()+1);
  819. std::size_t buc=find_bucket(v);
  820. link_info pos(buckets.at(buc));
  821. if(!link_point(v,pos)){
  822. return static_cast<final_node_type*>(
  823. index_node_type::from_impl(node_impl_type::pointer_from(pos)));
  824. }
  825. final_node_type* res=super::insert_(v,position,x,variant);
  826. if(res==x)link(static_cast<index_node_type*>(x),pos);
  827. return res;
  828. }
  829. template<typename Dst>
  830. void extract_(index_node_type* x,Dst dst)
  831. {
  832. unlink(x);
  833. super::extract_(x,dst.next());
  834. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  835. transfer_iterators(dst.get(),x);
  836. #endif
  837. }
  838. void delete_all_nodes_()
  839. {
  840. delete_all_nodes_(Category());
  841. }
  842. void delete_all_nodes_(hashed_unique_tag)
  843. {
  844. for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){
  845. node_impl_pointer y=x->prior();
  846. this->final_delete_node_(
  847. static_cast<final_node_type*>(index_node_type::from_impl(x)));
  848. x=y;
  849. }
  850. }
  851. void delete_all_nodes_(hashed_non_unique_tag)
  852. {
  853. for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){
  854. node_impl_pointer y=x->prior();
  855. if(y->next()!=node_impl_type::base_pointer_from(x)&&
  856. y->next()->prior()!=x){ /* n-1 of group */
  857. /* Make the second node prior() pointer back-linked so that it won't
  858. * refer to a deleted node when the time for its own destruction comes.
  859. */
  860. node_impl_pointer first=node_impl_type::pointer_from(y->next());
  861. first->next()->prior()=first;
  862. }
  863. this->final_delete_node_(
  864. static_cast<final_node_type*>(index_node_type::from_impl(x)));
  865. x=y;
  866. }
  867. }
  868. void clear_()
  869. {
  870. super::clear_();
  871. buckets.clear(header()->impl());
  872. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  873. safe.detach_dereferenceable_iterators();
  874. #endif
  875. }
  876. template<typename BoolConstant>
  877. void swap_(
  878. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  879. BoolConstant swap_allocators)
  880. {
  881. adl_swap(key,x.key);
  882. adl_swap(hash_,x.hash_);
  883. adl_swap(eq_,x.eq_);
  884. buckets.swap(x.buckets,swap_allocators);
  885. std::swap(mlf,x.mlf);
  886. std::swap(max_load,x.max_load);
  887. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  888. safe.swap(x.safe);
  889. #endif
  890. super::swap_(x,swap_allocators);
  891. }
  892. void swap_elements_(
  893. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  894. {
  895. buckets.swap(x.buckets);
  896. std::swap(mlf,x.mlf);
  897. std::swap(max_load,x.max_load);
  898. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  899. safe.swap(x.safe);
  900. #endif
  901. super::swap_elements_(x);
  902. }
  903. template<typename Variant>
  904. bool replace_(value_param_type v,index_node_type* x,Variant variant)
  905. {
  906. if(eq_(key(v),key(x->value()))){
  907. return super::replace_(v,x,variant);
  908. }
  909. unlink_undo undo;
  910. unlink(x,undo);
  911. BOOST_TRY{
  912. std::size_t buc=find_bucket(v);
  913. link_info pos(buckets.at(buc));
  914. if(link_point(v,pos)&&super::replace_(v,x,variant)){
  915. link(x,pos);
  916. return true;
  917. }
  918. undo();
  919. return false;
  920. }
  921. BOOST_CATCH(...){
  922. undo();
  923. BOOST_RETHROW;
  924. }
  925. BOOST_CATCH_END
  926. }
  927. bool modify_(index_node_type* x)
  928. {
  929. std::size_t buc;
  930. bool b;
  931. BOOST_TRY{
  932. buc=find_bucket(x->value());
  933. b=in_place(x->impl(),key(x->value()),buc);
  934. }
  935. BOOST_CATCH(...){
  936. extract_(x,invalidate_iterators());
  937. BOOST_RETHROW;
  938. }
  939. BOOST_CATCH_END
  940. if(!b){
  941. unlink(x);
  942. BOOST_TRY{
  943. link_info pos(buckets.at(buc));
  944. if(!link_point(x->value(),pos)){
  945. super::extract_(x,invalidate_iterators());
  946. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  947. detach_iterators(x);
  948. #endif
  949. return false;
  950. }
  951. link(x,pos);
  952. }
  953. BOOST_CATCH(...){
  954. super::extract_(x,invalidate_iterators());
  955. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  956. detach_iterators(x);
  957. #endif
  958. BOOST_RETHROW;
  959. }
  960. BOOST_CATCH_END
  961. }
  962. BOOST_TRY{
  963. if(!super::modify_(x)){
  964. unlink(x);
  965. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  966. detach_iterators(x);
  967. #endif
  968. return false;
  969. }
  970. else return true;
  971. }
  972. BOOST_CATCH(...){
  973. unlink(x);
  974. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  975. detach_iterators(x);
  976. #endif
  977. BOOST_RETHROW;
  978. }
  979. BOOST_CATCH_END
  980. }
  981. bool modify_rollback_(index_node_type* x)
  982. {
  983. std::size_t buc=find_bucket(x->value());
  984. if(in_place(x->impl(),key(x->value()),buc)){
  985. return super::modify_rollback_(x);
  986. }
  987. unlink_undo undo;
  988. unlink(x,undo);
  989. BOOST_TRY{
  990. link_info pos(buckets.at(buc));
  991. if(link_point(x->value(),pos)&&super::modify_rollback_(x)){
  992. link(x,pos);
  993. return true;
  994. }
  995. undo();
  996. return false;
  997. }
  998. BOOST_CATCH(...){
  999. undo();
  1000. BOOST_RETHROW;
  1001. }
  1002. BOOST_CATCH_END
  1003. }
  1004. bool check_rollback_(index_node_type* x)const
  1005. {
  1006. std::size_t buc=find_bucket(x->value());
  1007. return in_place(x->impl(),key(x->value()),buc)&&super::check_rollback_(x);
  1008. }
  1009. /* comparison */
  1010. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  1011. /* defect macro refers to class, not function, templates, but anyway */
  1012. template<typename K,typename H,typename P,typename S,typename T,typename C>
  1013. friend bool operator==(
  1014. const hashed_index<K,H,P,S,T,C>&,const hashed_index<K,H,P,S,T,C>& y);
  1015. #endif
  1016. bool equals(const hashed_index& x)const{return equals(x,Category());}
  1017. bool equals(const hashed_index& x,hashed_unique_tag)const
  1018. {
  1019. if(size()!=x.size())return false;
  1020. for(const_iterator it=begin(),it_end=end(),it2_end=x.end();
  1021. it!=it_end;++it){
  1022. const_iterator it2=x.find(key(*it));
  1023. if(it2==it2_end||!(*it==*it2))return false;
  1024. }
  1025. return true;
  1026. }
  1027. bool equals(const hashed_index& x,hashed_non_unique_tag)const
  1028. {
  1029. if(size()!=x.size())return false;
  1030. for(const_iterator it=begin(),it_end=end();it!=it_end;){
  1031. const_iterator it2,it2_last;
  1032. boost::tie(it2,it2_last)=x.equal_range(key(*it));
  1033. if(it2==it2_last)return false;
  1034. const_iterator it_last=make_iterator(
  1035. index_node_type::from_impl(end_of_range(it.get_node()->impl())));
  1036. if(std::distance(it,it_last)!=std::distance(it2,it2_last))return false;
  1037. /* From is_permutation code in
  1038. * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3068.pdf
  1039. */
  1040. for(;it!=it_last;++it,++it2){
  1041. if(!(*it==*it2))break;
  1042. }
  1043. if(it!=it_last){
  1044. for(const_iterator scan=it;scan!=it_last;++scan){
  1045. if(std::find(it,scan,*scan)!=scan)continue;
  1046. difference_type matches=std::count(it2,it2_last,*scan);
  1047. if(matches==0||matches!=std::count(scan,it_last,*scan))return false;
  1048. }
  1049. it=it_last;
  1050. }
  1051. }
  1052. return true;
  1053. }
  1054. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  1055. /* serialization */
  1056. template<typename Archive>
  1057. void save_(
  1058. Archive& ar,const unsigned int version,const index_saver_type& sm)const
  1059. {
  1060. ar<<core::make_nvp("position",buckets);
  1061. super::save_(ar,version,sm);
  1062. }
  1063. template<typename Archive>
  1064. void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
  1065. {
  1066. ar>>core::make_nvp("position",buckets);
  1067. super::load_(ar,version,lm);
  1068. }
  1069. #endif
  1070. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  1071. /* invariant stuff */
  1072. bool invariant_()const
  1073. {
  1074. if(size()==0||begin()==end()){
  1075. if(size()!=0||begin()!=end())return false;
  1076. }
  1077. else{
  1078. size_type s0=0;
  1079. for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
  1080. if(s0!=size())return false;
  1081. size_type s1=0;
  1082. for(size_type buc=0;buc<bucket_count();++buc){
  1083. size_type ss1=0;
  1084. for(const_local_iterator it=begin(buc),it_end=end(buc);
  1085. it!=it_end;++it,++ss1){
  1086. if(find_bucket(*it)!=buc)return false;
  1087. }
  1088. if(ss1!=bucket_size(buc))return false;
  1089. s1+=ss1;
  1090. }
  1091. if(s1!=size())return false;
  1092. }
  1093. return super::invariant_();
  1094. }
  1095. /* This forwarding function eases things for the boost::mem_fn construct
  1096. * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
  1097. * final_check_invariant is already an inherited member function of index.
  1098. */
  1099. void check_invariant_()const{this->final_check_invariant_();}
  1100. #endif
  1101. private:
  1102. index_node_type* header()const{return this->final_header();}
  1103. std::size_t find_bucket(value_param_type v)const
  1104. {
  1105. return bucket(key(v));
  1106. }
  1107. struct link_info_non_unique
  1108. {
  1109. link_info_non_unique(node_impl_base_pointer pos):
  1110. first(pos),last(node_impl_base_pointer(0)){}
  1111. operator const node_impl_base_pointer&()const{return this->first;}
  1112. node_impl_base_pointer first,last;
  1113. };
  1114. typedef typename mpl::if_<
  1115. is_same<Category,hashed_unique_tag>,
  1116. node_impl_base_pointer,
  1117. link_info_non_unique
  1118. >::type link_info;
  1119. bool link_point(value_param_type v,link_info& pos)
  1120. {
  1121. return link_point(v,pos,Category());
  1122. }
  1123. bool link_point(
  1124. value_param_type v,node_impl_base_pointer& pos,hashed_unique_tag)
  1125. {
  1126. for(node_impl_pointer x=pos->prior();x!=node_impl_pointer(0);
  1127. x=node_alg::after_local(x)){
  1128. if(eq_(key(v),key(index_node_type::from_impl(x)->value()))){
  1129. pos=node_impl_type::base_pointer_from(x);
  1130. return false;
  1131. }
  1132. }
  1133. return true;
  1134. }
  1135. bool link_point(
  1136. value_param_type v,link_info_non_unique& pos,hashed_non_unique_tag)
  1137. {
  1138. for(node_impl_pointer x=pos.first->prior();x!=node_impl_pointer(0);
  1139. x=node_alg::next_to_inspect(x)){
  1140. if(eq_(key(v),key(index_node_type::from_impl(x)->value()))){
  1141. pos.first=node_impl_type::base_pointer_from(x);
  1142. pos.last=node_impl_type::base_pointer_from(last_of_range(x));
  1143. return true;
  1144. }
  1145. }
  1146. return true;
  1147. }
  1148. node_impl_pointer last_of_range(node_impl_pointer x)const
  1149. {
  1150. return last_of_range(x,Category());
  1151. }
  1152. node_impl_pointer last_of_range(node_impl_pointer x,hashed_unique_tag)const
  1153. {
  1154. return x;
  1155. }
  1156. node_impl_pointer last_of_range(
  1157. node_impl_pointer x,hashed_non_unique_tag)const
  1158. {
  1159. node_impl_base_pointer y=x->next();
  1160. node_impl_pointer z=y->prior();
  1161. if(z==x){ /* range of size 1 or 2 */
  1162. node_impl_pointer yy=node_impl_type::pointer_from(y);
  1163. return
  1164. eq_(
  1165. key(index_node_type::from_impl(x)->value()),
  1166. key(index_node_type::from_impl(yy)->value()))?yy:x;
  1167. }
  1168. else if(z->prior()==x) /* last of bucket */
  1169. return x;
  1170. else /* group of size>2 */
  1171. return z;
  1172. }
  1173. node_impl_pointer end_of_range(node_impl_pointer x)const
  1174. {
  1175. return end_of_range(x,Category());
  1176. }
  1177. node_impl_pointer end_of_range(node_impl_pointer x,hashed_unique_tag)const
  1178. {
  1179. return node_alg::after(last_of_range(x));
  1180. }
  1181. node_impl_pointer end_of_range(
  1182. node_impl_pointer x,hashed_non_unique_tag)const
  1183. {
  1184. node_impl_base_pointer y=x->next();
  1185. node_impl_pointer z=y->prior();
  1186. if(z==x){ /* range of size 1 or 2 */
  1187. node_impl_pointer yy=node_impl_type::pointer_from(y);
  1188. if(!eq_(
  1189. key(index_node_type::from_impl(x)->value()),
  1190. key(index_node_type::from_impl(yy)->value())))yy=x;
  1191. return yy->next()->prior()==yy?
  1192. node_impl_type::pointer_from(yy->next()):
  1193. yy->next()->prior();
  1194. }
  1195. else if(z->prior()==x) /* last of bucket */
  1196. return z;
  1197. else /* group of size>2 */
  1198. return z->next()->prior()==z?
  1199. node_impl_type::pointer_from(z->next()):
  1200. z->next()->prior();
  1201. }
  1202. void link(index_node_type* x,const link_info& pos)
  1203. {
  1204. link(x,pos,Category());
  1205. }
  1206. void link(index_node_type* x,node_impl_base_pointer pos,hashed_unique_tag)
  1207. {
  1208. node_alg::link(x->impl(),pos,header()->impl());
  1209. }
  1210. void link(
  1211. index_node_type* x,const link_info_non_unique& pos,hashed_non_unique_tag)
  1212. {
  1213. if(pos.last==node_impl_base_pointer(0)){
  1214. node_alg::link(x->impl(),pos.first,header()->impl());
  1215. }
  1216. else{
  1217. node_alg::link(
  1218. x->impl(),
  1219. node_impl_type::pointer_from(pos.first),
  1220. node_impl_type::pointer_from(pos.last));
  1221. }
  1222. }
  1223. void unlink(index_node_type* x)
  1224. {
  1225. node_alg::unlink(x->impl());
  1226. }
  1227. typedef typename node_alg::unlink_undo unlink_undo;
  1228. void unlink(index_node_type* x,unlink_undo& undo)
  1229. {
  1230. node_alg::unlink(x->impl(),undo);
  1231. }
  1232. void calculate_max_load()
  1233. {
  1234. float fml=mlf*static_cast<float>(bucket_count());
  1235. max_load=(std::numeric_limits<size_type>::max)();
  1236. if(max_load>fml)max_load=static_cast<size_type>(fml);
  1237. }
  1238. void reserve_for_insert(size_type n)
  1239. {
  1240. if(n>max_load){
  1241. size_type bc =(std::numeric_limits<size_type>::max)();
  1242. float fbc=1.0f+static_cast<float>(n)/mlf;
  1243. if(bc>fbc)bc =static_cast<size_type>(fbc);
  1244. unchecked_rehash(bc);
  1245. }
  1246. }
  1247. void unchecked_rehash(size_type n){unchecked_rehash(n,Category());}
  1248. void unchecked_rehash(size_type n,hashed_unique_tag)
  1249. {
  1250. node_impl_type cpy_end_node;
  1251. node_impl_pointer cpy_end=node_impl_pointer(&cpy_end_node),
  1252. end_=header()->impl();
  1253. bucket_array_type buckets_cpy(get_allocator(),cpy_end,n);
  1254. if(size()!=0){
  1255. auto_space<
  1256. std::size_t,allocator_type> hashes(get_allocator(),size());
  1257. auto_space<
  1258. node_impl_pointer,allocator_type> node_ptrs(get_allocator(),size());
  1259. std::size_t i=0,size_=size();
  1260. bool within_bucket=false;
  1261. BOOST_TRY{
  1262. for(;i!=size_;++i){
  1263. node_impl_pointer x=end_->prior();
  1264. /* only this can possibly throw */
  1265. std::size_t h=hash_(key(index_node_type::from_impl(x)->value()));
  1266. hashes.data()[i]=h;
  1267. node_ptrs.data()[i]=x;
  1268. within_bucket=!node_alg::unlink_last(end_);
  1269. node_alg::link(x,buckets_cpy.at(buckets_cpy.position(h)),cpy_end);
  1270. }
  1271. }
  1272. BOOST_CATCH(...){
  1273. if(i!=0){
  1274. std::size_t prev_buc=buckets.position(hashes.data()[i-1]);
  1275. if(!within_bucket)prev_buc=~prev_buc;
  1276. for(std::size_t j=i;j--;){
  1277. std::size_t buc=buckets.position(hashes.data()[j]);
  1278. node_impl_pointer x=node_ptrs.data()[j];
  1279. if(buc==prev_buc)node_alg::append(x,end_);
  1280. else node_alg::link(x,buckets.at(buc),end_);
  1281. prev_buc=buc;
  1282. }
  1283. }
  1284. BOOST_RETHROW;
  1285. }
  1286. BOOST_CATCH_END
  1287. }
  1288. end_->prior()=cpy_end->prior()!=cpy_end?cpy_end->prior():end_;
  1289. end_->next()=cpy_end->next();
  1290. end_->prior()->next()->prior()=end_->next()->prior()->prior()=end_;
  1291. buckets.swap(buckets_cpy);
  1292. calculate_max_load();
  1293. }
  1294. void unchecked_rehash(size_type n,hashed_non_unique_tag)
  1295. {
  1296. node_impl_type cpy_end_node;
  1297. node_impl_pointer cpy_end=node_impl_pointer(&cpy_end_node),
  1298. end_=header()->impl();
  1299. bucket_array_type buckets_cpy(get_allocator(),cpy_end,n);
  1300. if(size()!=0){
  1301. auto_space<
  1302. std::size_t,allocator_type> hashes(get_allocator(),size());
  1303. auto_space<
  1304. node_impl_pointer,allocator_type> node_ptrs(get_allocator(),size());
  1305. std::size_t i=0;
  1306. bool within_bucket=false;
  1307. BOOST_TRY{
  1308. for(;;++i){
  1309. node_impl_pointer x=end_->prior();
  1310. if(x==end_)break;
  1311. /* only this can possibly throw */
  1312. std::size_t h=hash_(key(index_node_type::from_impl(x)->value()));
  1313. hashes.data()[i]=h;
  1314. node_ptrs.data()[i]=x;
  1315. std::pair<node_impl_pointer,bool> p=
  1316. node_alg::unlink_last_group(end_);
  1317. node_alg::link_range(
  1318. p.first,x,buckets_cpy.at(buckets_cpy.position(h)),cpy_end);
  1319. within_bucket=!(p.second);
  1320. }
  1321. }
  1322. BOOST_CATCH(...){
  1323. if(i!=0){
  1324. std::size_t prev_buc=buckets.position(hashes.data()[i-1]);
  1325. if(!within_bucket)prev_buc=~prev_buc;
  1326. for(std::size_t j=i;j--;){
  1327. std::size_t buc=buckets.position(hashes.data()[j]);
  1328. node_impl_pointer x=node_ptrs.data()[j],
  1329. y=
  1330. x->prior()->next()!=node_impl_type::base_pointer_from(x)&&
  1331. x->prior()->next()->prior()!=x?
  1332. node_impl_type::pointer_from(x->prior()->next()):x;
  1333. node_alg::unlink_range(y,x);
  1334. if(buc==prev_buc)node_alg::append_range(y,x,end_);
  1335. else node_alg::link_range(y,x,buckets.at(buc),end_);
  1336. prev_buc=buc;
  1337. }
  1338. }
  1339. BOOST_RETHROW;
  1340. }
  1341. BOOST_CATCH_END
  1342. }
  1343. end_->prior()=cpy_end->prior()!=cpy_end?cpy_end->prior():end_;
  1344. end_->next()=cpy_end->next();
  1345. end_->prior()->next()->prior()=end_->next()->prior()->prior()=end_;
  1346. buckets.swap(buckets_cpy);
  1347. calculate_max_load();
  1348. }
  1349. bool in_place(node_impl_pointer x,key_param_type k,std::size_t buc)const
  1350. {
  1351. return in_place(x,k,buc,Category());
  1352. }
  1353. bool in_place(
  1354. node_impl_pointer x,key_param_type k,std::size_t buc,
  1355. hashed_unique_tag)const
  1356. {
  1357. bool found=false;
  1358. for(node_impl_pointer y=buckets.at(buc)->prior();
  1359. y!=node_impl_pointer(0);y=node_alg::after_local(y)){
  1360. if(y==x)found=true;
  1361. else if(eq_(k,key(index_node_type::from_impl(y)->value())))return false;
  1362. }
  1363. return found;
  1364. }
  1365. bool in_place(
  1366. node_impl_pointer x,key_param_type k,std::size_t buc,
  1367. hashed_non_unique_tag)const
  1368. {
  1369. bool found=false;
  1370. int range_size=0;
  1371. for(node_impl_pointer y=buckets.at(buc)->prior();y!=node_impl_pointer(0);){
  1372. if(node_alg::is_first_of_group(y)){ /* group of 3 or more */
  1373. if(y==x){
  1374. /* in place <-> equal to some other member of the group */
  1375. return eq_(
  1376. k,
  1377. key(index_node_type::from_impl(
  1378. node_impl_type::pointer_from(y->next()))->value()));
  1379. }
  1380. else{
  1381. node_impl_pointer z=
  1382. node_alg::after_local(y->next()->prior()); /* end of range */
  1383. if(eq_(k,key(index_node_type::from_impl(y)->value()))){
  1384. if(found)return false; /* x lies outside */
  1385. do{
  1386. if(y==x)return true;
  1387. y=node_alg::after_local(y);
  1388. }while(y!=z);
  1389. return false; /* x not found */
  1390. }
  1391. else{
  1392. if(range_size==1&&!found)return false;
  1393. if(range_size==2)return found;
  1394. range_size=0;
  1395. y=z; /* skip range (and potentially x, too, which is fine) */
  1396. }
  1397. }
  1398. }
  1399. else{ /* group of 1 or 2 */
  1400. if(y==x){
  1401. if(range_size==1)return true;
  1402. range_size=1;
  1403. found=true;
  1404. }
  1405. else if(eq_(k,key(index_node_type::from_impl(y)->value()))){
  1406. if(range_size==0&&found)return false;
  1407. if(range_size==1&&!found)return false;
  1408. if(range_size==2)return false;
  1409. ++range_size;
  1410. }
  1411. else{
  1412. if(range_size==1&&!found)return false;
  1413. if(range_size==2)return found;
  1414. range_size=0;
  1415. }
  1416. y=node_alg::after_local(y);
  1417. }
  1418. }
  1419. return found;
  1420. }
  1421. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  1422. void detach_iterators(index_node_type* x)
  1423. {
  1424. iterator it=make_iterator(x);
  1425. safe_mode::detach_equivalent_iterators(it);
  1426. }
  1427. template<typename Dst>
  1428. void transfer_iterators(Dst& dst,index_node_type* x)
  1429. {
  1430. iterator it=make_iterator(x);
  1431. safe_mode::transfer_equivalent_iterators(dst,it);
  1432. }
  1433. #endif
  1434. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1435. std::pair<iterator,bool> emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1436. {
  1437. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  1438. std::pair<final_node_type*,bool>p=
  1439. this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1440. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  1441. }
  1442. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1443. iterator emplace_hint_impl(
  1444. iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1445. {
  1446. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  1447. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  1448. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  1449. std::pair<final_node_type*,bool>p=
  1450. this->final_emplace_hint_(
  1451. static_cast<final_node_type*>(position.get_node()),
  1452. BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1453. return make_iterator(p.first);
  1454. }
  1455. template<
  1456. typename CompatibleHash,typename CompatiblePred
  1457. >
  1458. iterator find(
  1459. const key_type& k,
  1460. const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
  1461. {
  1462. return find(k,hash,eq,mpl::false_());
  1463. }
  1464. template<
  1465. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  1466. >
  1467. iterator find(
  1468. const CompatibleKey& k,
  1469. const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
  1470. {
  1471. std::size_t buc=buckets.position(hash(k));
  1472. for(node_impl_pointer x=buckets.at(buc)->prior();
  1473. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  1474. if(eq(k,key(index_node_type::from_impl(x)->value()))){
  1475. return make_iterator(index_node_type::from_impl(x));
  1476. }
  1477. }
  1478. return end();
  1479. }
  1480. template<
  1481. typename CompatibleHash,typename CompatiblePred
  1482. >
  1483. size_type count(
  1484. const key_type& k,
  1485. const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
  1486. {
  1487. return count(k,hash,eq,mpl::false_());
  1488. }
  1489. template<
  1490. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  1491. >
  1492. size_type count(
  1493. const CompatibleKey& k,
  1494. const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
  1495. {
  1496. std::size_t buc=buckets.position(hash(k));
  1497. for(node_impl_pointer x=buckets.at(buc)->prior();
  1498. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  1499. if(eq(k,key(index_node_type::from_impl(x)->value()))){
  1500. size_type res=0;
  1501. node_impl_pointer y=end_of_range(x);
  1502. do{
  1503. ++res;
  1504. x=node_alg::after(x);
  1505. }while(x!=y);
  1506. return res;
  1507. }
  1508. }
  1509. return 0;
  1510. }
  1511. template<
  1512. typename CompatibleHash,typename CompatiblePred
  1513. >
  1514. std::pair<iterator,iterator> equal_range(
  1515. const key_type& k,
  1516. const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
  1517. {
  1518. return equal_range(k,hash,eq,mpl::false_());
  1519. }
  1520. template<
  1521. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  1522. >
  1523. std::pair<iterator,iterator> equal_range(
  1524. const CompatibleKey& k,
  1525. const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
  1526. {
  1527. std::size_t buc=buckets.position(hash(k));
  1528. for(node_impl_pointer x=buckets.at(buc)->prior();
  1529. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  1530. if(eq(k,key(index_node_type::from_impl(x)->value()))){
  1531. return std::pair<iterator,iterator>(
  1532. make_iterator(index_node_type::from_impl(x)),
  1533. make_iterator(index_node_type::from_impl(end_of_range(x))));
  1534. }
  1535. }
  1536. return std::pair<iterator,iterator>(end(),end());
  1537. }
  1538. key_from_value key;
  1539. hasher hash_;
  1540. key_equal eq_;
  1541. bucket_array_type buckets;
  1542. float mlf;
  1543. size_type max_load;
  1544. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  1545. safe_container safe;
  1546. #endif
  1547. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  1548. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  1549. #pragma parse_mfunc_templ reset
  1550. #endif
  1551. };
  1552. #if defined(BOOST_MSVC)
  1553. #pragma warning(pop) /* C4355 */
  1554. #endif
  1555. /* comparison */
  1556. template<
  1557. typename KeyFromValue,typename Hash,typename Pred,
  1558. typename SuperMeta,typename TagList,typename Category
  1559. >
  1560. bool operator==(
  1561. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1562. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1563. {
  1564. return x.equals(y);
  1565. }
  1566. template<
  1567. typename KeyFromValue,typename Hash,typename Pred,
  1568. typename SuperMeta,typename TagList,typename Category
  1569. >
  1570. bool operator!=(
  1571. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1572. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1573. {
  1574. return !(x==y);
  1575. }
  1576. /* specialized algorithms */
  1577. template<
  1578. typename KeyFromValue,typename Hash,typename Pred,
  1579. typename SuperMeta,typename TagList,typename Category
  1580. >
  1581. void swap(
  1582. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1583. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1584. {
  1585. x.swap(y);
  1586. }
  1587. } /* namespace multi_index::detail */
  1588. /* hashed index specifiers */
  1589. template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1590. struct hashed_unique
  1591. {
  1592. typedef typename detail::hashed_index_args<
  1593. Arg1,Arg2,Arg3,Arg4> index_args;
  1594. typedef typename index_args::tag_list_type::type tag_list_type;
  1595. typedef typename index_args::key_from_value_type key_from_value_type;
  1596. typedef typename index_args::hash_type hash_type;
  1597. typedef typename index_args::pred_type pred_type;
  1598. template<typename Super>
  1599. struct node_class
  1600. {
  1601. typedef detail::hashed_index_node<Super> type;
  1602. };
  1603. template<typename SuperMeta>
  1604. struct index_class
  1605. {
  1606. typedef detail::hashed_index<
  1607. key_from_value_type,hash_type,pred_type,
  1608. SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
  1609. };
  1610. };
  1611. template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1612. struct hashed_non_unique
  1613. {
  1614. typedef typename detail::hashed_index_args<
  1615. Arg1,Arg2,Arg3,Arg4> index_args;
  1616. typedef typename index_args::tag_list_type::type tag_list_type;
  1617. typedef typename index_args::key_from_value_type key_from_value_type;
  1618. typedef typename index_args::hash_type hash_type;
  1619. typedef typename index_args::pred_type pred_type;
  1620. template<typename Super>
  1621. struct node_class
  1622. {
  1623. typedef detail::hashed_index_node<Super> type;
  1624. };
  1625. template<typename SuperMeta>
  1626. struct index_class
  1627. {
  1628. typedef detail::hashed_index<
  1629. key_from_value_type,hash_type,pred_type,
  1630. SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
  1631. };
  1632. };
  1633. } /* namespace multi_index */
  1634. } /* namespace boost */
  1635. /* Boost.Foreach compatibility */
  1636. namespace boost{
  1637. namespace foreach{
  1638. template<typename>
  1639. struct is_noncopyable;
  1640. template<
  1641. typename KeyFromValue,typename Hash,typename Pred,
  1642. typename SuperMeta,typename TagList,typename Category
  1643. >
  1644. struct is_noncopyable<boost::multi_index::detail::hashed_index<
  1645. KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>
  1646. >:boost::mpl::true_{};
  1647. }
  1648. }
  1649. #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  1650. #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF
  1651. #endif