random_access_index.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. /* Copyright 2003-2020 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_RANDOM_ACCESS_INDEX_HPP
  9. #define BOOST_MULTI_INDEX_RANDOM_ACCESS_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/bind/bind.hpp>
  16. #include <boost/call_traits.hpp>
  17. #include <boost/core/addressof.hpp>
  18. #include <boost/detail/no_exceptions_support.hpp>
  19. #include <boost/detail/workaround.hpp>
  20. #include <boost/foreach_fwd.hpp>
  21. #include <boost/iterator/reverse_iterator.hpp>
  22. #include <boost/move/core.hpp>
  23. #include <boost/move/utility_core.hpp>
  24. #include <boost/mpl/bool.hpp>
  25. #include <boost/mpl/not.hpp>
  26. #include <boost/mpl/push_front.hpp>
  27. #include <boost/multi_index/detail/access_specifier.hpp>
  28. #include <boost/multi_index/detail/allocator_traits.hpp>
  29. #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
  30. #include <boost/multi_index/detail/index_node_base.hpp>
  31. #include <boost/multi_index/detail/rnd_node_iterator.hpp>
  32. #include <boost/multi_index/detail/rnd_index_node.hpp>
  33. #include <boost/multi_index/detail/rnd_index_ops.hpp>
  34. #include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
  35. #include <boost/multi_index/detail/safe_mode.hpp>
  36. #include <boost/multi_index/detail/scope_guard.hpp>
  37. #include <boost/multi_index/detail/vartempl_support.hpp>
  38. #include <boost/multi_index/random_access_index_fwd.hpp>
  39. #include <boost/throw_exception.hpp>
  40. #include <boost/tuple/tuple.hpp>
  41. #include <boost/type_traits/is_integral.hpp>
  42. #include <functional>
  43. #include <stdexcept>
  44. #include <utility>
  45. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  46. #include<initializer_list>
  47. #endif
  48. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  49. #include <boost/multi_index/detail/rnd_index_loader.hpp>
  50. #endif
  51. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  52. #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(x) \
  53. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  54. detail::make_obj_guard(x,&random_access_index::check_invariant_); \
  55. BOOST_JOIN(check_invariant_,__LINE__).touch();
  56. #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT \
  57. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(*this)
  58. #else
  59. #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(x)
  60. #define BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
  61. #endif
  62. namespace boost{
  63. namespace multi_index{
  64. namespace detail{
  65. /* random_access_index adds a layer of random access indexing
  66. * to a given Super
  67. */
  68. template<typename SuperMeta,typename TagList>
  69. class random_access_index:
  70. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
  71. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  72. ,public safe_mode::safe_container<
  73. random_access_index<SuperMeta,TagList> >
  74. #endif
  75. {
  76. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  77. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  78. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  79. * lifetime of const references bound to temporaries --precisely what
  80. * scopeguards are.
  81. */
  82. #pragma parse_mfunc_templ off
  83. #endif
  84. typedef typename SuperMeta::type super;
  85. protected:
  86. typedef random_access_index_node<
  87. typename super::node_type> node_type;
  88. private:
  89. typedef typename node_type::impl_type node_impl_type;
  90. typedef random_access_index_ptr_array<
  91. typename super::final_allocator_type> ptr_array;
  92. typedef typename ptr_array::pointer node_impl_ptr_pointer;
  93. public:
  94. /* types */
  95. typedef typename node_type::value_type value_type;
  96. typedef tuples::null_type ctor_args;
  97. typedef typename super::final_allocator_type allocator_type;
  98. typedef value_type& reference;
  99. typedef const value_type& const_reference;
  100. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  101. typedef safe_mode::safe_iterator<
  102. rnd_node_iterator<node_type>,
  103. random_access_index> iterator;
  104. #else
  105. typedef rnd_node_iterator<node_type> iterator;
  106. #endif
  107. typedef iterator const_iterator;
  108. private:
  109. typedef allocator_traits<allocator_type> alloc_traits;
  110. public:
  111. typedef typename alloc_traits::pointer pointer;
  112. typedef typename alloc_traits::const_pointer const_pointer;
  113. typedef typename alloc_traits::size_type size_type;
  114. typedef typename alloc_traits::difference_type difference_type;
  115. typedef typename
  116. boost::reverse_iterator<iterator> reverse_iterator;
  117. typedef typename
  118. boost::reverse_iterator<const_iterator> const_reverse_iterator;
  119. typedef TagList tag_list;
  120. protected:
  121. typedef typename super::final_node_type final_node_type;
  122. typedef tuples::cons<
  123. ctor_args,
  124. typename super::ctor_args_list> ctor_args_list;
  125. typedef typename mpl::push_front<
  126. typename super::index_type_list,
  127. random_access_index>::type index_type_list;
  128. typedef typename mpl::push_front<
  129. typename super::iterator_type_list,
  130. iterator>::type iterator_type_list;
  131. typedef typename mpl::push_front<
  132. typename super::const_iterator_type_list,
  133. const_iterator>::type const_iterator_type_list;
  134. typedef typename super::copy_map_type copy_map_type;
  135. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  136. typedef typename super::index_saver_type index_saver_type;
  137. typedef typename super::index_loader_type index_loader_type;
  138. #endif
  139. private:
  140. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  141. typedef safe_mode::safe_container<
  142. random_access_index> safe_super;
  143. #endif
  144. typedef typename call_traits<
  145. value_type>::param_type value_param_type;
  146. /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
  147. * expansion.
  148. */
  149. typedef std::pair<iterator,bool> emplace_return_type;
  150. public:
  151. /* construct/copy/destroy
  152. * Default and copy ctors are in the protected section as indices are
  153. * not supposed to be created on their own. No range ctor either.
  154. */
  155. random_access_index<SuperMeta,TagList>& operator=(
  156. const random_access_index<SuperMeta,TagList>& x)
  157. {
  158. this->final()=x.final();
  159. return *this;
  160. }
  161. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  162. random_access_index<SuperMeta,TagList>& operator=(
  163. std::initializer_list<value_type> list)
  164. {
  165. this->final()=list;
  166. return *this;
  167. }
  168. #endif
  169. template <class InputIterator>
  170. void assign(InputIterator first,InputIterator last)
  171. {
  172. assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
  173. }
  174. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  175. void assign(std::initializer_list<value_type> list)
  176. {
  177. assign(list.begin(),list.end());
  178. }
  179. #endif
  180. void assign(size_type n,value_param_type value)
  181. {
  182. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  183. clear();
  184. for(size_type i=0;i<n;++i)push_back(value);
  185. }
  186. allocator_type get_allocator()const BOOST_NOEXCEPT
  187. {
  188. return this->final().get_allocator();
  189. }
  190. /* iterators */
  191. iterator begin()BOOST_NOEXCEPT
  192. {return make_iterator(node_type::from_impl(*ptrs.begin()));}
  193. const_iterator begin()const BOOST_NOEXCEPT
  194. {return make_iterator(node_type::from_impl(*ptrs.begin()));}
  195. iterator
  196. end()BOOST_NOEXCEPT{return make_iterator(header());}
  197. const_iterator
  198. end()const BOOST_NOEXCEPT{return make_iterator(header());}
  199. reverse_iterator
  200. rbegin()BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
  201. const_reverse_iterator
  202. rbegin()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
  203. reverse_iterator
  204. rend()BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
  205. const_reverse_iterator
  206. rend()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
  207. const_iterator
  208. cbegin()const BOOST_NOEXCEPT{return begin();}
  209. const_iterator
  210. cend()const BOOST_NOEXCEPT{return end();}
  211. const_reverse_iterator
  212. crbegin()const BOOST_NOEXCEPT{return rbegin();}
  213. const_reverse_iterator
  214. crend()const BOOST_NOEXCEPT{return rend();}
  215. iterator iterator_to(const value_type& x)
  216. {
  217. return make_iterator(node_from_value<node_type>(boost::addressof(x)));
  218. }
  219. const_iterator iterator_to(const value_type& x)const
  220. {
  221. return make_iterator(node_from_value<node_type>(boost::addressof(x)));
  222. }
  223. /* capacity */
  224. bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
  225. size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
  226. size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
  227. size_type capacity()const BOOST_NOEXCEPT{return ptrs.capacity();}
  228. void reserve(size_type n)
  229. {
  230. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  231. ptrs.reserve(n);
  232. }
  233. void shrink_to_fit()
  234. {
  235. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  236. ptrs.shrink_to_fit();
  237. }
  238. void resize(size_type n)
  239. {
  240. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  241. if(n>size())
  242. for(size_type m=n-size();m--;)
  243. this->final_emplace_(BOOST_MULTI_INDEX_NULL_PARAM_PACK);
  244. else if(n<size())erase(begin()+n,end());
  245. }
  246. void resize(size_type n,value_param_type x)
  247. {
  248. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  249. if(n>size())for(size_type m=n-size();m--;)this->final_insert_(x);
  250. else if(n<size())erase(begin()+n,end());
  251. }
  252. /* access: no non-const versions provided as random_access_index
  253. * handles const elements.
  254. */
  255. const_reference operator[](size_type n)const
  256. {
  257. BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(n<size(),safe_mode::out_of_bounds);
  258. return node_type::from_impl(*ptrs.at(n))->value();
  259. }
  260. const_reference at(size_type n)const
  261. {
  262. if(n>=size())throw_exception(std::out_of_range("random access index"));
  263. return node_type::from_impl(*ptrs.at(n))->value();
  264. }
  265. const_reference front()const{return operator[](0);}
  266. const_reference back()const{return operator[](size()-1);}
  267. /* modifiers */
  268. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
  269. emplace_return_type,emplace_front,emplace_front_impl)
  270. std::pair<iterator,bool> push_front(const value_type& x)
  271. {return insert(begin(),x);}
  272. std::pair<iterator,bool> push_front(BOOST_RV_REF(value_type) x)
  273. {return insert(begin(),boost::move(x));}
  274. void pop_front(){erase(begin());}
  275. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
  276. emplace_return_type,emplace_back,emplace_back_impl)
  277. std::pair<iterator,bool> push_back(const value_type& x)
  278. {return insert(end(),x);}
  279. std::pair<iterator,bool> push_back(BOOST_RV_REF(value_type) x)
  280. {return insert(end(),boost::move(x));}
  281. void pop_back(){erase(--end());}
  282. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
  283. emplace_return_type,emplace,emplace_impl,iterator,position)
  284. std::pair<iterator,bool> insert(iterator position,const value_type& x)
  285. {
  286. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  287. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  288. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  289. std::pair<final_node_type*,bool> p=this->final_insert_(x);
  290. if(p.second&&position.get_node()!=header()){
  291. relocate(position.get_node(),p.first);
  292. }
  293. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  294. }
  295. std::pair<iterator,bool> insert(iterator position,BOOST_RV_REF(value_type) x)
  296. {
  297. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  298. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  299. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  300. std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
  301. if(p.second&&position.get_node()!=header()){
  302. relocate(position.get_node(),p.first);
  303. }
  304. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  305. }
  306. void insert(iterator position,size_type n,value_param_type x)
  307. {
  308. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  309. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  310. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  311. size_type s=0;
  312. BOOST_TRY{
  313. while(n--){
  314. if(push_back(x).second)++s;
  315. }
  316. }
  317. BOOST_CATCH(...){
  318. relocate(position,end()-s,end());
  319. BOOST_RETHROW;
  320. }
  321. BOOST_CATCH_END
  322. relocate(position,end()-s,end());
  323. }
  324. template<typename InputIterator>
  325. void insert(iterator position,InputIterator first,InputIterator last)
  326. {
  327. insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
  328. }
  329. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  330. void insert(iterator position,std::initializer_list<value_type> list)
  331. {
  332. insert(position,list.begin(),list.end());
  333. }
  334. #endif
  335. iterator erase(iterator position)
  336. {
  337. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  338. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  339. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  340. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  341. this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
  342. return position;
  343. }
  344. iterator erase(iterator first,iterator last)
  345. {
  346. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  347. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  348. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  349. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  350. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  351. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  352. difference_type n=static_cast<difference_type>(last-first);
  353. relocate(end(),first,last);
  354. while(n--)pop_back();
  355. return last;
  356. }
  357. bool replace(iterator position,const value_type& x)
  358. {
  359. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  360. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  361. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  362. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  363. return this->final_replace_(
  364. x,static_cast<final_node_type*>(position.get_node()));
  365. }
  366. bool replace(iterator position,BOOST_RV_REF(value_type) x)
  367. {
  368. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  369. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  370. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  371. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  372. return this->final_replace_rv_(
  373. x,static_cast<final_node_type*>(position.get_node()));
  374. }
  375. template<typename Modifier>
  376. bool modify(iterator position,Modifier mod)
  377. {
  378. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  379. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  380. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  381. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  382. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  383. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  384. * this is not added. Left it for all compilers as it does no
  385. * harm.
  386. */
  387. position.detach();
  388. #endif
  389. return this->final_modify_(
  390. mod,static_cast<final_node_type*>(position.get_node()));
  391. }
  392. template<typename Modifier,typename Rollback>
  393. bool modify(iterator position,Modifier mod,Rollback back_)
  394. {
  395. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  396. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  397. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  398. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  399. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  400. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  401. * this is not added. Left it for all compilers as it does no
  402. * harm.
  403. */
  404. position.detach();
  405. #endif
  406. return this->final_modify_(
  407. mod,back_,static_cast<final_node_type*>(position.get_node()));
  408. }
  409. void swap(random_access_index<SuperMeta,TagList>& x)
  410. {
  411. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  412. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF(x);
  413. this->final_swap_(x.final());
  414. }
  415. void clear()BOOST_NOEXCEPT
  416. {
  417. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  418. this->final_clear_();
  419. }
  420. /* list operations */
  421. void splice(iterator position,random_access_index<SuperMeta,TagList>& x)
  422. {
  423. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  424. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  425. BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(*this,x);
  426. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  427. iterator first=x.begin(),last=x.end();
  428. size_type n=0;
  429. BOOST_TRY{
  430. while(first!=last){
  431. if(push_back(*first).second){
  432. first=x.erase(first);
  433. ++n;
  434. }
  435. else ++first;
  436. }
  437. }
  438. BOOST_CATCH(...){
  439. relocate(position,end()-n,end());
  440. BOOST_RETHROW;
  441. }
  442. BOOST_CATCH_END
  443. relocate(position,end()-n,end());
  444. }
  445. void splice(
  446. iterator position,random_access_index<SuperMeta,TagList>& x,iterator i)
  447. {
  448. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  449. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  450. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
  451. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
  452. BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,x);
  453. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  454. if(&x==this)relocate(position,i);
  455. else{
  456. if(insert(position,*i).second){
  457. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  458. /* MSVC++ 6.0 optimizer has a hard time with safe mode, and the following
  459. * workaround is needed. Left it for all compilers as it does no
  460. * harm.
  461. */
  462. i.detach();
  463. x.erase(x.make_iterator(i.get_node()));
  464. #else
  465. x.erase(i);
  466. #endif
  467. }
  468. }
  469. }
  470. void splice(
  471. iterator position,random_access_index<SuperMeta,TagList>& x,
  472. iterator first,iterator last)
  473. {
  474. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  475. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  476. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  477. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  478. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,x);
  479. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,x);
  480. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  481. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  482. if(&x==this)relocate(position,first,last);
  483. else{
  484. size_type n=0;
  485. BOOST_TRY{
  486. while(first!=last){
  487. if(push_back(*first).second){
  488. first=x.erase(first);
  489. ++n;
  490. }
  491. else ++first;
  492. }
  493. }
  494. BOOST_CATCH(...){
  495. relocate(position,end()-n,end());
  496. BOOST_RETHROW;
  497. }
  498. BOOST_CATCH_END
  499. relocate(position,end()-n,end());
  500. }
  501. }
  502. void remove(value_param_type value)
  503. {
  504. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  505. difference_type n=
  506. end()-make_iterator(
  507. random_access_index_remove<node_type>(
  508. ptrs,
  509. ::boost::bind(std::equal_to<value_type>(),::boost::arg<1>(),value)));
  510. while(n--)pop_back();
  511. }
  512. template<typename Predicate>
  513. void remove_if(Predicate pred)
  514. {
  515. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  516. difference_type n=
  517. end()-make_iterator(random_access_index_remove<node_type>(ptrs,pred));
  518. while(n--)pop_back();
  519. }
  520. void unique()
  521. {
  522. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  523. difference_type n=
  524. end()-make_iterator(
  525. random_access_index_unique<node_type>(
  526. ptrs,std::equal_to<value_type>()));
  527. while(n--)pop_back();
  528. }
  529. template <class BinaryPredicate>
  530. void unique(BinaryPredicate binary_pred)
  531. {
  532. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  533. difference_type n=
  534. end()-make_iterator(
  535. random_access_index_unique<node_type>(ptrs,binary_pred));
  536. while(n--)pop_back();
  537. }
  538. void merge(random_access_index<SuperMeta,TagList>& x)
  539. {
  540. if(this!=&x){
  541. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  542. size_type s=size();
  543. splice(end(),x);
  544. random_access_index_inplace_merge<node_type>(
  545. get_allocator(),ptrs,ptrs.at(s),std::less<value_type>());
  546. }
  547. }
  548. template <typename Compare>
  549. void merge(random_access_index<SuperMeta,TagList>& x,Compare comp)
  550. {
  551. if(this!=&x){
  552. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  553. size_type s=size();
  554. splice(end(),x);
  555. random_access_index_inplace_merge<node_type>(
  556. get_allocator(),ptrs,ptrs.at(s),comp);
  557. }
  558. }
  559. void sort()
  560. {
  561. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  562. random_access_index_sort<node_type>(
  563. get_allocator(),ptrs,std::less<value_type>());
  564. }
  565. template <typename Compare>
  566. void sort(Compare comp)
  567. {
  568. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  569. random_access_index_sort<node_type>(
  570. get_allocator(),ptrs,comp);
  571. }
  572. void reverse()BOOST_NOEXCEPT
  573. {
  574. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  575. node_impl_type::reverse(ptrs.begin(),ptrs.end());
  576. }
  577. /* rearrange operations */
  578. void relocate(iterator position,iterator i)
  579. {
  580. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  581. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  582. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(i);
  583. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(i);
  584. BOOST_MULTI_INDEX_CHECK_IS_OWNER(i,*this);
  585. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  586. if(position!=i)relocate(position.get_node(),i.get_node());
  587. }
  588. void relocate(iterator position,iterator first,iterator last)
  589. {
  590. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  591. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  592. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  593. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  594. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  595. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  596. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  597. BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(position,first,last);
  598. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  599. if(position!=last)relocate(
  600. position.get_node(),first.get_node(),last.get_node());
  601. }
  602. template<typename InputIterator>
  603. void rearrange(InputIterator first)
  604. {
  605. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  606. for(node_impl_ptr_pointer p0=ptrs.begin(),p0_end=ptrs.end();
  607. p0!=p0_end;++first,++p0){
  608. const value_type& v1=*first;
  609. node_impl_ptr_pointer p1=node_from_value<node_type>(&v1)->up();
  610. std::swap(*p0,*p1);
  611. (*p0)->up()=p0;
  612. (*p1)->up()=p1;
  613. }
  614. }
  615. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  616. random_access_index(
  617. const ctor_args_list& args_list,const allocator_type& al):
  618. super(args_list.get_tail(),al),
  619. ptrs(al,header()->impl(),0)
  620. {
  621. }
  622. random_access_index(const random_access_index<SuperMeta,TagList>& x):
  623. super(x),
  624. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  625. safe_super(),
  626. #endif
  627. ptrs(x.get_allocator(),header()->impl(),x.size())
  628. {
  629. /* The actual copying takes place in subsequent call to copy_().
  630. */
  631. }
  632. random_access_index(
  633. const random_access_index<SuperMeta,TagList>& x,do_not_copy_elements_tag):
  634. super(x,do_not_copy_elements_tag()),
  635. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  636. safe_super(),
  637. #endif
  638. ptrs(x.get_allocator(),header()->impl(),0)
  639. {
  640. }
  641. ~random_access_index()
  642. {
  643. /* the container is guaranteed to be empty by now */
  644. }
  645. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  646. iterator make_iterator(node_type* node){return iterator(node,this);}
  647. const_iterator make_iterator(node_type* node)const
  648. {return const_iterator(node,const_cast<random_access_index*>(this));}
  649. #else
  650. iterator make_iterator(node_type* node){return iterator(node);}
  651. const_iterator make_iterator(node_type* node)const
  652. {return const_iterator(node);}
  653. #endif
  654. void copy_(
  655. const random_access_index<SuperMeta,TagList>& x,const copy_map_type& map)
  656. {
  657. for(node_impl_ptr_pointer begin_org=x.ptrs.begin(),
  658. begin_cpy=ptrs.begin(),
  659. end_org=x.ptrs.end();
  660. begin_org!=end_org;++begin_org,++begin_cpy){
  661. *begin_cpy=
  662. static_cast<node_type*>(
  663. map.find(
  664. static_cast<final_node_type*>(
  665. node_type::from_impl(*begin_org))))->impl();
  666. (*begin_cpy)->up()=begin_cpy;
  667. }
  668. super::copy_(x,map);
  669. }
  670. template<typename Variant>
  671. final_node_type* insert_(
  672. value_param_type v,final_node_type*& x,Variant variant)
  673. {
  674. ptrs.room_for_one();
  675. final_node_type* res=super::insert_(v,x,variant);
  676. if(res==x)ptrs.push_back(static_cast<node_type*>(x)->impl());
  677. return res;
  678. }
  679. template<typename Variant>
  680. final_node_type* insert_(
  681. value_param_type v,node_type* position,final_node_type*& x,Variant variant)
  682. {
  683. ptrs.room_for_one();
  684. final_node_type* res=super::insert_(v,position,x,variant);
  685. if(res==x)ptrs.push_back(static_cast<node_type*>(x)->impl());
  686. return res;
  687. }
  688. void erase_(node_type* x)
  689. {
  690. ptrs.erase(x->impl());
  691. super::erase_(x);
  692. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  693. detach_iterators(x);
  694. #endif
  695. }
  696. void delete_all_nodes_()
  697. {
  698. for(node_impl_ptr_pointer x=ptrs.begin(),x_end=ptrs.end();x!=x_end;++x){
  699. this->final_delete_node_(
  700. static_cast<final_node_type*>(node_type::from_impl(*x)));
  701. }
  702. }
  703. void clear_()
  704. {
  705. super::clear_();
  706. ptrs.clear();
  707. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  708. safe_super::detach_dereferenceable_iterators();
  709. #endif
  710. }
  711. template<typename BoolConstant>
  712. void swap_(
  713. random_access_index<SuperMeta,TagList>& x,BoolConstant swap_allocators)
  714. {
  715. ptrs.swap(x.ptrs,swap_allocators);
  716. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  717. safe_super::swap(x);
  718. #endif
  719. super::swap_(x,swap_allocators);
  720. }
  721. void swap_elements_(random_access_index<SuperMeta,TagList>& x)
  722. {
  723. ptrs.swap(x.ptrs);
  724. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  725. safe_super::swap(x);
  726. #endif
  727. super::swap_elements_(x);
  728. }
  729. template<typename Variant>
  730. bool replace_(value_param_type v,node_type* x,Variant variant)
  731. {
  732. return super::replace_(v,x,variant);
  733. }
  734. bool modify_(node_type* x)
  735. {
  736. BOOST_TRY{
  737. if(!super::modify_(x)){
  738. ptrs.erase(x->impl());
  739. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  740. detach_iterators(x);
  741. #endif
  742. return false;
  743. }
  744. else return true;
  745. }
  746. BOOST_CATCH(...){
  747. ptrs.erase(x->impl());
  748. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  749. detach_iterators(x);
  750. #endif
  751. BOOST_RETHROW;
  752. }
  753. BOOST_CATCH_END
  754. }
  755. bool modify_rollback_(node_type* x)
  756. {
  757. return super::modify_rollback_(x);
  758. }
  759. bool check_rollback_(node_type* x)const
  760. {
  761. return super::check_rollback_(x);
  762. }
  763. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  764. /* serialization */
  765. template<typename Archive>
  766. void save_(
  767. Archive& ar,const unsigned int version,const index_saver_type& sm)const
  768. {
  769. sm.save(begin(),end(),ar,version);
  770. super::save_(ar,version,sm);
  771. }
  772. template<typename Archive>
  773. void load_(
  774. Archive& ar,const unsigned int version,const index_loader_type& lm)
  775. {
  776. {
  777. typedef random_access_index_loader<node_type,allocator_type> loader;
  778. loader ld(get_allocator(),ptrs);
  779. lm.load(
  780. ::boost::bind(
  781. &loader::rearrange,&ld,::boost::arg<1>(),::boost::arg<2>()),
  782. ar,version);
  783. } /* exit scope so that ld frees its resources */
  784. super::load_(ar,version,lm);
  785. }
  786. #endif
  787. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  788. /* invariant stuff */
  789. bool invariant_()const
  790. {
  791. if(size()>capacity())return false;
  792. if(size()==0||begin()==end()){
  793. if(size()!=0||begin()!=end())return false;
  794. }
  795. else{
  796. size_type s=0;
  797. for(const_iterator it=begin(),it_end=end();;++it,++s){
  798. if(*(it.get_node()->up())!=it.get_node()->impl())return false;
  799. if(it==it_end)break;
  800. }
  801. if(s!=size())return false;
  802. }
  803. return super::invariant_();
  804. }
  805. /* This forwarding function eases things for the boost::mem_fn construct
  806. * in BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT. Actually,
  807. * final_check_invariant is already an inherited member function of index.
  808. */
  809. void check_invariant_()const{this->final_check_invariant_();}
  810. #endif
  811. private:
  812. node_type* header()const{return this->final_header();}
  813. static void relocate(node_type* position,node_type* x)
  814. {
  815. node_impl_type::relocate(position->up(),x->up());
  816. }
  817. static void relocate(node_type* position,node_type* first,node_type* last)
  818. {
  819. node_impl_type::relocate(
  820. position->up(),first->up(),last->up());
  821. }
  822. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  823. void detach_iterators(node_type* x)
  824. {
  825. iterator it=make_iterator(x);
  826. safe_mode::detach_equivalent_iterators(it);
  827. }
  828. #endif
  829. template <class InputIterator>
  830. void assign_iter(InputIterator first,InputIterator last,mpl::true_)
  831. {
  832. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  833. clear();
  834. for(;first!=last;++first)this->final_insert_ref_(*first);
  835. }
  836. void assign_iter(size_type n,value_param_type value,mpl::false_)
  837. {
  838. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  839. clear();
  840. for(size_type i=0;i<n;++i)push_back(value);
  841. }
  842. template<typename InputIterator>
  843. void insert_iter(
  844. iterator position,InputIterator first,InputIterator last,mpl::true_)
  845. {
  846. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  847. size_type s=0;
  848. BOOST_TRY{
  849. for(;first!=last;++first){
  850. if(this->final_insert_ref_(*first).second)++s;
  851. }
  852. }
  853. BOOST_CATCH(...){
  854. relocate(position,end()-s,end());
  855. BOOST_RETHROW;
  856. }
  857. BOOST_CATCH_END
  858. relocate(position,end()-s,end());
  859. }
  860. void insert_iter(
  861. iterator position,size_type n,value_param_type x,mpl::false_)
  862. {
  863. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  864. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  865. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  866. size_type s=0;
  867. BOOST_TRY{
  868. while(n--){
  869. if(push_back(x).second)++s;
  870. }
  871. }
  872. BOOST_CATCH(...){
  873. relocate(position,end()-s,end());
  874. BOOST_RETHROW;
  875. }
  876. BOOST_CATCH_END
  877. relocate(position,end()-s,end());
  878. }
  879. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  880. std::pair<iterator,bool> emplace_front_impl(
  881. BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  882. {
  883. return emplace_impl(begin(),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  884. }
  885. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  886. std::pair<iterator,bool> emplace_back_impl(
  887. BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  888. {
  889. return emplace_impl(end(),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  890. }
  891. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  892. std::pair<iterator,bool> emplace_impl(
  893. iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  894. {
  895. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  896. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  897. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  898. std::pair<final_node_type*,bool> p=
  899. this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  900. if(p.second&&position.get_node()!=header()){
  901. relocate(position.get_node(),p.first);
  902. }
  903. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  904. }
  905. ptr_array ptrs;
  906. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  907. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  908. #pragma parse_mfunc_templ reset
  909. #endif
  910. };
  911. /* comparison */
  912. template<
  913. typename SuperMeta1,typename TagList1,
  914. typename SuperMeta2,typename TagList2
  915. >
  916. bool operator==(
  917. const random_access_index<SuperMeta1,TagList1>& x,
  918. const random_access_index<SuperMeta2,TagList2>& y)
  919. {
  920. return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
  921. }
  922. template<
  923. typename SuperMeta1,typename TagList1,
  924. typename SuperMeta2,typename TagList2
  925. >
  926. bool operator<(
  927. const random_access_index<SuperMeta1,TagList1>& x,
  928. const random_access_index<SuperMeta2,TagList2>& y)
  929. {
  930. return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
  931. }
  932. template<
  933. typename SuperMeta1,typename TagList1,
  934. typename SuperMeta2,typename TagList2
  935. >
  936. bool operator!=(
  937. const random_access_index<SuperMeta1,TagList1>& x,
  938. const random_access_index<SuperMeta2,TagList2>& y)
  939. {
  940. return !(x==y);
  941. }
  942. template<
  943. typename SuperMeta1,typename TagList1,
  944. typename SuperMeta2,typename TagList2
  945. >
  946. bool operator>(
  947. const random_access_index<SuperMeta1,TagList1>& x,
  948. const random_access_index<SuperMeta2,TagList2>& y)
  949. {
  950. return y<x;
  951. }
  952. template<
  953. typename SuperMeta1,typename TagList1,
  954. typename SuperMeta2,typename TagList2
  955. >
  956. bool operator>=(
  957. const random_access_index<SuperMeta1,TagList1>& x,
  958. const random_access_index<SuperMeta2,TagList2>& y)
  959. {
  960. return !(x<y);
  961. }
  962. template<
  963. typename SuperMeta1,typename TagList1,
  964. typename SuperMeta2,typename TagList2
  965. >
  966. bool operator<=(
  967. const random_access_index<SuperMeta1,TagList1>& x,
  968. const random_access_index<SuperMeta2,TagList2>& y)
  969. {
  970. return !(x>y);
  971. }
  972. /* specialized algorithms */
  973. template<typename SuperMeta,typename TagList>
  974. void swap(
  975. random_access_index<SuperMeta,TagList>& x,
  976. random_access_index<SuperMeta,TagList>& y)
  977. {
  978. x.swap(y);
  979. }
  980. } /* namespace multi_index::detail */
  981. /* random access index specifier */
  982. template <typename TagList>
  983. struct random_access
  984. {
  985. BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
  986. template<typename Super>
  987. struct node_class
  988. {
  989. typedef detail::random_access_index_node<Super> type;
  990. };
  991. template<typename SuperMeta>
  992. struct index_class
  993. {
  994. typedef detail::random_access_index<
  995. SuperMeta,typename TagList::type> type;
  996. };
  997. };
  998. } /* namespace multi_index */
  999. } /* namespace boost */
  1000. /* Boost.Foreach compatibility */
  1001. template<typename SuperMeta,typename TagList>
  1002. inline boost::mpl::true_* boost_foreach_is_noncopyable(
  1003. boost::multi_index::detail::random_access_index<SuperMeta,TagList>*&,
  1004. boost_foreach_argument_dependent_lookup_hack)
  1005. {
  1006. return 0;
  1007. }
  1008. #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
  1009. #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF
  1010. #endif