multi_index_container.hpp 44 KB

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