/Src/Dependencies/Boost/boost/multi_index/random_access_index.hpp

http://hadesmem.googlecode.com/ · C++ Header · 1008 lines · 816 code · 141 blank · 51 comment · 46 complexity · ceb4fe7e30b6e1333bc55efc4e100fe8 MD5 · raw file

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