sequenced_index.hpp 30 KB

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