multi_index_container.hpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597
  1. /* Multiply indexed container.
  2. *
  3. * Copyright 2003-2023 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)
  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/core/addressof.hpp>
  18. #include <boost/core/no_exceptions_support.hpp>
  19. #include <boost/detail/workaround.hpp>
  20. #include <boost/move/core.hpp>
  21. #include <boost/move/utility_core.hpp>
  22. #include <boost/mpl/at.hpp>
  23. #include <boost/mpl/contains.hpp>
  24. #include <boost/mpl/find_if.hpp>
  25. #include <boost/mpl/identity.hpp>
  26. #include <boost/mpl/int.hpp>
  27. #include <boost/mpl/size.hpp>
  28. #include <boost/mpl/deref.hpp>
  29. #include <boost/multi_index_container_fwd.hpp>
  30. #include <boost/multi_index/detail/access_specifier.hpp>
  31. #include <boost/multi_index/detail/adl_swap.hpp>
  32. #include <boost/multi_index/detail/allocator_traits.hpp>
  33. #include <boost/multi_index/detail/base_type.hpp>
  34. #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
  35. #include <boost/multi_index/detail/converter.hpp>
  36. #include <boost/multi_index/detail/header_holder.hpp>
  37. #include <boost/multi_index/detail/has_tag.hpp>
  38. #include <boost/multi_index/detail/invalidate_iterators.hpp>
  39. #include <boost/multi_index/detail/no_duplicate_tags.hpp>
  40. #include <boost/multi_index/detail/safe_mode.hpp>
  41. #include <boost/multi_index/detail/scope_guard.hpp>
  42. #include <boost/multi_index/detail/vartempl_support.hpp>
  43. #include <boost/static_assert.hpp>
  44. #include <boost/type_traits/integral_constant.hpp>
  45. #include <boost/type_traits/is_same.hpp>
  46. #include <boost/utility/base_from_member.hpp>
  47. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  48. #include <initializer_list>
  49. #endif
  50. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  51. #include <boost/core/serialization.hpp>
  52. #include <boost/multi_index/detail/archive_constructed.hpp>
  53. #include <boost/multi_index/detail/bad_archive_exception.hpp>
  54. #include <boost/multi_index/detail/serialization_version.hpp>
  55. #include <boost/throw_exception.hpp>
  56. #if defined(BOOST_MULTI_INDEX_ENABLE_SERIALIZATION_COMPATIBILITY_V2)
  57. #define BOOST_MULTI_INDEX_BLOCK_BOOSTDEP_HEADER \
  58. <boost/serialization/collection_size_type.hpp>
  59. #include BOOST_MULTI_INDEX_BLOCK_BOOSTDEP_HEADER
  60. #undef BOOST_MULTI_INDEX_BLOCK_BOOSTDEP_HEADER
  61. #endif
  62. #endif
  63. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  64. #include <boost/multi_index/detail/invariant_assert.hpp>
  65. #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x) \
  66. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  67. detail::make_obj_guard(x,&multi_index_container::check_invariant_); \
  68. BOOST_JOIN(check_invariant_,__LINE__).touch();
  69. #define BOOST_MULTI_INDEX_CHECK_INVARIANT \
  70. BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(*this)
  71. #else
  72. #define BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x)
  73. #define BOOST_MULTI_INDEX_CHECK_INVARIANT
  74. #endif
  75. namespace boost{
  76. namespace multi_index{
  77. namespace detail{
  78. struct unequal_alloc_move_ctor_tag{};
  79. } /* namespace multi_index::detail */
  80. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  81. #pragma warning(push)
  82. #pragma warning(disable:4522) /* spurious warning on multiple operator=()'s */
  83. #endif
  84. template<typename Value,typename IndexSpecifierList,typename Allocator>
  85. class multi_index_container:
  86. private ::boost::base_from_member<
  87. typename detail::rebind_alloc_for<
  88. Allocator,
  89. typename detail::multi_index_node_type<
  90. Value,IndexSpecifierList,Allocator>::type
  91. >::type
  92. >,
  93. BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
  94. typename detail::allocator_traits<
  95. typename detail::rebind_alloc_for<
  96. Allocator,
  97. typename detail::multi_index_node_type<
  98. Value,IndexSpecifierList,Allocator>::type
  99. >::type
  100. >::pointer,
  101. multi_index_container<Value,IndexSpecifierList,Allocator> >,
  102. public detail::multi_index_base_type<
  103. Value,IndexSpecifierList,Allocator>::type
  104. {
  105. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  106. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  107. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  108. * lifetime of const references bound to temporaries --precisely what
  109. * scopeguards are.
  110. */
  111. #pragma parse_mfunc_templ off
  112. #endif
  113. private:
  114. BOOST_COPYABLE_AND_MOVABLE(multi_index_container)
  115. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  116. template <typename,typename,typename> friend class detail::index_base;
  117. template <typename,typename> friend struct detail::header_holder;
  118. template <typename,typename> friend struct detail::converter;
  119. #endif
  120. typedef typename detail::multi_index_base_type<
  121. Value,IndexSpecifierList,Allocator>::type super;
  122. typedef typename detail::rebind_alloc_for<
  123. Allocator,
  124. typename super::index_node_type
  125. >::type node_allocator;
  126. typedef detail::allocator_traits<node_allocator> node_alloc_traits;
  127. typedef typename node_alloc_traits::pointer node_pointer;
  128. typedef ::boost::base_from_member<
  129. node_allocator> bfm_allocator;
  130. typedef detail::header_holder<
  131. node_pointer,
  132. multi_index_container> bfm_header;
  133. public:
  134. /* All types are inherited from super, a few are explicitly
  135. * brought forward here to save us some typename's.
  136. */
  137. typedef typename super::ctor_args_list ctor_args_list;
  138. typedef IndexSpecifierList index_specifier_type_list;
  139. typedef typename super::index_type_list index_type_list;
  140. typedef typename super::iterator_type_list iterator_type_list;
  141. typedef typename super::const_iterator_type_list const_iterator_type_list;
  142. typedef typename super::value_type value_type;
  143. typedef typename super::final_allocator_type allocator_type;
  144. typedef typename super::size_type size_type;
  145. typedef typename super::iterator iterator;
  146. typedef typename super::const_iterator const_iterator;
  147. BOOST_STATIC_ASSERT(
  148. detail::no_duplicate_tags_in_index_list<index_type_list>::value);
  149. /* global project() needs to see this publicly */
  150. typedef typename super::final_node_type final_node_type;
  151. /* construct/copy/destroy */
  152. multi_index_container():
  153. bfm_allocator(allocator_type()),
  154. super(ctor_args_list(),bfm_allocator::member),
  155. node_count(0)
  156. {
  157. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  158. }
  159. explicit multi_index_container(
  160. const ctor_args_list& args_list,
  161. #if BOOST_WORKAROUND(__IBMCPP__,<=600)
  162. /* VisualAge seems to have an ETI issue with the default value for
  163. * argument al.
  164. */
  165. const allocator_type& al=
  166. typename mpl::identity<multi_index_container>::type::
  167. allocator_type()):
  168. #else
  169. const allocator_type& al=allocator_type()):
  170. #endif
  171. bfm_allocator(al),
  172. super(args_list,bfm_allocator::member),
  173. node_count(0)
  174. {
  175. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  176. }
  177. explicit multi_index_container(const allocator_type& al):
  178. bfm_allocator(al),
  179. super(ctor_args_list(),bfm_allocator::member),
  180. node_count(0)
  181. {
  182. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  183. }
  184. template<typename InputIterator>
  185. multi_index_container(
  186. InputIterator first,InputIterator last,
  187. #if BOOST_WORKAROUND(__IBMCPP__,<=600)
  188. /* VisualAge seems to have an ETI issue with the default values
  189. * for arguments args_list and al.
  190. */
  191. const ctor_args_list& args_list=
  192. typename mpl::identity<multi_index_container>::type::
  193. ctor_args_list(),
  194. const allocator_type& al=
  195. typename mpl::identity<multi_index_container>::type::
  196. allocator_type()):
  197. #else
  198. const ctor_args_list& args_list=ctor_args_list(),
  199. const allocator_type& al=allocator_type()):
  200. #endif
  201. bfm_allocator(al),
  202. super(args_list,bfm_allocator::member),
  203. node_count(0)
  204. {
  205. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  206. BOOST_TRY{
  207. iterator hint=super::end();
  208. for(;first!=last;++first){
  209. hint=super::make_iterator(
  210. insert_ref_(*first,hint.get_node()).first);
  211. ++hint;
  212. }
  213. }
  214. BOOST_CATCH(...){
  215. clear_();
  216. BOOST_RETHROW;
  217. }
  218. BOOST_CATCH_END
  219. }
  220. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  221. multi_index_container(
  222. std::initializer_list<Value> list,
  223. const ctor_args_list& args_list=ctor_args_list(),
  224. const allocator_type& al=allocator_type()):
  225. bfm_allocator(al),
  226. super(args_list,bfm_allocator::member),
  227. node_count(0)
  228. {
  229. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  230. BOOST_TRY{
  231. typedef const Value* init_iterator;
  232. iterator hint=super::end();
  233. for(init_iterator first=list.begin(),last=list.end();
  234. first!=last;++first){
  235. hint=super::make_iterator(insert_(*first,hint.get_node()).first);
  236. ++hint;
  237. }
  238. }
  239. BOOST_CATCH(...){
  240. clear_();
  241. BOOST_RETHROW;
  242. }
  243. BOOST_CATCH_END
  244. }
  245. #endif
  246. multi_index_container(
  247. const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
  248. bfm_allocator(
  249. node_alloc_traits::select_on_container_copy_construction(
  250. x.bfm_allocator::member)),
  251. bfm_header(),
  252. super(x),
  253. node_count(0)
  254. {
  255. copy_construct_from(x);
  256. }
  257. multi_index_container(BOOST_RV_REF(multi_index_container) x):
  258. bfm_allocator(boost::move(x.bfm_allocator::member)),
  259. bfm_header(),
  260. super(x,detail::do_not_copy_elements_tag()),
  261. node_count(0)
  262. {
  263. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  264. BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
  265. swap_elements_(x);
  266. }
  267. multi_index_container(
  268. const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  269. const allocator_type& al):
  270. bfm_allocator(al),
  271. bfm_header(),
  272. super(x),
  273. node_count(0)
  274. {
  275. copy_construct_from(x);
  276. }
  277. multi_index_container(
  278. BOOST_RV_REF(multi_index_container) x,const allocator_type& al):
  279. bfm_allocator(al),
  280. bfm_header(),
  281. super(x,detail::do_not_copy_elements_tag()),
  282. node_count(0)
  283. {
  284. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  285. BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
  286. if(al==x.get_allocator()){
  287. swap_elements_(x);
  288. }
  289. else{
  290. multi_index_container y(x,al,detail::unequal_alloc_move_ctor_tag());
  291. swap_elements_(y);
  292. }
  293. }
  294. ~multi_index_container()
  295. {
  296. delete_all_nodes_();
  297. }
  298. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  299. /* As per http://www.boost.org/doc/html/move/emulation_limitations.html
  300. * #move.emulation_limitations.assignment_operator
  301. */
  302. multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
  303. const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
  304. {
  305. multi_index_container y(
  306. x,
  307. node_alloc_traits::propagate_on_container_copy_assignment::value?
  308. x.get_allocator():this->get_allocator());
  309. swap_(y,boost::true_type() /* swap_allocators */);
  310. return *this;
  311. }
  312. #endif
  313. multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
  314. BOOST_COPY_ASSIGN_REF(multi_index_container) x)
  315. {
  316. multi_index_container y(
  317. x,
  318. node_alloc_traits::propagate_on_container_copy_assignment::value?
  319. x.get_allocator():this->get_allocator());
  320. swap_(y,boost::true_type() /* swap_allocators */);
  321. return *this;
  322. }
  323. multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
  324. BOOST_RV_REF(multi_index_container) x)
  325. {
  326. #include <boost/multi_index/detail/define_if_constexpr_macro.hpp>
  327. BOOST_MULTI_INDEX_IF_CONSTEXPR(
  328. node_alloc_traits::propagate_on_container_move_assignment::value){
  329. swap_(x,boost::true_type() /* swap_allocators */);
  330. }
  331. else if(this->get_allocator()==x.get_allocator()){
  332. swap_(x,boost::false_type() /* swap_allocators */);
  333. }
  334. else{
  335. multi_index_container y(boost::move(x),this->get_allocator());
  336. swap_(y,boost::false_type() /* swap_allocators */);
  337. }
  338. return *this;
  339. #include <boost/multi_index/detail/undef_if_constexpr_macro.hpp>
  340. }
  341. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  342. multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
  343. std::initializer_list<Value> list)
  344. {
  345. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  346. typedef const Value* init_iterator;
  347. multi_index_container x(*this,detail::do_not_copy_elements_tag());
  348. iterator hint=x.end();
  349. for(init_iterator first=list.begin(),last=list.end();
  350. first!=last;++first){
  351. hint=x.make_iterator(x.insert_(*first,hint.get_node()).first);
  352. ++hint;
  353. }
  354. x.swap_elements_(*this);
  355. return*this;
  356. }
  357. #endif
  358. allocator_type get_allocator()const BOOST_NOEXCEPT
  359. {
  360. return allocator_type(bfm_allocator::member);
  361. }
  362. /* retrieval of indices by number */
  363. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  364. template<int N>
  365. struct nth_index
  366. {
  367. BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
  368. typedef typename mpl::at_c<index_type_list,N>::type type;
  369. };
  370. template<int N>
  371. typename nth_index<N>::type& get()BOOST_NOEXCEPT
  372. {
  373. BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
  374. return *this;
  375. }
  376. template<int N>
  377. const typename nth_index<N>::type& get()const BOOST_NOEXCEPT
  378. {
  379. BOOST_STATIC_ASSERT(N>=0&&N<mpl::size<index_type_list>::type::value);
  380. return *this;
  381. }
  382. #endif
  383. /* retrieval of indices by tag */
  384. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  385. template<typename Tag>
  386. struct index
  387. {
  388. typedef typename mpl::find_if<
  389. index_type_list,
  390. detail::has_tag<Tag>
  391. >::type iter;
  392. BOOST_STATIC_CONSTANT(
  393. bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
  394. BOOST_STATIC_ASSERT(index_found);
  395. typedef typename mpl::deref<iter>::type type;
  396. };
  397. template<typename Tag>
  398. typename index<Tag>::type& get()BOOST_NOEXCEPT
  399. {
  400. return *this;
  401. }
  402. template<typename Tag>
  403. const typename index<Tag>::type& get()const BOOST_NOEXCEPT
  404. {
  405. return *this;
  406. }
  407. #endif
  408. /* projection of iterators by number */
  409. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  410. template<int N>
  411. struct nth_index_iterator
  412. {
  413. typedef typename nth_index<N>::type::iterator type;
  414. };
  415. template<int N>
  416. struct nth_index_const_iterator
  417. {
  418. typedef typename nth_index<N>::type::const_iterator type;
  419. };
  420. template<int N,typename IteratorType>
  421. typename nth_index_iterator<N>::type project(IteratorType it)
  422. {
  423. typedef typename nth_index<N>::type index_type;
  424. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  425. BOOST_STATIC_ASSERT(
  426. (mpl::contains<iterator_type_list,IteratorType>::value));
  427. #endif
  428. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  429. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
  430. return index_type::make_iterator(
  431. static_cast<final_node_type*>(it.get_node()));
  432. }
  433. template<int N,typename IteratorType>
  434. typename nth_index_const_iterator<N>::type project(IteratorType it)const
  435. {
  436. typedef typename nth_index<N>::type index_type;
  437. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  438. BOOST_STATIC_ASSERT((
  439. mpl::contains<iterator_type_list,IteratorType>::value||
  440. mpl::contains<const_iterator_type_list,IteratorType>::value));
  441. #endif
  442. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  443. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
  444. return index_type::make_iterator(
  445. static_cast<final_node_type*>(it.get_node()));
  446. }
  447. #endif
  448. /* projection of iterators by tag */
  449. #if !defined(BOOST_NO_MEMBER_TEMPLATES)
  450. template<typename Tag>
  451. struct index_iterator
  452. {
  453. typedef typename index<Tag>::type::iterator type;
  454. };
  455. template<typename Tag>
  456. struct index_const_iterator
  457. {
  458. typedef typename index<Tag>::type::const_iterator type;
  459. };
  460. template<typename Tag,typename IteratorType>
  461. typename index_iterator<Tag>::type project(IteratorType it)
  462. {
  463. typedef typename index<Tag>::type index_type;
  464. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  465. BOOST_STATIC_ASSERT(
  466. (mpl::contains<iterator_type_list,IteratorType>::value));
  467. #endif
  468. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  469. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
  470. return index_type::make_iterator(
  471. static_cast<final_node_type*>(it.get_node()));
  472. }
  473. template<typename Tag,typename IteratorType>
  474. typename index_const_iterator<Tag>::type project(IteratorType it)const
  475. {
  476. typedef typename index<Tag>::type index_type;
  477. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* fails in Sun C++ 5.7 */
  478. BOOST_STATIC_ASSERT((
  479. mpl::contains<iterator_type_list,IteratorType>::value||
  480. mpl::contains<const_iterator_type_list,IteratorType>::value));
  481. #endif
  482. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  483. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,*this);
  484. return index_type::make_iterator(
  485. static_cast<final_node_type*>(it.get_node()));
  486. }
  487. #endif
  488. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  489. typedef typename super::final_node_handle_type final_node_handle_type;
  490. typedef typename super::copy_map_type copy_map_type;
  491. multi_index_container(
  492. multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  493. const allocator_type& al,
  494. detail::unequal_alloc_move_ctor_tag):
  495. bfm_allocator(al),
  496. bfm_header(),
  497. super(x),
  498. node_count(0)
  499. {
  500. BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
  501. BOOST_TRY{
  502. copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
  503. for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
  504. map.move_clone(it.get_node());
  505. }
  506. super::copy_(x,map);
  507. map.release();
  508. node_count=x.size();
  509. x.clear();
  510. }
  511. BOOST_CATCH(...){
  512. x.clear();
  513. BOOST_RETHROW;
  514. }
  515. BOOST_CATCH_END
  516. /* Not until this point are the indices required to be consistent,
  517. * hence the position of the invariant checker.
  518. */
  519. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  520. }
  521. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  522. multi_index_container(
  523. const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  524. detail::do_not_copy_elements_tag):
  525. bfm_allocator(x.bfm_allocator::member),
  526. bfm_header(),
  527. super(x,detail::do_not_copy_elements_tag()),
  528. node_count(0)
  529. {
  530. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  531. }
  532. #endif
  533. void copy_construct_from(
  534. const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
  535. {
  536. copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
  537. for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
  538. map.copy_clone(it.get_node());
  539. }
  540. super::copy_(x,map);
  541. map.release();
  542. node_count=x.size();
  543. /* Not until this point are the indices required to be consistent,
  544. * hence the position of the invariant checker.
  545. */
  546. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  547. }
  548. final_node_type* header()const
  549. {
  550. return &*bfm_header::member;
  551. }
  552. final_node_type* allocate_node()
  553. {
  554. return &*node_alloc_traits::allocate(bfm_allocator::member,1);
  555. }
  556. void deallocate_node(final_node_type* x)
  557. {
  558. node_alloc_traits::deallocate(
  559. bfm_allocator::member,static_cast<node_pointer>(x),1);
  560. }
  561. void construct_value(final_node_type* x,const Value& v)
  562. {
  563. node_alloc_traits::construct(
  564. bfm_allocator::member,boost::addressof(x->value()),v);
  565. }
  566. void construct_value(final_node_type* x,BOOST_RV_REF(Value) v)
  567. {
  568. node_alloc_traits::construct(
  569. bfm_allocator::member,boost::addressof(x->value()),boost::move(v));
  570. }
  571. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
  572. void,construct_value,vartempl_construct_value_impl,final_node_type*,x)
  573. void destroy_value(final_node_type* x)
  574. {
  575. node_alloc_traits::destroy(
  576. bfm_allocator::member,boost::addressof(x->value()));
  577. }
  578. bool empty_()const
  579. {
  580. return node_count==0;
  581. }
  582. size_type size_()const
  583. {
  584. return node_count;
  585. }
  586. size_type max_size_()const
  587. {
  588. return static_cast<size_type>(-1);
  589. }
  590. template<typename Variant>
  591. std::pair<final_node_type*,bool> insert_(const Value& v,Variant variant)
  592. {
  593. final_node_type* x=0;
  594. final_node_type* res=super::insert_(v,x,variant);
  595. if(res==x){
  596. ++node_count;
  597. return std::pair<final_node_type*,bool>(res,true);
  598. }
  599. else{
  600. return std::pair<final_node_type*,bool>(res,false);
  601. }
  602. }
  603. std::pair<final_node_type*,bool> insert_(const Value& v)
  604. {
  605. return insert_(v,detail::lvalue_tag());
  606. }
  607. std::pair<final_node_type*,bool> insert_rv_(const Value& v)
  608. {
  609. return insert_(v,detail::rvalue_tag());
  610. }
  611. template<typename T>
  612. std::pair<final_node_type*,bool> insert_ref_(T& t)
  613. {
  614. final_node_type* x=allocate_node();
  615. BOOST_TRY{
  616. construct_value(x,t);
  617. BOOST_TRY{
  618. final_node_type* res=super::insert_(
  619. x->value(),x,detail::emplaced_tag());
  620. if(res==x){
  621. ++node_count;
  622. return std::pair<final_node_type*,bool>(res,true);
  623. }
  624. else{
  625. delete_node_(x);
  626. return std::pair<final_node_type*,bool>(res,false);
  627. }
  628. }
  629. BOOST_CATCH(...){
  630. destroy_value(x);
  631. BOOST_RETHROW;
  632. }
  633. BOOST_CATCH_END
  634. }
  635. BOOST_CATCH(...){
  636. deallocate_node(x);
  637. BOOST_RETHROW;
  638. }
  639. BOOST_CATCH_END
  640. }
  641. std::pair<final_node_type*,bool> insert_ref_(const value_type& x)
  642. {
  643. return insert_(x);
  644. }
  645. std::pair<final_node_type*,bool> insert_ref_(value_type& x)
  646. {
  647. return insert_(x);
  648. }
  649. std::pair<final_node_type*,bool> insert_nh_(final_node_handle_type& nh)
  650. {
  651. if(!nh)return std::pair<final_node_type*,bool>(header(),false);
  652. else{
  653. final_node_type* x=nh.node;
  654. final_node_type* res=super::insert_(
  655. x->value(),x,detail::emplaced_tag());
  656. if(res==x){
  657. nh.release_node();
  658. ++node_count;
  659. return std::pair<final_node_type*,bool>(res,true);
  660. }
  661. else return std::pair<final_node_type*,bool>(res,false);
  662. }
  663. }
  664. template<typename Index>
  665. std::pair<final_node_type*,bool> transfer_(Index& x,final_node_type* n)
  666. {
  667. final_node_type* res=super::insert_(n->value(),n,&super::final(x));
  668. if(res==n){
  669. ++node_count;
  670. return std::pair<final_node_type*,bool>(res,true);
  671. }
  672. else{
  673. return std::pair<final_node_type*,bool>(res,false);
  674. }
  675. }
  676. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  677. std::pair<final_node_type*,bool> emplace_(
  678. BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  679. {
  680. final_node_type* x=allocate_node();
  681. BOOST_TRY{
  682. construct_value(x,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  683. BOOST_TRY{
  684. final_node_type* res=super::insert_(
  685. x->value(),x,detail::emplaced_tag());
  686. if(res==x){
  687. ++node_count;
  688. return std::pair<final_node_type*,bool>(res,true);
  689. }
  690. else{
  691. delete_node_(x);
  692. return std::pair<final_node_type*,bool>(res,false);
  693. }
  694. }
  695. BOOST_CATCH(...){
  696. destroy_value(x);
  697. BOOST_RETHROW;
  698. }
  699. BOOST_CATCH_END
  700. }
  701. BOOST_CATCH(...){
  702. deallocate_node(x);
  703. BOOST_RETHROW;
  704. }
  705. BOOST_CATCH_END
  706. }
  707. template<typename Variant>
  708. std::pair<final_node_type*,bool> insert_(
  709. const Value& v,final_node_type* position,Variant variant)
  710. {
  711. final_node_type* x=0;
  712. final_node_type* res=super::insert_(v,position,x,variant);
  713. if(res==x){
  714. ++node_count;
  715. return std::pair<final_node_type*,bool>(res,true);
  716. }
  717. else{
  718. return std::pair<final_node_type*,bool>(res,false);
  719. }
  720. }
  721. std::pair<final_node_type*,bool> insert_(
  722. const Value& v,final_node_type* position)
  723. {
  724. return insert_(v,position,detail::lvalue_tag());
  725. }
  726. std::pair<final_node_type*,bool> insert_rv_(
  727. const Value& v,final_node_type* position)
  728. {
  729. return insert_(v,position,detail::rvalue_tag());
  730. }
  731. template<typename T>
  732. std::pair<final_node_type*,bool> insert_ref_(
  733. T& t,final_node_type* position)
  734. {
  735. final_node_type* x=allocate_node();
  736. BOOST_TRY{
  737. construct_value(x,t);
  738. BOOST_TRY{
  739. final_node_type* res=super::insert_(
  740. x->value(),position,x,detail::emplaced_tag());
  741. if(res==x){
  742. ++node_count;
  743. return std::pair<final_node_type*,bool>(res,true);
  744. }
  745. else{
  746. delete_node_(x);
  747. return std::pair<final_node_type*,bool>(res,false);
  748. }
  749. }
  750. BOOST_CATCH(...){
  751. destroy_value(x);
  752. BOOST_RETHROW;
  753. }
  754. BOOST_CATCH_END
  755. }
  756. BOOST_CATCH(...){
  757. deallocate_node(x);
  758. BOOST_RETHROW;
  759. }
  760. BOOST_CATCH_END
  761. }
  762. std::pair<final_node_type*,bool> insert_ref_(
  763. const value_type& x,final_node_type* position)
  764. {
  765. return insert_(x,position);
  766. }
  767. std::pair<final_node_type*,bool> insert_ref_(
  768. value_type& x,final_node_type* position)
  769. {
  770. return insert_(x,position);
  771. }
  772. std::pair<final_node_type*,bool> insert_nh_(
  773. final_node_handle_type& nh,final_node_type* position)
  774. {
  775. if(!nh)return std::pair<final_node_type*,bool>(header(),false);
  776. else{
  777. final_node_type* x=nh.node;
  778. final_node_type* res=super::insert_(
  779. x->value(),position,x,detail::emplaced_tag());
  780. if(res==x){
  781. nh.release_node();
  782. ++node_count;
  783. return std::pair<final_node_type*,bool>(res,true);
  784. }
  785. else return std::pair<final_node_type*,bool>(res,false);
  786. }
  787. }
  788. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  789. std::pair<final_node_type*,bool> emplace_hint_(
  790. final_node_type* position,
  791. BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  792. {
  793. final_node_type* x=allocate_node();
  794. BOOST_TRY{
  795. construct_value(x,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  796. BOOST_TRY{
  797. final_node_type* res=super::insert_(
  798. x->value(),position,x,detail::emplaced_tag());
  799. if(res==x){
  800. ++node_count;
  801. return std::pair<final_node_type*,bool>(res,true);
  802. }
  803. else{
  804. delete_node_(x);
  805. return std::pair<final_node_type*,bool>(res,false);
  806. }
  807. }
  808. BOOST_CATCH(...){
  809. destroy_value(x);
  810. BOOST_RETHROW;
  811. }
  812. BOOST_CATCH_END
  813. }
  814. BOOST_CATCH(...){
  815. deallocate_node(x);
  816. BOOST_RETHROW;
  817. }
  818. BOOST_CATCH_END
  819. }
  820. final_node_handle_type extract_(final_node_type* x)
  821. {
  822. --node_count;
  823. super::extract_(x,detail::invalidate_iterators());
  824. return final_node_handle_type(x,get_allocator());
  825. }
  826. template<typename Dst>
  827. void extract_for_transfer_(final_node_type* x,Dst dst)
  828. {
  829. --node_count;
  830. super::extract_(x,dst);
  831. }
  832. void erase_(final_node_type* x)
  833. {
  834. --node_count;
  835. super::extract_(x,detail::invalidate_iterators());
  836. delete_node_(x);
  837. }
  838. void delete_node_(final_node_type* x)
  839. {
  840. destroy_value(x);
  841. deallocate_node(x);
  842. }
  843. void delete_all_nodes_()
  844. {
  845. super::delete_all_nodes_();
  846. }
  847. void clear_()
  848. {
  849. delete_all_nodes_();
  850. super::clear_();
  851. node_count=0;
  852. }
  853. template<typename Index>
  854. void transfer_range_(
  855. Index& x,
  856. BOOST_DEDUCED_TYPENAME Index::iterator first,
  857. BOOST_DEDUCED_TYPENAME Index::iterator last)
  858. {
  859. while(first!=last){
  860. transfer_(x,static_cast<final_node_type*>((first++).get_node()));
  861. }
  862. }
  863. void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
  864. {
  865. swap_(
  866. x,
  867. boost::integral_constant<
  868. bool,node_alloc_traits::propagate_on_container_swap::value>());
  869. }
  870. void swap_(
  871. multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  872. boost::true_type swap_allocators)
  873. {
  874. detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
  875. std::swap(bfm_header::member,x.bfm_header::member);
  876. super::swap_(x,swap_allocators);
  877. std::swap(node_count,x.node_count);
  878. }
  879. void swap_(
  880. multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  881. boost::false_type swap_allocators)
  882. {
  883. std::swap(bfm_header::member,x.bfm_header::member);
  884. super::swap_(x,swap_allocators);
  885. std::swap(node_count,x.node_count);
  886. }
  887. void swap_elements_(
  888. multi_index_container<Value,IndexSpecifierList,Allocator>& x)
  889. {
  890. std::swap(bfm_header::member,x.bfm_header::member);
  891. super::swap_elements_(x);
  892. std::swap(node_count,x.node_count);
  893. }
  894. bool replace_(const Value& k,final_node_type* x)
  895. {
  896. return super::replace_(k,x,detail::lvalue_tag());
  897. }
  898. bool replace_rv_(const Value& k,final_node_type* x)
  899. {
  900. return super::replace_(k,x,detail::rvalue_tag());
  901. }
  902. template<typename Modifier>
  903. bool modify_(Modifier& mod,final_node_type* x)
  904. {
  905. BOOST_TRY{
  906. mod(const_cast<value_type&>(x->value()));
  907. }
  908. BOOST_CATCH(...){
  909. this->erase_(x);
  910. BOOST_RETHROW;
  911. }
  912. BOOST_CATCH_END
  913. BOOST_TRY{
  914. if(!super::modify_(x)){
  915. delete_node_(x);
  916. --node_count;
  917. return false;
  918. }
  919. else return true;
  920. }
  921. BOOST_CATCH(...){
  922. delete_node_(x);
  923. --node_count;
  924. BOOST_RETHROW;
  925. }
  926. BOOST_CATCH_END
  927. }
  928. template<typename Modifier,typename Rollback>
  929. bool modify_(Modifier& mod,Rollback& back_,final_node_type* x)
  930. {
  931. BOOST_TRY{
  932. mod(const_cast<value_type&>(x->value()));
  933. }
  934. BOOST_CATCH(...){
  935. this->erase_(x);
  936. BOOST_RETHROW;
  937. }
  938. BOOST_CATCH_END
  939. bool b;
  940. BOOST_TRY{
  941. b=super::modify_rollback_(x);
  942. }
  943. BOOST_CATCH(...){
  944. BOOST_TRY{
  945. back_(const_cast<value_type&>(x->value()));
  946. if(!super::check_rollback_(x))this->erase_(x);
  947. BOOST_RETHROW;
  948. }
  949. BOOST_CATCH(...){
  950. this->erase_(x);
  951. BOOST_RETHROW;
  952. }
  953. BOOST_CATCH_END
  954. }
  955. BOOST_CATCH_END
  956. BOOST_TRY{
  957. if(!b){
  958. back_(const_cast<value_type&>(x->value()));
  959. if(!super::check_rollback_(x))this->erase_(x);
  960. return false;
  961. }
  962. else return true;
  963. }
  964. BOOST_CATCH(...){
  965. this->erase_(x);
  966. BOOST_RETHROW;
  967. }
  968. BOOST_CATCH_END
  969. }
  970. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  971. /* serialization */
  972. friend class boost::serialization::access;
  973. template<class Archive>
  974. void serialize(Archive& ar,const unsigned int version)
  975. {
  976. core::split_member(ar,*this,version);
  977. }
  978. typedef typename super::index_saver_type index_saver_type;
  979. typedef typename super::index_loader_type index_loader_type;
  980. template<class Archive>
  981. void save(Archive& ar,const unsigned int version)const
  982. {
  983. const unsigned long s(size_());
  984. const detail::serialization_version<value_type> value_version;
  985. ar<<core::make_nvp("count",s);
  986. ar<<core::make_nvp("value_version",value_version);
  987. index_saver_type sm(bfm_allocator::member,s);
  988. for(iterator it=super::begin(),it_end=super::end();it!=it_end;++it){
  989. core::save_construct_data_adl(
  990. ar,boost::addressof(*it),value_version);
  991. ar<<serialization::make_nvp("item",*it);
  992. sm.add(it.get_node(),ar,version);
  993. }
  994. sm.add_track(header(),ar,version);
  995. super::save_(ar,version,sm);
  996. }
  997. template<class Archive>
  998. void load(Archive& ar,const unsigned int version)
  999. {
  1000. BOOST_MULTI_INDEX_CHECK_INVARIANT;
  1001. clear_();
  1002. unsigned long s;
  1003. detail::serialization_version<value_type> value_version;
  1004. if(version<1){
  1005. std::size_t sz;
  1006. ar>>core::make_nvp("count",sz);
  1007. s=static_cast<unsigned long>(sz);
  1008. }
  1009. else if(version<3){
  1010. #if defined(BOOST_MULTI_INDEX_ENABLE_SERIALIZATION_COMPATIBILITY_V2)
  1011. serialization::collection_size_type csz;
  1012. ar>>core::make_nvp("count",csz);
  1013. s=static_cast<unsigned long>(csz);
  1014. #else
  1015. ar>>core::make_nvp("count",s);
  1016. #endif
  1017. }
  1018. else{
  1019. ar>>core::make_nvp("count",s);
  1020. }
  1021. if(version<2){
  1022. value_version=0;
  1023. }
  1024. else{
  1025. ar>>core::make_nvp("value_version",value_version);
  1026. }
  1027. index_loader_type lm(bfm_allocator::member,s);
  1028. for(std::size_t n=0;n<s;++n){
  1029. detail::archive_constructed<Value> value("item",ar,value_version);
  1030. std::pair<final_node_type*,bool> p=insert_rv_(
  1031. value.get(),super::end().get_node());
  1032. if(!p.second)throw_exception(detail::bad_archive_exception());
  1033. ar.reset_object_address(
  1034. boost::addressof(p.first->value()),boost::addressof(value.get()));
  1035. lm.add(p.first,ar,version);
  1036. }
  1037. lm.add_track(header(),ar,version);
  1038. super::load_(ar,version,lm);
  1039. }
  1040. #endif
  1041. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  1042. /* invariant stuff */
  1043. bool invariant_()const
  1044. {
  1045. return super::invariant_();
  1046. }
  1047. void check_invariant_()const
  1048. {
  1049. BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
  1050. }
  1051. #endif
  1052. private:
  1053. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1054. void vartempl_construct_value_impl(
  1055. final_node_type* x,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1056. {
  1057. node_alloc_traits::construct(
  1058. bfm_allocator::member,boost::addressof(x->value()),
  1059. BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1060. }
  1061. size_type node_count;
  1062. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  1063. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  1064. #pragma parse_mfunc_templ reset
  1065. #endif
  1066. };
  1067. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  1068. #pragma warning(pop) /* C4522 */
  1069. #endif
  1070. /* retrieval of indices by number */
  1071. template<typename MultiIndexContainer,int N>
  1072. struct nth_index
  1073. {
  1074. BOOST_STATIC_CONSTANT(
  1075. int,
  1076. M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
  1077. BOOST_STATIC_ASSERT(N>=0&&N<M);
  1078. typedef typename mpl::at_c<
  1079. typename MultiIndexContainer::index_type_list,N>::type type;
  1080. };
  1081. template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
  1082. typename nth_index<
  1083. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
  1084. get(
  1085. multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
  1086. {
  1087. typedef multi_index_container<
  1088. Value,IndexSpecifierList,Allocator> multi_index_type;
  1089. typedef typename nth_index<
  1090. multi_index_container<
  1091. Value,IndexSpecifierList,Allocator>,
  1092. N
  1093. >::type index_type;
  1094. BOOST_STATIC_ASSERT(N>=0&&
  1095. N<
  1096. mpl::size<
  1097. BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
  1098. >::type::value);
  1099. return detail::converter<multi_index_type,index_type>::index(m);
  1100. }
  1101. template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
  1102. const typename nth_index<
  1103. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
  1104. get(
  1105. const multi_index_container<Value,IndexSpecifierList,Allocator>& m
  1106. )BOOST_NOEXCEPT
  1107. {
  1108. typedef multi_index_container<
  1109. Value,IndexSpecifierList,Allocator> multi_index_type;
  1110. typedef typename nth_index<
  1111. multi_index_container<
  1112. Value,IndexSpecifierList,Allocator>,
  1113. N
  1114. >::type index_type;
  1115. BOOST_STATIC_ASSERT(N>=0&&
  1116. N<
  1117. mpl::size<
  1118. BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
  1119. >::type::value);
  1120. return detail::converter<multi_index_type,index_type>::index(m);
  1121. }
  1122. /* retrieval of indices by tag */
  1123. template<typename MultiIndexContainer,typename Tag>
  1124. struct index
  1125. {
  1126. typedef typename MultiIndexContainer::index_type_list index_type_list;
  1127. typedef typename mpl::find_if<
  1128. index_type_list,
  1129. detail::has_tag<Tag>
  1130. >::type iter;
  1131. BOOST_STATIC_CONSTANT(
  1132. bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
  1133. BOOST_STATIC_ASSERT(index_found);
  1134. typedef typename mpl::deref<iter>::type type;
  1135. };
  1136. template<
  1137. typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
  1138. >
  1139. typename ::boost::multi_index::index<
  1140. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
  1141. get(
  1142. multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
  1143. {
  1144. typedef multi_index_container<
  1145. Value,IndexSpecifierList,Allocator> multi_index_type;
  1146. typedef typename ::boost::multi_index::index<
  1147. multi_index_container<
  1148. Value,IndexSpecifierList,Allocator>,
  1149. Tag
  1150. >::type index_type;
  1151. return detail::converter<multi_index_type,index_type>::index(m);
  1152. }
  1153. template<
  1154. typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
  1155. >
  1156. const typename ::boost::multi_index::index<
  1157. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
  1158. get(
  1159. const multi_index_container<Value,IndexSpecifierList,Allocator>& m
  1160. )BOOST_NOEXCEPT
  1161. {
  1162. typedef multi_index_container<
  1163. Value,IndexSpecifierList,Allocator> multi_index_type;
  1164. typedef typename ::boost::multi_index::index<
  1165. multi_index_container<
  1166. Value,IndexSpecifierList,Allocator>,
  1167. Tag
  1168. >::type index_type;
  1169. return detail::converter<multi_index_type,index_type>::index(m);
  1170. }
  1171. /* projection of iterators by number */
  1172. template<typename MultiIndexContainer,int N>
  1173. struct nth_index_iterator
  1174. {
  1175. typedef typename nth_index<MultiIndexContainer,N>::type::iterator type;
  1176. };
  1177. template<typename MultiIndexContainer,int N>
  1178. struct nth_index_const_iterator
  1179. {
  1180. typedef typename nth_index<MultiIndexContainer,N>::type::const_iterator type;
  1181. };
  1182. template<
  1183. int N,typename IteratorType,
  1184. typename Value,typename IndexSpecifierList,typename Allocator>
  1185. typename nth_index_iterator<
  1186. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
  1187. project(
  1188. multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1189. IteratorType it)
  1190. {
  1191. typedef multi_index_container<
  1192. Value,IndexSpecifierList,Allocator> multi_index_type;
  1193. typedef typename nth_index<multi_index_type,N>::type index_type;
  1194. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1195. BOOST_STATIC_ASSERT((
  1196. mpl::contains<
  1197. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1198. IteratorType>::value));
  1199. #endif
  1200. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1201. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1202. return detail::converter<multi_index_type,index_type>::iterator(
  1203. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1204. }
  1205. template<
  1206. int N,typename IteratorType,
  1207. typename Value,typename IndexSpecifierList,typename Allocator>
  1208. typename nth_index_const_iterator<
  1209. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
  1210. project(
  1211. const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1212. IteratorType it)
  1213. {
  1214. typedef multi_index_container<
  1215. Value,IndexSpecifierList,Allocator> multi_index_type;
  1216. typedef typename nth_index<multi_index_type,N>::type index_type;
  1217. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1218. BOOST_STATIC_ASSERT((
  1219. mpl::contains<
  1220. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1221. IteratorType>::value||
  1222. mpl::contains<
  1223. BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
  1224. IteratorType>::value));
  1225. #endif
  1226. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1227. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1228. return detail::converter<multi_index_type,index_type>::const_iterator(
  1229. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1230. }
  1231. /* projection of iterators by tag */
  1232. template<typename MultiIndexContainer,typename Tag>
  1233. struct index_iterator
  1234. {
  1235. typedef typename ::boost::multi_index::index<
  1236. MultiIndexContainer,Tag>::type::iterator type;
  1237. };
  1238. template<typename MultiIndexContainer,typename Tag>
  1239. struct index_const_iterator
  1240. {
  1241. typedef typename ::boost::multi_index::index<
  1242. MultiIndexContainer,Tag>::type::const_iterator type;
  1243. };
  1244. template<
  1245. typename Tag,typename IteratorType,
  1246. typename Value,typename IndexSpecifierList,typename Allocator>
  1247. typename index_iterator<
  1248. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
  1249. project(
  1250. multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1251. IteratorType it)
  1252. {
  1253. typedef multi_index_container<
  1254. Value,IndexSpecifierList,Allocator> multi_index_type;
  1255. typedef typename ::boost::multi_index::index<
  1256. multi_index_type,Tag>::type index_type;
  1257. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1258. BOOST_STATIC_ASSERT((
  1259. mpl::contains<
  1260. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1261. IteratorType>::value));
  1262. #endif
  1263. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1264. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1265. return detail::converter<multi_index_type,index_type>::iterator(
  1266. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1267. }
  1268. template<
  1269. typename Tag,typename IteratorType,
  1270. typename Value,typename IndexSpecifierList,typename Allocator>
  1271. typename index_const_iterator<
  1272. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
  1273. project(
  1274. const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1275. IteratorType it)
  1276. {
  1277. typedef multi_index_container<
  1278. Value,IndexSpecifierList,Allocator> multi_index_type;
  1279. typedef typename ::boost::multi_index::index<
  1280. multi_index_type,Tag>::type index_type;
  1281. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1282. BOOST_STATIC_ASSERT((
  1283. mpl::contains<
  1284. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1285. IteratorType>::value||
  1286. mpl::contains<
  1287. BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
  1288. IteratorType>::value));
  1289. #endif
  1290. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1291. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1292. return detail::converter<multi_index_type,index_type>::const_iterator(
  1293. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1294. }
  1295. /* Comparison. Simple forward to first index. */
  1296. template<
  1297. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1298. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1299. >
  1300. bool operator==(
  1301. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1302. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1303. {
  1304. return get<0>(x)==get<0>(y);
  1305. }
  1306. template<
  1307. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1308. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1309. >
  1310. bool operator<(
  1311. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1312. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1313. {
  1314. return get<0>(x)<get<0>(y);
  1315. }
  1316. template<
  1317. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1318. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1319. >
  1320. bool operator!=(
  1321. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1322. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1323. {
  1324. return get<0>(x)!=get<0>(y);
  1325. }
  1326. template<
  1327. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1328. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1329. >
  1330. bool operator>(
  1331. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1332. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1333. {
  1334. return get<0>(x)>get<0>(y);
  1335. }
  1336. template<
  1337. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1338. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1339. >
  1340. bool operator>=(
  1341. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1342. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1343. {
  1344. return get<0>(x)>=get<0>(y);
  1345. }
  1346. template<
  1347. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1348. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1349. >
  1350. bool operator<=(
  1351. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1352. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1353. {
  1354. return get<0>(x)<=get<0>(y);
  1355. }
  1356. /* specialized algorithms */
  1357. template<typename Value,typename IndexSpecifierList,typename Allocator>
  1358. void swap(
  1359. multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  1360. multi_index_container<Value,IndexSpecifierList,Allocator>& y)
  1361. {
  1362. x.swap(y);
  1363. }
  1364. } /* namespace multi_index */
  1365. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  1366. /* class version = 1 : we now serialize the size through
  1367. * boost::serialization::collection_size_type.
  1368. * class version = 2 : proper use of {save|load}_construct_data.
  1369. * class version = 3 : dropped boost::serialization::collection_size_type
  1370. * in favor of unsigned long --this allows us to provide serialization
  1371. * support without including any header from Boost.Serialization.
  1372. */
  1373. namespace serialization {
  1374. template<typename Value,typename IndexSpecifierList,typename Allocator>
  1375. struct version<
  1376. boost::multi_index_container<Value,IndexSpecifierList,Allocator>
  1377. >
  1378. {
  1379. BOOST_STATIC_CONSTANT(int,value=3);
  1380. };
  1381. } /* namespace serialization */
  1382. #endif
  1383. /* Associated global functions are promoted to namespace boost, except
  1384. * comparison operators and swap, which are meant to be Koenig looked-up.
  1385. */
  1386. using multi_index::get;
  1387. using multi_index::project;
  1388. } /* namespace boost */
  1389. #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
  1390. #undef BOOST_MULTI_INDEX_CHECK_INVARIANT_OF
  1391. #endif