hashed_index.hpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. /* Copyright 2003-2013 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)&&(_MSC_VER>=1200)
  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/detail/allocator_utilities.hpp>
  17. #include <boost/detail/no_exceptions_support.hpp>
  18. #include <boost/detail/workaround.hpp>
  19. #include <boost/foreach_fwd.hpp>
  20. #include <boost/limits.hpp>
  21. #include <boost/move/core.hpp>
  22. #include <boost/mpl/bool.hpp>
  23. #include <boost/mpl/push_front.hpp>
  24. #include <boost/multi_index/detail/access_specifier.hpp>
  25. #include <boost/multi_index/detail/auto_space.hpp>
  26. #include <boost/multi_index/detail/bucket_array.hpp>
  27. #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
  28. #include <boost/multi_index/detail/hash_index_iterator.hpp>
  29. #include <boost/multi_index/detail/index_node_base.hpp>
  30. #include <boost/multi_index/detail/modify_key_adaptor.hpp>
  31. #include <boost/multi_index/detail/safe_ctr_proxy.hpp>
  32. #include <boost/multi_index/detail/safe_mode.hpp>
  33. #include <boost/multi_index/detail/scope_guard.hpp>
  34. #include <boost/multi_index/detail/vartempl_support.hpp>
  35. #include <boost/multi_index/hashed_index_fwd.hpp>
  36. #include <boost/tuple/tuple.hpp>
  37. #include <cstddef>
  38. #include <functional>
  39. #include <utility>
  40. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  41. #include <initializer_list>
  42. #endif
  43. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  44. #include <boost/serialization/nvp.hpp>
  45. #endif
  46. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  47. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x) \
  48. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  49. detail::make_obj_guard(x,&hashed_index::check_invariant_); \
  50. BOOST_JOIN(check_invariant_,__LINE__).touch();
  51. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT \
  52. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(*this)
  53. #else
  54. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x)
  55. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  56. #endif
  57. namespace boost{
  58. namespace multi_index{
  59. namespace detail{
  60. /* hashed_index adds a layer of hashed indexing to a given Super */
  61. /* Most of the implementation of unique and non-unique indices is
  62. * shared. We tell from one another on instantiation time by using
  63. * these tags.
  64. */
  65. struct hashed_unique_tag{};
  66. struct hashed_non_unique_tag{};
  67. template<
  68. typename KeyFromValue,typename Hash,typename Pred,
  69. typename SuperMeta,typename TagList,typename Category
  70. >
  71. class hashed_index:
  72. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
  73. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  74. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  75. ,public safe_ctr_proxy_impl<
  76. hashed_index_iterator<
  77. hashed_index_node<typename SuperMeta::type::node_type>,
  78. bucket_array<typename SuperMeta::type::final_allocator_type> >,
  79. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
  80. #else
  81. ,public safe_mode::safe_container<
  82. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
  83. #endif
  84. #endif
  85. {
  86. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  87. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  88. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  89. * lifetime of const references bound to temporaries --precisely what
  90. * scopeguards are.
  91. */
  92. #pragma parse_mfunc_templ off
  93. #endif
  94. typedef typename SuperMeta::type super;
  95. protected:
  96. typedef hashed_index_node<
  97. typename super::node_type> node_type;
  98. private:
  99. typedef typename node_type::impl_type node_impl_type;
  100. typedef typename node_impl_type::pointer node_impl_pointer;
  101. typedef bucket_array<
  102. typename super::final_allocator_type> bucket_array_type;
  103. public:
  104. /* types */
  105. typedef typename KeyFromValue::result_type key_type;
  106. typedef typename node_type::value_type value_type;
  107. typedef KeyFromValue key_from_value;
  108. typedef Hash hasher;
  109. typedef Pred key_equal;
  110. typedef tuple<std::size_t,
  111. key_from_value,hasher,key_equal> ctor_args;
  112. typedef typename super::final_allocator_type allocator_type;
  113. typedef typename allocator_type::pointer pointer;
  114. typedef typename allocator_type::const_pointer const_pointer;
  115. typedef typename allocator_type::reference reference;
  116. typedef typename allocator_type::const_reference const_reference;
  117. typedef std::size_t size_type;
  118. typedef std::ptrdiff_t difference_type;
  119. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  120. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  121. typedef safe_mode::safe_iterator<
  122. hashed_index_iterator<
  123. node_type,bucket_array_type>,
  124. safe_ctr_proxy<
  125. hashed_index_iterator<
  126. node_type,bucket_array_type> > > iterator;
  127. #else
  128. typedef safe_mode::safe_iterator<
  129. hashed_index_iterator<
  130. node_type,bucket_array_type>,
  131. hashed_index> iterator;
  132. #endif
  133. #else
  134. typedef hashed_index_iterator<
  135. node_type,bucket_array_type> iterator;
  136. #endif
  137. typedef iterator const_iterator;
  138. typedef iterator local_iterator;
  139. typedef const_iterator const_local_iterator;
  140. typedef TagList tag_list;
  141. protected:
  142. typedef typename super::final_node_type final_node_type;
  143. typedef tuples::cons<
  144. ctor_args,
  145. typename super::ctor_args_list> ctor_args_list;
  146. typedef typename mpl::push_front<
  147. typename super::index_type_list,
  148. hashed_index>::type index_type_list;
  149. typedef typename mpl::push_front<
  150. typename super::iterator_type_list,
  151. iterator>::type iterator_type_list;
  152. typedef typename mpl::push_front<
  153. typename super::const_iterator_type_list,
  154. const_iterator>::type const_iterator_type_list;
  155. typedef typename super::copy_map_type copy_map_type;
  156. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  157. typedef typename super::index_saver_type index_saver_type;
  158. typedef typename super::index_loader_type index_loader_type;
  159. #endif
  160. private:
  161. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  162. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  163. typedef safe_ctr_proxy_impl<
  164. hashed_index_iterator<
  165. node_type,bucket_array_type>,
  166. hashed_index> safe_super;
  167. #else
  168. typedef safe_mode::safe_container<
  169. hashed_index> safe_super;
  170. #endif
  171. #endif
  172. typedef typename call_traits<value_type>::param_type value_param_type;
  173. typedef typename call_traits<
  174. key_type>::param_type key_param_type;
  175. /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
  176. * expansion.
  177. */
  178. typedef std::pair<iterator,bool> emplace_return_type;
  179. public:
  180. /* construct/destroy/copy
  181. * Default and copy ctors are in the protected section as indices are
  182. * not supposed to be created on their own. No range ctor either.
  183. */
  184. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  185. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  186. {
  187. this->final()=x.final();
  188. return *this;
  189. }
  190. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  191. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  192. std::initializer_list<value_type> list)
  193. {
  194. this->final()=list;
  195. return *this;
  196. }
  197. #endif
  198. allocator_type get_allocator()const
  199. {
  200. return this->final().get_allocator();
  201. }
  202. /* size and capacity */
  203. bool empty()const{return this->final_empty_();}
  204. size_type size()const{return this->final_size_();}
  205. size_type max_size()const{return this->final_max_size_();}
  206. /* iterators */
  207. iterator begin()
  208. {
  209. return make_iterator(
  210. node_type::from_impl(buckets.at(first_bucket)->next()));
  211. }
  212. const_iterator begin()const
  213. {
  214. return make_iterator(
  215. node_type::from_impl(buckets.at(first_bucket)->next()));
  216. }
  217. iterator end(){return make_iterator(header());}
  218. const_iterator end()const{return make_iterator(header());}
  219. const_iterator cbegin()const{return begin();}
  220. const_iterator cend()const{return end();}
  221. iterator iterator_to(const value_type& x)
  222. {
  223. return make_iterator(node_from_value<node_type>(&x));
  224. }
  225. const_iterator iterator_to(const value_type& x)const
  226. {
  227. return make_iterator(node_from_value<node_type>(&x));
  228. }
  229. /* modifiers */
  230. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
  231. emplace_return_type,emplace,emplace_impl)
  232. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
  233. iterator,emplace_hint,emplace_hint_impl,iterator,position)
  234. std::pair<iterator,bool> insert(const value_type& x)
  235. {
  236. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  237. std::pair<final_node_type*,bool> p=this->final_insert_(x);
  238. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  239. }
  240. std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
  241. {
  242. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  243. std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
  244. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  245. }
  246. iterator insert(iterator position,const value_type& x)
  247. {
  248. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  249. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  250. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  251. std::pair<final_node_type*,bool> p=this->final_insert_(
  252. x,static_cast<final_node_type*>(position.get_node()));
  253. return make_iterator(p.first);
  254. }
  255. iterator insert(iterator position,BOOST_RV_REF(value_type) x)
  256. {
  257. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  258. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  259. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  260. std::pair<final_node_type*,bool> p=this->final_insert_rv_(
  261. x,static_cast<final_node_type*>(position.get_node()));
  262. return make_iterator(p.first);
  263. }
  264. template<typename InputIterator>
  265. void insert(InputIterator first,InputIterator last)
  266. {
  267. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  268. for(;first!=last;++first)this->final_insert_ref_(*first);
  269. }
  270. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  271. void insert(std::initializer_list<value_type> list)
  272. {
  273. insert(list.begin(),list.end());
  274. }
  275. #endif
  276. iterator erase(iterator position)
  277. {
  278. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  279. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  280. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  281. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  282. this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
  283. return position;
  284. }
  285. size_type erase(key_param_type k)
  286. {
  287. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  288. size_type s=0;
  289. std::size_t buc=buckets.position(hash_(k));
  290. node_impl_pointer x=buckets.at(buc);
  291. node_impl_pointer y=x->next();
  292. while(y!=x){
  293. if(eq_(k,key(node_type::from_impl(y)->value()))){
  294. bool b;
  295. do{
  296. node_impl_pointer z=y->next();
  297. b=z!=x&&eq_(
  298. key(node_type::from_impl(y)->value()),
  299. key(node_type::from_impl(z)->value()));
  300. this->final_erase_(
  301. static_cast<final_node_type*>(node_type::from_impl(y)));
  302. y=z;
  303. ++s;
  304. }while(b);
  305. break;
  306. }
  307. y=y->next();
  308. }
  309. return s;
  310. }
  311. iterator erase(iterator first,iterator last)
  312. {
  313. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  314. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  315. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  316. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  317. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  318. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  319. while(first!=last){
  320. first=erase(first);
  321. }
  322. return first;
  323. }
  324. bool replace(iterator position,const value_type& x)
  325. {
  326. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  327. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  328. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  329. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  330. return this->final_replace_(
  331. x,static_cast<final_node_type*>(position.get_node()));
  332. }
  333. bool replace(iterator position,BOOST_RV_REF(value_type) x)
  334. {
  335. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  336. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  337. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  338. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  339. return this->final_replace_rv_(
  340. x,static_cast<final_node_type*>(position.get_node()));
  341. }
  342. template<typename Modifier>
  343. bool modify(iterator position,Modifier mod)
  344. {
  345. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  346. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  347. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  348. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  349. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  350. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  351. * this is not added. Left it for all compilers as it does no
  352. * harm.
  353. */
  354. position.detach();
  355. #endif
  356. return this->final_modify_(
  357. mod,static_cast<final_node_type*>(position.get_node()));
  358. }
  359. template<typename Modifier,typename Rollback>
  360. bool modify(iterator position,Modifier mod,Rollback back)
  361. {
  362. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  363. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  364. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  365. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  366. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  367. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  368. * this is not added. Left it for all compilers as it does no
  369. * harm.
  370. */
  371. position.detach();
  372. #endif
  373. return this->final_modify_(
  374. mod,back,static_cast<final_node_type*>(position.get_node()));
  375. }
  376. template<typename Modifier>
  377. bool modify_key(iterator position,Modifier mod)
  378. {
  379. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  380. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  381. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  382. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  383. return modify(
  384. position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
  385. }
  386. template<typename Modifier,typename Rollback>
  387. bool modify_key(iterator position,Modifier mod,Rollback back)
  388. {
  389. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  390. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  391. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  392. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  393. return modify(
  394. position,
  395. modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
  396. modify_key_adaptor<Rollback,value_type,KeyFromValue>(back,key));
  397. }
  398. void clear()
  399. {
  400. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  401. this->final_clear_();
  402. }
  403. void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  404. {
  405. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  406. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x);
  407. this->final_swap_(x.final());
  408. }
  409. /* observers */
  410. key_from_value key_extractor()const{return key;}
  411. hasher hash_function()const{return hash_;}
  412. key_equal key_eq()const{return eq_;}
  413. /* lookup */
  414. /* Internally, these ops rely on const_iterator being the same
  415. * type as iterator.
  416. */
  417. template<typename CompatibleKey>
  418. iterator find(const CompatibleKey& k)const
  419. {
  420. return find(k,hash_,eq_);
  421. }
  422. template<
  423. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  424. >
  425. iterator find(
  426. const CompatibleKey& k,
  427. const CompatibleHash& hash,const CompatiblePred& eq)const
  428. {
  429. std::size_t buc=buckets.position(hash(k));
  430. node_impl_pointer x=buckets.at(buc);
  431. node_impl_pointer y=x->next();
  432. while(y!=x){
  433. if(eq(k,key(node_type::from_impl(y)->value()))){
  434. return make_iterator(node_type::from_impl(y));
  435. }
  436. y=y->next();
  437. }
  438. return end();
  439. }
  440. template<typename CompatibleKey>
  441. size_type count(const CompatibleKey& k)const
  442. {
  443. return count(k,hash_,eq_);
  444. }
  445. template<
  446. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  447. >
  448. size_type count(
  449. const CompatibleKey& k,
  450. const CompatibleHash& hash,const CompatiblePred& eq)const
  451. {
  452. size_type res=0;
  453. std::size_t buc=buckets.position(hash(k));
  454. node_impl_pointer x=buckets.at(buc);
  455. node_impl_pointer y=x->next();
  456. while(y!=x){
  457. if(eq(k,key(node_type::from_impl(y)->value()))){
  458. do{
  459. ++res;
  460. y=y->next();
  461. }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
  462. break;
  463. }
  464. y=y->next();
  465. }
  466. return res;
  467. }
  468. template<typename CompatibleKey>
  469. std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
  470. {
  471. return equal_range(k,hash_,eq_);
  472. }
  473. template<
  474. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  475. >
  476. std::pair<iterator,iterator> equal_range(
  477. const CompatibleKey& k,
  478. const CompatibleHash& hash,const CompatiblePred& eq)const
  479. {
  480. std::size_t buc=buckets.position(hash(k));
  481. node_impl_pointer x=buckets.at(buc);
  482. node_impl_pointer y=x->next();
  483. while(y!=x){
  484. if(eq(k,key(node_type::from_impl(y)->value()))){
  485. node_impl_pointer y0=y;
  486. do{
  487. y=y->next();
  488. }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
  489. if(y==x){
  490. do{
  491. ++y;
  492. }while(y==y->next());
  493. y=y->next();
  494. }
  495. return std::pair<iterator,iterator>(
  496. make_iterator(node_type::from_impl(y0)),
  497. make_iterator(node_type::from_impl(y)));
  498. }
  499. y=y->next();
  500. }
  501. return std::pair<iterator,iterator>(end(),end());
  502. }
  503. /* bucket interface */
  504. size_type bucket_count()const{return buckets.size();}
  505. size_type max_bucket_count()const{return static_cast<size_type>(-1);}
  506. size_type bucket_size(size_type n)const
  507. {
  508. size_type res=0;
  509. node_impl_pointer x=buckets.at(n);
  510. node_impl_pointer y=x->next();
  511. while(y!=x){
  512. ++res;
  513. y=y->next();
  514. }
  515. return res;
  516. }
  517. size_type bucket(key_param_type k)const
  518. {
  519. return buckets.position(hash_(k));
  520. }
  521. local_iterator begin(size_type n)
  522. {
  523. return const_cast<const hashed_index*>(this)->begin(n);
  524. }
  525. const_local_iterator begin(size_type n)const
  526. {
  527. node_impl_pointer x=buckets.at(n);
  528. node_impl_pointer y=x->next();
  529. if(y==x)return end();
  530. return make_iterator(node_type::from_impl(y));
  531. }
  532. local_iterator end(size_type n)
  533. {
  534. return const_cast<const hashed_index*>(this)->end(n);
  535. }
  536. const_local_iterator end(size_type n)const
  537. {
  538. node_impl_pointer x=buckets.at(n);
  539. if(x==x->next())return end();
  540. do{
  541. ++x;
  542. }while(x==x->next());
  543. return make_iterator(node_type::from_impl(x->next()));
  544. }
  545. const_local_iterator cbegin(size_type n)const{return begin(n);}
  546. const_local_iterator cend(size_type n)const{return end(n);}
  547. local_iterator local_iterator_to(const value_type& x)
  548. {
  549. return make_iterator(node_from_value<node_type>(&x));
  550. }
  551. const_local_iterator local_iterator_to(const value_type& x)const
  552. {
  553. return make_iterator(node_from_value<node_type>(&x));
  554. }
  555. /* hash policy */
  556. float load_factor()const{return static_cast<float>(size())/bucket_count();}
  557. float max_load_factor()const{return mlf;}
  558. void max_load_factor(float z){mlf=z;calculate_max_load();}
  559. void rehash(size_type n)
  560. {
  561. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  562. if(size()<max_load&&n<=bucket_count())return;
  563. size_type bc =(std::numeric_limits<size_type>::max)();
  564. float fbc=static_cast<float>(1+size()/mlf);
  565. if(bc>fbc){
  566. bc=static_cast<size_type>(fbc);
  567. if(bc<n)bc=n;
  568. }
  569. unchecked_rehash(bc);
  570. }
  571. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  572. hashed_index(const ctor_args_list& args_list,const allocator_type& al):
  573. super(args_list.get_tail(),al),
  574. key(tuples::get<1>(args_list.get_head())),
  575. hash_(tuples::get<2>(args_list.get_head())),
  576. eq_(tuples::get<3>(args_list.get_head())),
  577. buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
  578. mlf(1.0f),
  579. first_bucket(buckets.size())
  580. {
  581. calculate_max_load();
  582. }
  583. hashed_index(
  584. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
  585. super(x),
  586. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  587. safe_super(),
  588. #endif
  589. key(x.key),
  590. hash_(x.hash_),
  591. eq_(x.eq_),
  592. buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
  593. mlf(x.mlf),
  594. max_load(x.max_load),
  595. first_bucket(x.first_bucket)
  596. {
  597. /* Copy ctor just takes the internal configuration objects from x. The rest
  598. * is done in subsequent call to copy_().
  599. */
  600. }
  601. hashed_index(
  602. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  603. do_not_copy_elements_tag):
  604. super(x,do_not_copy_elements_tag()),
  605. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  606. safe_super(),
  607. #endif
  608. key(x.key),
  609. hash_(x.hash_),
  610. eq_(x.eq_),
  611. buckets(x.get_allocator(),header()->impl(),0),
  612. mlf(1.0f),
  613. first_bucket(buckets.size())
  614. {
  615. calculate_max_load();
  616. }
  617. ~hashed_index()
  618. {
  619. /* the container is guaranteed to be empty by now */
  620. }
  621. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  622. iterator make_iterator(node_type* node)
  623. {
  624. return iterator(node,&buckets,this);
  625. }
  626. const_iterator make_iterator(node_type* node)const
  627. {
  628. return const_iterator(
  629. node,
  630. &const_cast<bucket_array_type&>(buckets),
  631. const_cast<hashed_index*>(this));
  632. }
  633. #else
  634. iterator make_iterator(node_type* node)
  635. {
  636. return iterator(node,&buckets);
  637. }
  638. const_iterator make_iterator(node_type* node)const
  639. {
  640. return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
  641. }
  642. #endif
  643. void copy_(
  644. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  645. const copy_map_type& map)
  646. {
  647. for(node_impl_pointer begin_org=x.buckets.begin(),
  648. begin_cpy=buckets.begin(),
  649. end_org=x.buckets.end();
  650. begin_org!=end_org;++begin_org,++begin_cpy){
  651. node_impl_pointer next_org=begin_org->next();
  652. node_impl_pointer cpy=begin_cpy;
  653. while(next_org!=begin_org){
  654. cpy->next()=
  655. static_cast<node_type*>(
  656. map.find(
  657. static_cast<final_node_type*>(
  658. node_type::from_impl(next_org))))->impl();
  659. next_org=next_org->next();
  660. cpy=cpy->next();
  661. }
  662. cpy->next()=begin_cpy;
  663. }
  664. super::copy_(x,map);
  665. }
  666. template<typename Variant>
  667. node_type* insert_(value_param_type v,node_type* x,Variant variant)
  668. {
  669. reserve(size()+1);
  670. std::size_t buc=find_bucket(v);
  671. node_impl_pointer pos=buckets.at(buc);
  672. if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
  673. node_type* res=static_cast<node_type*>(super::insert_(v,x,variant));
  674. if(res==x){
  675. link(x,pos);
  676. if(first_bucket>buc)first_bucket=buc;
  677. }
  678. return res;
  679. }
  680. template<typename Variant>
  681. node_type* insert_(
  682. value_param_type v,node_type* position,node_type* x,Variant variant)
  683. {
  684. reserve(size()+1);
  685. std::size_t buc=find_bucket(v);
  686. node_impl_pointer pos=buckets.at(buc);
  687. if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
  688. node_type* res=
  689. static_cast<node_type*>(super::insert_(v,position,x,variant));
  690. if(res==x){
  691. link(x,pos);
  692. if(first_bucket>buc)first_bucket=buc;
  693. }
  694. return res;
  695. }
  696. void erase_(node_type* x)
  697. {
  698. unlink(x);
  699. first_bucket=buckets.first_nonempty(first_bucket);
  700. super::erase_(x);
  701. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  702. detach_iterators(x);
  703. #endif
  704. }
  705. void delete_all_nodes_()
  706. {
  707. for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
  708. x!=x_end;++x){
  709. node_impl_pointer y=x->next();
  710. while(y!=x){
  711. node_impl_pointer z=y->next();
  712. this->final_delete_node_(
  713. static_cast<final_node_type*>(node_type::from_impl(y)));
  714. y=z;
  715. }
  716. }
  717. }
  718. void clear_()
  719. {
  720. super::clear_();
  721. buckets.clear();
  722. first_bucket=buckets.size();
  723. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  724. safe_super::detach_dereferenceable_iterators();
  725. #endif
  726. }
  727. void swap_(
  728. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  729. {
  730. std::swap(key,x.key);
  731. std::swap(hash_,x.hash_);
  732. std::swap(eq_,x.eq_);
  733. buckets.swap(x.buckets);
  734. std::swap(mlf,x.mlf);
  735. std::swap(max_load,x.max_load);
  736. std::swap(first_bucket,x.first_bucket);
  737. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  738. safe_super::swap(x);
  739. #endif
  740. super::swap_(x);
  741. }
  742. void swap_elements_(
  743. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  744. {
  745. buckets.swap(x.buckets);
  746. std::swap(mlf,x.mlf);
  747. std::swap(max_load,x.max_load);
  748. std::swap(first_bucket,x.first_bucket);
  749. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  750. safe_super::swap(x);
  751. #endif
  752. super::swap_elements_(x);
  753. }
  754. template<typename Variant>
  755. bool replace_(value_param_type v,node_type* x,Variant variant)
  756. {
  757. if(eq_(key(v),key(x->value()))){
  758. return super::replace_(v,x,variant);
  759. }
  760. node_impl_pointer y=prev(x);
  761. unlink_next(y);
  762. BOOST_TRY{
  763. std::size_t buc=find_bucket(v);
  764. node_impl_pointer pos=buckets.at(buc);
  765. if(link_point(v,pos,Category())&&super::replace_(v,x,variant)){
  766. link(x,pos);
  767. if(first_bucket>buc){
  768. first_bucket=buc;
  769. }
  770. else if(first_bucket<buc){
  771. first_bucket=buckets.first_nonempty(first_bucket);
  772. }
  773. return true;
  774. }
  775. link(x,y);
  776. return false;
  777. }
  778. BOOST_CATCH(...){
  779. link(x,y);
  780. BOOST_RETHROW;
  781. }
  782. BOOST_CATCH_END
  783. }
  784. bool modify_(node_type* x)
  785. {
  786. std::size_t buc;
  787. bool b;
  788. BOOST_TRY{
  789. buc=find_bucket(x->value());
  790. b=in_place(x->impl(),key(x->value()),buc,Category());
  791. }
  792. BOOST_CATCH(...){
  793. erase_(x);
  794. BOOST_RETHROW;
  795. }
  796. BOOST_CATCH_END
  797. if(!b){
  798. unlink(x);
  799. BOOST_TRY{
  800. node_impl_pointer pos=buckets.at(buc);
  801. if(!link_point(x->value(),pos,Category())){
  802. first_bucket=buckets.first_nonempty(first_bucket);
  803. super::erase_(x);
  804. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  805. detach_iterators(x);
  806. #endif
  807. return false;
  808. }
  809. link(x,pos);
  810. if(first_bucket>buc){
  811. first_bucket=buc;
  812. }
  813. else if(first_bucket<buc){
  814. first_bucket=buckets.first_nonempty(first_bucket);
  815. }
  816. }
  817. BOOST_CATCH(...){
  818. first_bucket=buckets.first_nonempty(first_bucket);
  819. super::erase_(x);
  820. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  821. detach_iterators(x);
  822. #endif
  823. BOOST_RETHROW;
  824. }
  825. BOOST_CATCH_END
  826. }
  827. BOOST_TRY{
  828. if(!super::modify_(x)){
  829. unlink(x);
  830. first_bucket=buckets.first_nonempty(first_bucket);
  831. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  832. detach_iterators(x);
  833. #endif
  834. return false;
  835. }
  836. else return true;
  837. }
  838. BOOST_CATCH(...){
  839. unlink(x);
  840. first_bucket=buckets.first_nonempty(first_bucket);
  841. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  842. detach_iterators(x);
  843. #endif
  844. BOOST_RETHROW;
  845. }
  846. BOOST_CATCH_END
  847. }
  848. bool modify_rollback_(node_type* x)
  849. {
  850. std::size_t buc=find_bucket(x->value());
  851. if(in_place(x->impl(),key(x->value()),buc,Category())){
  852. return super::modify_rollback_(x);
  853. }
  854. node_impl_pointer y=prev(x);
  855. unlink_next(y);
  856. BOOST_TRY{
  857. node_impl_pointer pos=buckets.at(buc);
  858. if(link_point(x->value(),pos,Category())&&super::modify_rollback_(x)){
  859. link(x,pos);
  860. if(first_bucket>buc){
  861. first_bucket=buc;
  862. }
  863. else if(first_bucket<buc){
  864. first_bucket=buckets.first_nonempty(first_bucket);
  865. }
  866. return true;
  867. }
  868. link(x,y);
  869. return false;
  870. }
  871. BOOST_CATCH(...){
  872. link(x,y);
  873. BOOST_RETHROW;
  874. }
  875. BOOST_CATCH_END
  876. }
  877. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  878. /* serialization */
  879. template<typename Archive>
  880. void save_(
  881. Archive& ar,const unsigned int version,const index_saver_type& sm)const
  882. {
  883. ar<<serialization::make_nvp("position",buckets);
  884. super::save_(ar,version,sm);
  885. }
  886. template<typename Archive>
  887. void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
  888. {
  889. ar>>serialization::make_nvp("position",buckets);
  890. super::load_(ar,version,lm);
  891. }
  892. #endif
  893. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  894. /* invariant stuff */
  895. bool invariant_()const
  896. {
  897. if(size()==0||begin()==end()){
  898. if(size()!=0||begin()!=end())return false;
  899. }
  900. else{
  901. size_type s0=0;
  902. for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
  903. if(s0!=size())return false;
  904. size_type s1=0;
  905. for(size_type buc=0;buc<bucket_count();++buc){
  906. size_type ss1=0;
  907. for(const_local_iterator it=begin(buc),it_end=end(buc);
  908. it!=it_end;++it,++ss1){
  909. if(find_bucket(*it)!=buc)return false;
  910. }
  911. if(ss1!=bucket_size(buc))return false;
  912. s1+=ss1;
  913. }
  914. if(s1!=size())return false;
  915. }
  916. if(first_bucket!=buckets.first_nonempty(0))return false;
  917. return super::invariant_();
  918. }
  919. /* This forwarding function eases things for the boost::mem_fn construct
  920. * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
  921. * final_check_invariant is already an inherited member function of index.
  922. */
  923. void check_invariant_()const{this->final_check_invariant_();}
  924. #endif
  925. private:
  926. node_type* header()const{return this->final_header();}
  927. std::size_t find_bucket(value_param_type v)const
  928. {
  929. return bucket(key(v));
  930. }
  931. bool link_point(
  932. value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
  933. {
  934. node_impl_pointer x=pos->next();
  935. while(x!=pos){
  936. if(eq_(key(v),key(node_type::from_impl(x)->value()))){
  937. pos=x;
  938. return false;
  939. }
  940. x=x->next();
  941. }
  942. return true;
  943. }
  944. bool link_point(
  945. value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
  946. {
  947. node_impl_pointer prev=pos;
  948. node_impl_pointer x=pos->next();
  949. while(x!=pos){
  950. if(eq_(key(v),key(node_type::from_impl(x)->value()))){
  951. pos=prev;
  952. return true;
  953. }
  954. prev=x;
  955. x=x->next();
  956. }
  957. return true;
  958. }
  959. static void link(node_type* x,node_impl_pointer pos)
  960. {
  961. node_impl_type::link(x->impl(),pos);
  962. };
  963. static void link(node_impl_pointer x,node_impl_pointer pos)
  964. {
  965. node_impl_type::link(x,pos);
  966. };
  967. static void unlink(node_type* x)
  968. {
  969. node_impl_type::unlink(x->impl());
  970. };
  971. static node_impl_pointer prev(node_type* x)
  972. {
  973. return node_impl_type::prev(x->impl());
  974. }
  975. static node_impl_pointer prev_from(node_type* x,node_impl_pointer y)
  976. {
  977. return node_impl_type::prev_from(x->impl(),y);
  978. }
  979. static void unlink_next(node_impl_pointer x)
  980. {
  981. node_impl_type::unlink_next(x);
  982. }
  983. void calculate_max_load()
  984. {
  985. float fml=static_cast<float>(mlf*bucket_count());
  986. max_load=(std::numeric_limits<size_type>::max)();
  987. if(max_load>fml)max_load=static_cast<size_type>(fml);
  988. }
  989. void reserve(size_type n)
  990. {
  991. if(n>max_load){
  992. size_type bc =(std::numeric_limits<size_type>::max)();
  993. float fbc=static_cast<float>(1+static_cast<double>(n)/mlf);
  994. if(bc>fbc)bc =static_cast<size_type>(fbc);
  995. unchecked_rehash(bc);
  996. }
  997. }
  998. void unchecked_rehash(size_type n)
  999. {
  1000. bucket_array_type buckets1(get_allocator(),header()->impl(),n);
  1001. auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
  1002. std::size_t i=0;
  1003. node_impl_pointer x=buckets.begin();
  1004. node_impl_pointer x_end=buckets.end();
  1005. for(;x!=x_end;++x){
  1006. node_impl_pointer y=x->next();
  1007. while(y!=x){
  1008. hashes.data()[i++]=hash_(key(node_type::from_impl(y)->value()));
  1009. y=y->next();
  1010. }
  1011. }
  1012. i=0;
  1013. x=buckets.begin();
  1014. for(;x!=x_end;++x){
  1015. node_impl_pointer y=x->next();
  1016. while(y!=x){
  1017. node_impl_pointer z=y->next();
  1018. std::size_t buc1=buckets1.position(hashes.data()[i++]);
  1019. node_impl_pointer x1=buckets1.at(buc1);
  1020. link(y,x1);
  1021. y=z;
  1022. }
  1023. }
  1024. buckets.swap(buckets1);
  1025. calculate_max_load();
  1026. first_bucket=buckets.first_nonempty(0);
  1027. }
  1028. bool in_place(
  1029. node_impl_pointer x,key_param_type k,std::size_t buc,
  1030. hashed_unique_tag)const
  1031. {
  1032. std::less_equal<node_impl_pointer> leq;
  1033. node_impl_pointer bbegin=buckets.begin();
  1034. node_impl_pointer bend=buckets.end();
  1035. node_impl_pointer pbuc=x->next();
  1036. while(!leq(bbegin,pbuc)||!leq(pbuc,bend))pbuc=pbuc->next();
  1037. if(buc!=static_cast<std::size_t>(pbuc-bbegin))return false;
  1038. node_impl_pointer y=x;
  1039. while(y->next()!=x){
  1040. y=y->next();
  1041. if(y==pbuc)continue;
  1042. if(eq_(k,key(node_type::from_impl(y)->value())))return false;
  1043. }
  1044. return true;
  1045. }
  1046. bool in_place(
  1047. node_impl_pointer x,key_param_type k,std::size_t buc,
  1048. hashed_non_unique_tag)const
  1049. {
  1050. std::less_equal<node_impl_pointer> leq;
  1051. node_impl_pointer bbegin=buckets.begin();
  1052. node_impl_pointer bend=buckets.end();
  1053. node_impl_pointer pbuc=x->next();
  1054. while(!leq(bbegin,pbuc)||!leq(pbuc,bend))pbuc=pbuc->next();
  1055. if(buc!=static_cast<std::size_t>(pbuc-bbegin))return false;
  1056. node_impl_pointer y=x->next();
  1057. if(y!=pbuc){
  1058. if(eq_(k,key(node_type::from_impl(y)->value()))){
  1059. /* adjacent to equivalent element -> in place */
  1060. return true;
  1061. }
  1062. else{
  1063. y=y->next();
  1064. while(y!=pbuc){
  1065. if(eq_(k,key(node_type::from_impl(y)->value())))return false;
  1066. y=y->next();
  1067. }
  1068. }
  1069. }
  1070. while(y->next()!=x){
  1071. y=y->next();
  1072. if(eq_(k,key(node_type::from_impl(y)->value()))){
  1073. while(y->next()!=x){
  1074. y=y->next();
  1075. if(!eq_(k,key(node_type::from_impl(y)->value())))return false;
  1076. }
  1077. /* after a group of equivalent elements --> in place */
  1078. return true;
  1079. }
  1080. }
  1081. return true;
  1082. }
  1083. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  1084. void detach_iterators(node_type* x)
  1085. {
  1086. iterator it=make_iterator(x);
  1087. safe_mode::detach_equivalent_iterators(it);
  1088. }
  1089. #endif
  1090. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1091. std::pair<iterator,bool> emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1092. {
  1093. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  1094. std::pair<final_node_type*,bool>p=
  1095. this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1096. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  1097. }
  1098. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1099. iterator emplace_hint_impl(
  1100. iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1101. {
  1102. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  1103. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  1104. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  1105. std::pair<final_node_type*,bool>p=
  1106. this->final_emplace_hint_(
  1107. static_cast<final_node_type*>(position.get_node()),
  1108. BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1109. return make_iterator(p.first);
  1110. }
  1111. key_from_value key;
  1112. hasher hash_;
  1113. key_equal eq_;
  1114. bucket_array_type buckets;
  1115. float mlf;
  1116. size_type max_load;
  1117. std::size_t first_bucket;
  1118. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  1119. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  1120. #pragma parse_mfunc_templ reset
  1121. #endif
  1122. };
  1123. /* specialized algorithms */
  1124. template<
  1125. typename KeyFromValue,typename Hash,typename Pred,
  1126. typename SuperMeta,typename TagList,typename Category
  1127. >
  1128. void swap(
  1129. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1130. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1131. {
  1132. x.swap(y);
  1133. }
  1134. } /* namespace multi_index::detail */
  1135. /* hashed index specifiers */
  1136. template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1137. struct hashed_unique
  1138. {
  1139. typedef typename detail::hashed_index_args<
  1140. Arg1,Arg2,Arg3,Arg4> index_args;
  1141. typedef typename index_args::tag_list_type::type tag_list_type;
  1142. typedef typename index_args::key_from_value_type key_from_value_type;
  1143. typedef typename index_args::hash_type hash_type;
  1144. typedef typename index_args::pred_type pred_type;
  1145. template<typename Super>
  1146. struct node_class
  1147. {
  1148. typedef detail::hashed_index_node<Super> type;
  1149. };
  1150. template<typename SuperMeta>
  1151. struct index_class
  1152. {
  1153. typedef detail::hashed_index<
  1154. key_from_value_type,hash_type,pred_type,
  1155. SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
  1156. };
  1157. };
  1158. template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1159. struct hashed_non_unique
  1160. {
  1161. typedef typename detail::hashed_index_args<
  1162. Arg1,Arg2,Arg3,Arg4> index_args;
  1163. typedef typename index_args::tag_list_type::type tag_list_type;
  1164. typedef typename index_args::key_from_value_type key_from_value_type;
  1165. typedef typename index_args::hash_type hash_type;
  1166. typedef typename index_args::pred_type pred_type;
  1167. template<typename Super>
  1168. struct node_class
  1169. {
  1170. typedef detail::hashed_index_node<Super> type;
  1171. };
  1172. template<typename SuperMeta>
  1173. struct index_class
  1174. {
  1175. typedef detail::hashed_index<
  1176. key_from_value_type,hash_type,pred_type,
  1177. SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
  1178. };
  1179. };
  1180. } /* namespace multi_index */
  1181. } /* namespace boost */
  1182. /* Boost.Foreach compatibility */
  1183. template<
  1184. typename KeyFromValue,typename Hash,typename Pred,
  1185. typename SuperMeta,typename TagList,typename Category
  1186. >
  1187. inline boost::mpl::true_* boost_foreach_is_noncopyable(
  1188. boost::multi_index::detail::hashed_index<
  1189. KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&,
  1190. boost::foreach::tag)
  1191. {
  1192. return 0;
  1193. }
  1194. #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  1195. #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF
  1196. #endif