multi_index_container.hpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. /* Multiply indexed container.
  2. *
  3. * Copyright 2003-2009 Joaquin M Lopez Munoz.
  4. * Distributed under the Boost Software License, Version 1.0.
  5. * (See accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * See http://www.boost.org/libs/multi_index for library home page.
  9. */
  10. #ifndef BOOST_MULTI_INDEX_HPP
  11. #define BOOST_MULTI_INDEX_HPP
  12. #if defined(_MSC_VER)&&(_MSC_VER>=1200)
  13. #pragma once
  14. #endif
  15. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  16. #include <algorithm>
  17. #include <boost/detail/allocator_utilities.hpp>
  18. #include <boost/detail/no_exceptions_support.hpp>
  19. #include <boost/detail/workaround.hpp>
  20. #include <boost/mpl/at.hpp>
  21. #include <boost/mpl/contains.hpp>
  22. #include <boost/mpl/find_if.hpp>
  23. #include <boost/mpl/identity.hpp>
  24. #include <boost/mpl/int.hpp>
  25. #include <boost/mpl/size.hpp>
  26. #include <boost/mpl/deref.hpp>
  27. #include <boost/multi_index_container_fwd.hpp>
  28. #include <boost/multi_index/detail/access_specifier.hpp>
  29. #include <boost/multi_index/detail/adl_swap.hpp>
  30. #include <boost/multi_index/detail/base_type.hpp>
  31. #include <boost/multi_index/detail/converter.hpp>
  32. #include <boost/multi_index/detail/header_holder.hpp>
  33. #include <boost/multi_index/detail/has_tag.hpp>
  34. #include <boost/multi_index/detail/no_duplicate_tags.hpp>
  35. #include <boost/multi_index/detail/prevent_eti.hpp>
  36. #include <boost/multi_index/detail/safe_mode.hpp>
  37. #include <boost/multi_index/detail/scope_guard.hpp>
  38. #include <boost/static_assert.hpp>
  39. #include <boost/type_traits/is_same.hpp>
  40. #include <boost/utility/base_from_member.hpp>
  41. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  42. #include <boost/multi_index/detail/archive_constructed.hpp>
  43. #include <boost/serialization/nvp.hpp>
  44. #include <boost/serialization/split_member.hpp>
  45. #include <boost/throw_exception.hpp>
  46. #endif
  47. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  48. #include <boost/multi_index/detail/invariant_assert.hpp>
  49. #define BOOST_MULTI_INDEX_CHECK_INVARIANT \
  50. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  51. detail::make_obj_guard(*this,&multi_index_container::check_invariant_); \
  52. BOOST_JOIN(check_invariant_,__LINE__).touch();
  53. #else
  54. #define BOOST_MULTI_INDEX_CHECK_INVARIANT
  55. #endif
  56. namespace boost{
  57. namespace multi_index{
  58. template<typename Value,typename IndexSpecifierList,typename Allocator>
  59. class multi_index_container:
  60. private ::boost::base_from_member<
  61. typename boost::detail::allocator::rebind_to<
  62. Allocator,
  63. typename detail::multi_index_node_type<
  64. Value,IndexSpecifierList,Allocator>::type
  65. >::type>,
  66. BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
  67. typename detail::prevent_eti<
  68. Allocator,
  69. typename boost::detail::allocator::rebind_to<
  70. Allocator,
  71. typename detail::multi_index_node_type<
  72. Value,IndexSpecifierList,Allocator>::type
  73. >::type
  74. >::type::pointer,
  75. multi_index_container<Value,IndexSpecifierList,Allocator> >,
  76. public detail::multi_index_base_type<
  77. Value,IndexSpecifierList,Allocator>::type
  78. {
  79. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  80. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  81. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  82. * lifetime of const references bound to temporaries --precisely what
  83. * scopeguards are.
  84. */
  85. #pragma parse_mfunc_templ off
  86. #endif
  87. private:
  88. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  89. template <typename,typename,typename> friend class detail::index_base;
  90. template <typename,typename> friend struct detail::header_holder;
  91. template <typename,typename> friend struct detail::converter;
  92. #endif
  93. typedef typename detail::multi_index_base_type<
  94. Value,IndexSpecifierList,Allocator>::type super;
  95. typedef typename
  96. boost::detail::allocator::rebind_to<
  97. Allocator,
  98. typename super::node_type
  99. >::type node_allocator;
  100. typedef ::boost::base_from_member<
  101. node_allocator> bfm_allocator;
  102. typedef detail::header_holder<
  103. typename detail::prevent_eti<
  104. Allocator,
  105. node_allocator
  106. >::type::pointer,
  107. multi_index_container> bfm_header;
  108. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  109. /* see definition of index_type_list below */
  110. typedef typename super::index_type_list super_index_type_list;
  111. #endif
  112. public:
  113. /* All types are inherited from super, a few are explicitly
  114. * brought forward here to save us some typename's.
  115. */
  116. typedef typename super::ctor_args_list ctor_args_list;
  117. typedef IndexSpecifierList index_specifier_type_list;
  118. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  119. /* MSVC++ 6.0 chokes on moderately long index lists (around 6 indices
  120. * or more), with errors ranging from corrupt exes to duplicate
  121. * comdats. The following type hiding hack alleviates this condition;
  122. * best results combined with type hiding of the indexed_by construct
  123. * itself, as explained in the "Compiler specifics" section of
  124. * the documentation.
  125. */
  126. struct index_type_list:super_index_type_list
  127. {
  128. typedef index_type_list type;
  129. typedef typename super_index_type_list::back back;
  130. typedef mpl::v_iter<type,0> begin;
  131. typedef mpl::v_iter<
  132. type,
  133. mpl::size<super_index_type_list>::value> end;
  134. };
  135. #else
  136. typedef typename super::index_type_list index_type_list;
  137. #endif
  138. typedef typename super::iterator_type_list iterator_type_list;
  139. typedef typename super::const_iterator_type_list const_iterator_type_list;
  140. typedef typename super::value_type value_type;
  141. typedef typename super::final_allocator_type allocator_type;
  142. typedef typename super::iterator iterator;
  143. typedef typename super::const_iterator const_iterator;
  144. BOOST_STATIC_ASSERT(
  145. detail::no_duplicate_tags_in_index_list<index_type_list>::value);
  146. /* global project() needs to see this publicly */
  147. typedef typename super::node_type node_type;
  148. /* construct/copy/destroy */
  149. explicit multi_index_container(
  150. #if BOOST_WORKAROUND(__IBMCPP__,<=600)
  151. /* VisualAge seems to have an ETI issue with the default values
  152. * for arguments args_list and al.
  153. */
  154. const ctor_args_list& args_list=
  155. typename mpl::identity<multi_index_container>::type::
  156. ctor_args_list(),
  157. const allocator_type& al=
  158. typename mpl::identity<multi_index_container>::type::
  159. allocator_type()):
  160. #else
  161. const ctor_args_list& args_list=ctor_args_list(),
  162. const allocator_type& al=allocator_type()):
  163. #endif
  164. bfm_allocator(al),
  165. super(args_list,bfm_allocator::member),
  166. node_count(0)
  167. {
  168. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  169. }
  170. explicit multi_index_container(const allocator_type& al):
  171. bfm_allocator(al),
  172. super(ctor_args_list(),bfm_allocator::member),
  173. node_count(0)
  174. {
  175. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  176. }
  177. template<typename InputIterator>
  178. multi_index_container(
  179. InputIterator first,InputIterator last,
  180. #if BOOST_WORKAROUND(__IBMCPP__,<=600)
  181. /* VisualAge seems to have an ETI issue with the default values
  182. * for arguments args_list and al.
  183. */
  184. const ctor_args_list& args_list=
  185. typename mpl::identity<multi_index_container>::type::
  186. ctor_args_list(),
  187. const allocator_type& al=
  188. typename mpl::identity<multi_index_container>::type::
  189. allocator_type()):
  190. #else
  191. const ctor_args_list& args_list=ctor_args_list(),
  192. const allocator_type& al=allocator_type()):
  193. #endif
  194. bfm_allocator(al),
  195. super(args_list,bfm_allocator::member),
  196. node_count(0)
  197. {
  198. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  199. BOOST_TRY{
  200. iterator hint=super::end();
  201. for(;first!=last;++first){
  202. hint=super::make_iterator(insert_(*first,hint.get_node()).first);
  203. }
  204. }
  205. BOOST_CATCH(...){
  206. clear_();
  207. BOOST_RETHROW;
  208. }
  209. BOOST_CATCH_END
  210. }
  211. multi_index_container(
  212. const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
  213. bfm_allocator(x.bfm_allocator::member),
  214. bfm_header(),
  215. super(x),
  216. node_count(0)
  217. {
  218. copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
  219. for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
  220. map.clone(it.get_node());
  221. }
  222. super::copy_(x,map);
  223. map.release();
  224. node_count=x.size();
  225. /* Not until this point are the indices required to be consistent,
  226. * hence the position of the invariant checker.
  227. */
  228. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  229. }
  230. ~multi_index_container()
  231. {
  232. delete_all_nodes_();
  233. }
  234. multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
  235. multi_index_container<Value,IndexSpecifierList,Allocator> x)
  236. {
  237. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  238. this->swap(x);
  239. return *this;
  240. }
  241. allocator_type get_allocator()const
  242. {
  243. return allocator_type(bfm_allocator::member);
  244. }
  245. /* retrieval of indices by number */
  246. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  247. template<int N>
  248. struct nth_index
  249. {
  250. BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
  251. typedef typename mpl::at_c<index_type_list,N>::type type;
  252. };
  253. template<int N>
  254. typename nth_index<N>::type& get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
  255. {
  256. BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
  257. return *this;
  258. }
  259. template<int N>
  260. const typename nth_index<N>::type& get(
  261. BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
  262. {
  263. BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
  264. return *this;
  265. }
  266. #endif
  267. /* retrieval of indices by tag */
  268. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  269. template<typename Tag>
  270. struct index
  271. {
  272. typedef typename mpl::find_if<
  273. index_type_list,
  274. detail::has_tag<Tag>
  275. >::type iter;
  276. BOOST_STATIC_CONSTANT(
  277. bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
  278. BOOST_STATIC_ASSERT(index_found);
  279. typedef typename mpl::deref<iter>::type type;
  280. };
  281. template<typename Tag>
  282. typename index<Tag>::type& get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))
  283. {
  284. return *this;
  285. }
  286. template<typename Tag>
  287. const typename index<Tag>::type& get(
  288. BOOST_EXPLICIT_TEMPLATE_TYPE(Tag))const
  289. {
  290. return *this;
  291. }
  292. #endif
  293. /* projection of iterators by number */
  294. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  295. template<int N>
  296. struct nth_index_iterator
  297. {
  298. typedef typename nth_index<N>::type::iterator type;
  299. };
  300. template<int N>
  301. struct nth_index_const_iterator
  302. {
  303. typedef typename nth_index<N>::type::const_iterator type;
  304. };
  305. template<int N,typename IteratorType>
  306. typename nth_index_iterator<N>::type project(
  307. IteratorType it
  308. BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
  309. {
  310. typedef typename nth_index<N>::type index;
  311. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  312. BOOST_STATIC_ASSERT(
  313. (mpl::contains<iterator_type_list,IteratorType>::value));
  314. #endif
  315. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  316. BOOST_MULTI_INDEX_CHECK_IS_OWNER(
  317. it,static_cast<typename IteratorType::container_type&>(*this));
  318. return index::make_iterator(static_cast<node_type*>(it.get_node()));
  319. }
  320. template<int N,typename IteratorType>
  321. typename nth_index_const_iterator<N>::type project(
  322. IteratorType it
  323. BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))const
  324. {
  325. typedef typename nth_index<N>::type index;
  326. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  327. BOOST_STATIC_ASSERT((
  328. mpl::contains<iterator_type_list,IteratorType>::value||
  329. mpl::contains<const_iterator_type_list,IteratorType>::value));
  330. #endif
  331. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  332. BOOST_MULTI_INDEX_CHECK_IS_OWNER(
  333. it,static_cast<const typename IteratorType::container_type&>(*this));
  334. return index::make_iterator(static_cast<node_type*>(it.get_node()));
  335. }
  336. #endif
  337. /* projection of iterators by tag */
  338. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  339. template<typename Tag>
  340. struct index_iterator
  341. {
  342. typedef typename index<Tag>::type::iterator type;
  343. };
  344. template<typename Tag>
  345. struct index_const_iterator
  346. {
  347. typedef typename index<Tag>::type::const_iterator type;
  348. };
  349. template<typename Tag,typename IteratorType>
  350. typename index_iterator<Tag>::type project(
  351. IteratorType it
  352. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
  353. {
  354. typedef typename index<Tag>::type index;
  355. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  356. BOOST_STATIC_ASSERT(
  357. (mpl::contains<iterator_type_list,IteratorType>::value));
  358. #endif
  359. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  360. BOOST_MULTI_INDEX_CHECK_IS_OWNER(
  361. it,static_cast<typename IteratorType::container_type&>(*this));
  362. return index::make_iterator(static_cast<node_type*>(it.get_node()));
  363. }
  364. template<typename Tag,typename IteratorType>
  365. typename index_const_iterator<Tag>::type project(
  366. IteratorType it
  367. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))const
  368. {
  369. typedef typename index<Tag>::type index;
  370. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  371. BOOST_STATIC_ASSERT((
  372. mpl::contains<iterator_type_list,IteratorType>::value||
  373. mpl::contains<const_iterator_type_list,IteratorType>::value));
  374. #endif
  375. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  376. BOOST_MULTI_INDEX_CHECK_IS_OWNER(
  377. it,static_cast<const typename IteratorType::container_type&>(*this));
  378. return index::make_iterator(static_cast<node_type*>(it.get_node()));
  379. }
  380. #endif
  381. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  382. typedef typename super::copy_map_type copy_map_type;
  383. node_type* header()const
  384. {
  385. return &*bfm_header::member;
  386. }
  387. node_type* allocate_node()
  388. {
  389. return &*bfm_allocator::member.allocate(1);
  390. }
  391. void deallocate_node(node_type* x)
  392. {
  393. typedef typename node_allocator::pointer node_pointer;
  394. bfm_allocator::member.deallocate(static_cast<node_pointer>(x),1);
  395. }
  396. bool empty_()const
  397. {
  398. return node_count==0;
  399. }
  400. std::size_t size_()const
  401. {
  402. return node_count;
  403. }
  404. std::size_t max_size_()const
  405. {
  406. return static_cast<std::size_t >(-1);
  407. }
  408. std::pair<node_type*,bool> insert_(const Value& v)
  409. {
  410. node_type* x=allocate_node();
  411. BOOST_TRY{
  412. node_type* res=super::insert_(v,x);
  413. if(res==x){
  414. ++node_count;
  415. return std::pair<node_type*,bool>(res,true);
  416. }
  417. else{
  418. deallocate_node(x);
  419. return std::pair<node_type*,bool>(res,false);
  420. }
  421. }
  422. BOOST_CATCH(...){
  423. deallocate_node(x);
  424. BOOST_RETHROW;
  425. }
  426. BOOST_CATCH_END
  427. }
  428. std::pair<node_type*,bool> insert_(const Value& v,node_type* position)
  429. {
  430. node_type* x=allocate_node();
  431. BOOST_TRY{
  432. node_type* res=super::insert_(v,position,x);
  433. if(res==x){
  434. ++node_count;
  435. return std::pair<node_type*,bool>(res,true);
  436. }
  437. else{
  438. deallocate_node(x);
  439. return std::pair<node_type*,bool>(res,false);
  440. }
  441. }
  442. BOOST_CATCH(...){
  443. deallocate_node(x);
  444. BOOST_RETHROW;
  445. }
  446. BOOST_CATCH_END
  447. }
  448. void erase_(node_type* x)
  449. {
  450. --node_count;
  451. super::erase_(x);
  452. deallocate_node(x);
  453. }
  454. void delete_node_(node_type* x)
  455. {
  456. super::delete_node_(x);
  457. deallocate_node(x);
  458. }
  459. void delete_all_nodes_()
  460. {
  461. super::delete_all_nodes_();
  462. }
  463. void clear_()
  464. {
  465. delete_all_nodes_();
  466. super::clear_();
  467. node_count=0;
  468. }
  469. void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
  470. {
  471. if(bfm_allocator::member!=x.bfm_allocator::member){
  472. detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
  473. }
  474. std::swap(bfm_header::member,x.bfm_header::member);
  475. super::swap_(x);
  476. std::swap(node_count,x.node_count);
  477. }
  478. bool replace_(const Value& k,node_type* x)
  479. {
  480. return super::replace_(k,x);
  481. }
  482. template<typename Modifier>
  483. bool modify_(Modifier& mod,node_type* x)
  484. {
  485. mod(const_cast<value_type&>(x->value()));
  486. BOOST_TRY{
  487. if(!super::modify_(x)){
  488. deallocate_node(x);
  489. --node_count;
  490. return false;
  491. }
  492. else return true;
  493. }
  494. BOOST_CATCH(...){
  495. deallocate_node(x);
  496. --node_count;
  497. BOOST_RETHROW;
  498. }
  499. BOOST_CATCH_END
  500. }
  501. template<typename Modifier,typename Rollback>
  502. bool modify_(Modifier& mod,Rollback& back,node_type* x)
  503. {
  504. mod(const_cast<value_type&>(x->value()));
  505. bool b;
  506. BOOST_TRY{
  507. b=super::modify_rollback_(x);
  508. }
  509. BOOST_CATCH(...){
  510. BOOST_TRY{
  511. back(const_cast<value_type&>(x->value()));
  512. BOOST_RETHROW;
  513. }
  514. BOOST_CATCH(...){
  515. this->erase_(x);
  516. BOOST_RETHROW;
  517. }
  518. BOOST_CATCH_END
  519. }
  520. BOOST_CATCH_END
  521. BOOST_TRY{
  522. if(!b){
  523. back(const_cast<value_type&>(x->value()));
  524. return false;
  525. }
  526. else return true;
  527. }
  528. BOOST_CATCH(...){
  529. this->erase_(x);
  530. BOOST_RETHROW;
  531. }
  532. BOOST_CATCH_END
  533. }
  534. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  535. /* serialization */
  536. friend class boost::serialization::access;
  537. BOOST_SERIALIZATION_SPLIT_MEMBER()
  538. typedef typename super::index_saver_type index_saver_type;
  539. typedef typename super::index_loader_type index_loader_type;
  540. template<class Archive>
  541. void save(Archive& ar,const unsigned int version)const
  542. {
  543. const std::size_t s=size_();
  544. ar<<serialization::make_nvp("count",s);
  545. index_saver_type sm(bfm_allocator::member,s);
  546. for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
  547. ar<<serialization::make_nvp("item",*it);
  548. sm.add(it.get_node(),ar,version);
  549. }
  550. sm.add_track(header(),ar,version);
  551. super::save_(ar,version,sm);
  552. }
  553. template<class Archive>
  554. void load(Archive& ar,const unsigned int version)
  555. {
  556. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  557. clear_();
  558. std::size_t s;
  559. ar>>serialization::make_nvp("count",s);
  560. index_loader_type lm(bfm_allocator::member,s);
  561. for(std::size_t n=0;n<s;++n){
  562. detail::archive_constructed<Value> value("item",ar,version);
  563. std::pair<node_type*,bool> p=insert_(
  564. value.get(),super::end().get_node());
  565. if(!p.second)throw_exception(
  566. archive::archive_exception(
  567. archive::archive_exception::other_exception));
  568. ar.reset_object_address(&p.first->value(),&value.get());
  569. lm.add(p.first,ar,version);
  570. }
  571. lm.add_track(header(),ar,version);
  572. super::load_(ar,version,lm);
  573. }
  574. #endif
  575. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  576. /* invariant stuff */
  577. bool invariant_()const
  578. {
  579. return super::invariant_();
  580. }
  581. void check_invariant_()const
  582. {
  583. BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
  584. }
  585. #endif
  586. private:
  587. std::size_t node_count;
  588. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  589. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  590. #pragma parse_mfunc_templ reset
  591. #endif
  592. };
  593. /* retrieval of indices by number */
  594. template<typename MultiIndexContainer,int N>
  595. struct nth_index
  596. {
  597. BOOST_STATIC_CONSTANT(
  598. int,
  599. M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
  600. BOOST_STATIC_ASSERT(N>=0&&N<M);
  601. typedef typename mpl::at_c<
  602. typename MultiIndexContainer::index_type_list,N>::type type;
  603. };
  604. template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
  605. typename nth_index<
  606. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
  607. get(
  608. multi_index_container<Value,IndexSpecifierList,Allocator>& m
  609. BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
  610. {
  611. typedef multi_index_container<
  612. Value,IndexSpecifierList,Allocator> multi_index_type;
  613. typedef typename nth_index<
  614. multi_index_container<
  615. Value,IndexSpecifierList,Allocator>,
  616. N
  617. >::type index;
  618. BOOST_STATIC_ASSERT(N>=0&&
  619. N<
  620. mpl::size<
  621. BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
  622. >::type::value);
  623. return detail::converter<multi_index_type,index>::index(m);
  624. }
  625. template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
  626. const typename nth_index<
  627. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
  628. get(
  629. const multi_index_container<Value,IndexSpecifierList,Allocator>& m
  630. BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
  631. {
  632. typedef multi_index_container<
  633. Value,IndexSpecifierList,Allocator> multi_index_type;
  634. typedef typename nth_index<
  635. multi_index_container<
  636. Value,IndexSpecifierList,Allocator>,
  637. N
  638. >::type index;
  639. BOOST_STATIC_ASSERT(N>=0&&
  640. N<
  641. mpl::size<
  642. BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
  643. >::type::value);
  644. return detail::converter<multi_index_type,index>::index(m);
  645. }
  646. /* retrieval of indices by tag */
  647. template<typename MultiIndexContainer,typename Tag>
  648. struct index
  649. {
  650. typedef typename MultiIndexContainer::index_type_list index_type_list;
  651. typedef typename mpl::find_if<
  652. index_type_list,
  653. detail::has_tag<Tag>
  654. >::type iter;
  655. BOOST_STATIC_CONSTANT(
  656. bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
  657. BOOST_STATIC_ASSERT(index_found);
  658. typedef typename mpl::deref<iter>::type type;
  659. };
  660. template<
  661. typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
  662. >
  663. typename ::boost::multi_index::index<
  664. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
  665. get(
  666. multi_index_container<Value,IndexSpecifierList,Allocator>& m
  667. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
  668. {
  669. typedef multi_index_container<
  670. Value,IndexSpecifierList,Allocator> multi_index_type;
  671. typedef typename ::boost::multi_index::index<
  672. multi_index_container<
  673. Value,IndexSpecifierList,Allocator>,
  674. Tag
  675. >::type index;
  676. return detail::converter<multi_index_type,index>::index(m);
  677. }
  678. template<
  679. typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
  680. >
  681. const typename ::boost::multi_index::index<
  682. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
  683. get(
  684. const multi_index_container<Value,IndexSpecifierList,Allocator>& m
  685. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
  686. {
  687. typedef multi_index_container<
  688. Value,IndexSpecifierList,Allocator> multi_index_type;
  689. typedef typename ::boost::multi_index::index<
  690. multi_index_container<
  691. Value,IndexSpecifierList,Allocator>,
  692. Tag
  693. >::type index;
  694. return detail::converter<multi_index_type,index>::index(m);
  695. }
  696. /* projection of iterators by number */
  697. template<typename MultiIndexContainer,int N>
  698. struct nth_index_iterator
  699. {
  700. typedef typename detail::prevent_eti<
  701. nth_index<MultiIndexContainer,N>,
  702. typename nth_index<MultiIndexContainer,N>::type>::type::iterator type;
  703. };
  704. template<typename MultiIndexContainer,int N>
  705. struct nth_index_const_iterator
  706. {
  707. typedef typename detail::prevent_eti<
  708. nth_index<MultiIndexContainer,N>,
  709. typename nth_index<MultiIndexContainer,N>::type
  710. >::type::const_iterator type;
  711. };
  712. template<
  713. int N,typename IteratorType,
  714. typename Value,typename IndexSpecifierList,typename Allocator>
  715. typename nth_index_iterator<
  716. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
  717. project(
  718. multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  719. IteratorType it
  720. BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
  721. {
  722. typedef multi_index_container<
  723. Value,IndexSpecifierList,Allocator> multi_index_type;
  724. typedef typename nth_index<multi_index_type,N>::type index;
  725. #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
  726. (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
  727. BOOST_STATIC_ASSERT((
  728. mpl::contains<
  729. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  730. IteratorType>::value));
  731. #endif
  732. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  733. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  734. typedef detail::converter<
  735. multi_index_type,
  736. BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
  737. BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
  738. #endif
  739. return detail::converter<multi_index_type,index>::iterator(
  740. m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
  741. }
  742. template<
  743. int N,typename IteratorType,
  744. typename Value,typename IndexSpecifierList,typename Allocator>
  745. typename nth_index_const_iterator<
  746. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
  747. project(
  748. const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  749. IteratorType it
  750. BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int,N))
  751. {
  752. typedef multi_index_container<
  753. Value,IndexSpecifierList,Allocator> multi_index_type;
  754. typedef typename nth_index<multi_index_type,N>::type index;
  755. #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
  756. (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
  757. BOOST_STATIC_ASSERT((
  758. mpl::contains<
  759. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  760. IteratorType>::value||
  761. mpl::contains<
  762. BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
  763. IteratorType>::value));
  764. #endif
  765. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  766. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  767. typedef detail::converter<
  768. multi_index_type,
  769. BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
  770. BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
  771. #endif
  772. return detail::converter<multi_index_type,index>::const_iterator(
  773. m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
  774. }
  775. /* projection of iterators by tag */
  776. template<typename MultiIndexContainer,typename Tag>
  777. struct index_iterator
  778. {
  779. typedef typename ::boost::multi_index::index<
  780. MultiIndexContainer,Tag>::type::iterator type;
  781. };
  782. template<typename MultiIndexContainer,typename Tag>
  783. struct index_const_iterator
  784. {
  785. typedef typename ::boost::multi_index::index<
  786. MultiIndexContainer,Tag>::type::const_iterator type;
  787. };
  788. template<
  789. typename Tag,typename IteratorType,
  790. typename Value,typename IndexSpecifierList,typename Allocator>
  791. typename index_iterator<
  792. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
  793. project(
  794. multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  795. IteratorType it
  796. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
  797. {
  798. typedef multi_index_container<
  799. Value,IndexSpecifierList,Allocator> multi_index_type;
  800. typedef typename ::boost::multi_index::index<
  801. multi_index_type,Tag>::type index;
  802. #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
  803. (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
  804. BOOST_STATIC_ASSERT((
  805. mpl::contains<
  806. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  807. IteratorType>::value));
  808. #endif
  809. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  810. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  811. typedef detail::converter<
  812. multi_index_type,
  813. BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
  814. BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
  815. #endif
  816. return detail::converter<multi_index_type,index>::iterator(
  817. m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
  818. }
  819. template<
  820. typename Tag,typename IteratorType,
  821. typename Value,typename IndexSpecifierList,typename Allocator>
  822. typename index_const_iterator<
  823. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
  824. project(
  825. const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  826. IteratorType it
  827. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag))
  828. {
  829. typedef multi_index_container<
  830. Value,IndexSpecifierList,Allocator> multi_index_type;
  831. typedef typename ::boost::multi_index::index<
  832. multi_index_type,Tag>::type index;
  833. #if (!defined(BOOST_MSVC)||!(BOOST_MSVC<1310))&& /* MSVC++ 6.0/7.0 fails */\
  834. (!defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580)) /* as does Sun C++ 5.7 */
  835. BOOST_STATIC_ASSERT((
  836. mpl::contains<
  837. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  838. IteratorType>::value||
  839. mpl::contains<
  840. BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
  841. IteratorType>::value));
  842. #endif
  843. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  844. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  845. typedef detail::converter<
  846. multi_index_type,
  847. BOOST_DEDUCED_TYPENAME IteratorType::container_type> converter;
  848. BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,converter::index(m));
  849. #endif
  850. return detail::converter<multi_index_type,index>::const_iterator(
  851. m,static_cast<typename multi_index_type::node_type*>(it.get_node()));
  852. }
  853. /* Comparison. Simple forward to first index. */
  854. template<
  855. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  856. typename Value2,typename IndexSpecifierList2,typename Allocator2
  857. >
  858. bool operator==(
  859. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  860. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  861. {
  862. return get<0>(x)==get<0>(y);
  863. }
  864. template<
  865. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  866. typename Value2,typename IndexSpecifierList2,typename Allocator2
  867. >
  868. bool operator<(
  869. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  870. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  871. {
  872. return get<0>(x)<get<0>(y);
  873. }
  874. template<
  875. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  876. typename Value2,typename IndexSpecifierList2,typename Allocator2
  877. >
  878. bool operator!=(
  879. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  880. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  881. {
  882. return get<0>(x)!=get<0>(y);
  883. }
  884. template<
  885. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  886. typename Value2,typename IndexSpecifierList2,typename Allocator2
  887. >
  888. bool operator>(
  889. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  890. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  891. {
  892. return get<0>(x)>get<0>(y);
  893. }
  894. template<
  895. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  896. typename Value2,typename IndexSpecifierList2,typename Allocator2
  897. >
  898. bool operator>=(
  899. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  900. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  901. {
  902. return get<0>(x)>=get<0>(y);
  903. }
  904. template<
  905. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  906. typename Value2,typename IndexSpecifierList2,typename Allocator2
  907. >
  908. bool operator<=(
  909. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  910. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  911. {
  912. return get<0>(x)<=get<0>(y);
  913. }
  914. /* specialized algorithms */
  915. template<typename Value,typename IndexSpecifierList,typename Allocator>
  916. void swap(
  917. multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  918. multi_index_container<Value,IndexSpecifierList,Allocator>& y)
  919. {
  920. x.swap(y);
  921. }
  922. } /* namespace multi_index */
  923. /* Associated global functions are promoted to namespace boost, except
  924. * comparison operators and swap, which are meant to be Koenig looked-up.
  925. */
  926. using multi_index::get;
  927. using multi_index::project;
  928. } /* namespace boost */
  929. #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
  930. #endif