random_access_index.hpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. /* Copyright 2003-2018 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.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. void swap_(random_access_index<SuperMeta,TagList>& x)
  712. {
  713. ptrs.swap(x.ptrs);
  714. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  715. safe_super::swap(x);
  716. #endif
  717. super::swap_(x);
  718. }
  719. void swap_elements_(random_access_index<SuperMeta,TagList>& x)
  720. {
  721. ptrs.swap(x.ptrs);
  722. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  723. safe_super::swap(x);
  724. #endif
  725. super::swap_elements_(x);
  726. }
  727. template<typename Variant>
  728. bool replace_(value_param_type v,node_type* x,Variant variant)
  729. {
  730. return super::replace_(v,x,variant);
  731. }
  732. bool modify_(node_type* x)
  733. {
  734. BOOST_TRY{
  735. if(!super::modify_(x)){
  736. ptrs.erase(x->impl());
  737. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  738. detach_iterators(x);
  739. #endif
  740. return false;
  741. }
  742. else return true;
  743. }
  744. BOOST_CATCH(...){
  745. ptrs.erase(x->impl());
  746. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  747. detach_iterators(x);
  748. #endif
  749. BOOST_RETHROW;
  750. }
  751. BOOST_CATCH_END
  752. }
  753. bool modify_rollback_(node_type* x)
  754. {
  755. return super::modify_rollback_(x);
  756. }
  757. bool check_rollback_(node_type* x)const
  758. {
  759. return super::check_rollback_(x);
  760. }
  761. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  762. /* serialization */
  763. template<typename Archive>
  764. void save_(
  765. Archive& ar,const unsigned int version,const index_saver_type& sm)const
  766. {
  767. sm.save(begin(),end(),ar,version);
  768. super::save_(ar,version,sm);
  769. }
  770. template<typename Archive>
  771. void load_(
  772. Archive& ar,const unsigned int version,const index_loader_type& lm)
  773. {
  774. {
  775. typedef random_access_index_loader<node_type,allocator_type> loader;
  776. loader ld(get_allocator(),ptrs);
  777. lm.load(
  778. ::boost::bind(
  779. &loader::rearrange,&ld,::boost::arg<1>(),::boost::arg<2>()),
  780. ar,version);
  781. } /* exit scope so that ld frees its resources */
  782. super::load_(ar,version,lm);
  783. }
  784. #endif
  785. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  786. /* invariant stuff */
  787. bool invariant_()const
  788. {
  789. if(size()>capacity())return false;
  790. if(size()==0||begin()==end()){
  791. if(size()!=0||begin()!=end())return false;
  792. }
  793. else{
  794. size_type s=0;
  795. for(const_iterator it=begin(),it_end=end();;++it,++s){
  796. if(*(it.get_node()->up())!=it.get_node()->impl())return false;
  797. if(it==it_end)break;
  798. }
  799. if(s!=size())return false;
  800. }
  801. return super::invariant_();
  802. }
  803. /* This forwarding function eases things for the boost::mem_fn construct
  804. * in BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT. Actually,
  805. * final_check_invariant is already an inherited member function of index.
  806. */
  807. void check_invariant_()const{this->final_check_invariant_();}
  808. #endif
  809. private:
  810. node_type* header()const{return this->final_header();}
  811. static void relocate(node_type* position,node_type* x)
  812. {
  813. node_impl_type::relocate(position->up(),x->up());
  814. }
  815. static void relocate(node_type* position,node_type* first,node_type* last)
  816. {
  817. node_impl_type::relocate(
  818. position->up(),first->up(),last->up());
  819. }
  820. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  821. void detach_iterators(node_type* x)
  822. {
  823. iterator it=make_iterator(x);
  824. safe_mode::detach_equivalent_iterators(it);
  825. }
  826. #endif
  827. template <class InputIterator>
  828. void assign_iter(InputIterator first,InputIterator last,mpl::true_)
  829. {
  830. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  831. clear();
  832. for(;first!=last;++first)this->final_insert_ref_(*first);
  833. }
  834. void assign_iter(size_type n,value_param_type value,mpl::false_)
  835. {
  836. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  837. clear();
  838. for(size_type i=0;i<n;++i)push_back(value);
  839. }
  840. template<typename InputIterator>
  841. void insert_iter(
  842. iterator position,InputIterator first,InputIterator last,mpl::true_)
  843. {
  844. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  845. size_type s=0;
  846. BOOST_TRY{
  847. for(;first!=last;++first){
  848. if(this->final_insert_ref_(*first).second)++s;
  849. }
  850. }
  851. BOOST_CATCH(...){
  852. relocate(position,end()-s,end());
  853. BOOST_RETHROW;
  854. }
  855. BOOST_CATCH_END
  856. relocate(position,end()-s,end());
  857. }
  858. void insert_iter(
  859. iterator position,size_type n,value_param_type x,mpl::false_)
  860. {
  861. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  862. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  863. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  864. size_type s=0;
  865. BOOST_TRY{
  866. while(n--){
  867. if(push_back(x).second)++s;
  868. }
  869. }
  870. BOOST_CATCH(...){
  871. relocate(position,end()-s,end());
  872. BOOST_RETHROW;
  873. }
  874. BOOST_CATCH_END
  875. relocate(position,end()-s,end());
  876. }
  877. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  878. std::pair<iterator,bool> emplace_front_impl(
  879. BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  880. {
  881. return emplace_impl(begin(),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  882. }
  883. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  884. std::pair<iterator,bool> emplace_back_impl(
  885. BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  886. {
  887. return emplace_impl(end(),BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  888. }
  889. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  890. std::pair<iterator,bool> emplace_impl(
  891. iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  892. {
  893. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  894. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  895. BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
  896. std::pair<final_node_type*,bool> p=
  897. this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  898. if(p.second&&position.get_node()!=header()){
  899. relocate(position.get_node(),p.first);
  900. }
  901. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  902. }
  903. ptr_array ptrs;
  904. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  905. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  906. #pragma parse_mfunc_templ reset
  907. #endif
  908. };
  909. /* comparison */
  910. template<
  911. typename SuperMeta1,typename TagList1,
  912. typename SuperMeta2,typename TagList2
  913. >
  914. bool operator==(
  915. const random_access_index<SuperMeta1,TagList1>& x,
  916. const random_access_index<SuperMeta2,TagList2>& y)
  917. {
  918. return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
  919. }
  920. template<
  921. typename SuperMeta1,typename TagList1,
  922. typename SuperMeta2,typename TagList2
  923. >
  924. bool operator<(
  925. const random_access_index<SuperMeta1,TagList1>& x,
  926. const random_access_index<SuperMeta2,TagList2>& y)
  927. {
  928. return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
  929. }
  930. template<
  931. typename SuperMeta1,typename TagList1,
  932. typename SuperMeta2,typename TagList2
  933. >
  934. bool operator!=(
  935. const random_access_index<SuperMeta1,TagList1>& x,
  936. const random_access_index<SuperMeta2,TagList2>& y)
  937. {
  938. return !(x==y);
  939. }
  940. template<
  941. typename SuperMeta1,typename TagList1,
  942. typename SuperMeta2,typename TagList2
  943. >
  944. bool operator>(
  945. const random_access_index<SuperMeta1,TagList1>& x,
  946. const random_access_index<SuperMeta2,TagList2>& y)
  947. {
  948. return y<x;
  949. }
  950. template<
  951. typename SuperMeta1,typename TagList1,
  952. typename SuperMeta2,typename TagList2
  953. >
  954. bool operator>=(
  955. const random_access_index<SuperMeta1,TagList1>& x,
  956. const random_access_index<SuperMeta2,TagList2>& y)
  957. {
  958. return !(x<y);
  959. }
  960. template<
  961. typename SuperMeta1,typename TagList1,
  962. typename SuperMeta2,typename TagList2
  963. >
  964. bool operator<=(
  965. const random_access_index<SuperMeta1,TagList1>& x,
  966. const random_access_index<SuperMeta2,TagList2>& y)
  967. {
  968. return !(x>y);
  969. }
  970. /* specialized algorithms */
  971. template<typename SuperMeta,typename TagList>
  972. void swap(
  973. random_access_index<SuperMeta,TagList>& x,
  974. random_access_index<SuperMeta,TagList>& y)
  975. {
  976. x.swap(y);
  977. }
  978. } /* namespace multi_index::detail */
  979. /* random access index specifier */
  980. template <typename TagList>
  981. struct random_access
  982. {
  983. BOOST_STATIC_ASSERT(detail::is_tag<TagList>::value);
  984. template<typename Super>
  985. struct node_class
  986. {
  987. typedef detail::random_access_index_node<Super> type;
  988. };
  989. template<typename SuperMeta>
  990. struct index_class
  991. {
  992. typedef detail::random_access_index<
  993. SuperMeta,typename TagList::type> type;
  994. };
  995. };
  996. } /* namespace multi_index */
  997. } /* namespace boost */
  998. /* Boost.Foreach compatibility */
  999. template<typename SuperMeta,typename TagList>
  1000. inline boost::mpl::true_* boost_foreach_is_noncopyable(
  1001. boost::multi_index::detail::random_access_index<SuperMeta,TagList>*&,
  1002. boost_foreach_argument_dependent_lookup_hack)
  1003. {
  1004. return 0;
  1005. }
  1006. #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT
  1007. #undef BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT_OF
  1008. #endif