multi_index_container.hpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  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 std::size_t 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. std::size_t 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<std::size_t>(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<std::size_t>(csz);
  1014. #else
  1015. ar>>core::make_nvp("count",s);
  1016. #endif
  1017. }
  1018. else if(version<4){
  1019. unsigned long ul;
  1020. ar>>core::make_nvp("count",ul);
  1021. s=static_cast<std::size_t>(ul);
  1022. }
  1023. else{
  1024. ar>>core::make_nvp("count",s);
  1025. }
  1026. if(version<2){
  1027. value_version=0;
  1028. }
  1029. else{
  1030. ar>>core::make_nvp("value_version",value_version);
  1031. }
  1032. index_loader_type lm(bfm_allocator::member,s);
  1033. for(std::size_t n=0;n<s;++n){
  1034. detail::archive_constructed<Value> value("item",ar,value_version);
  1035. std::pair<final_node_type*,bool> p=insert_rv_(
  1036. value.get(),super::end().get_node());
  1037. if(!p.second)throw_exception(detail::bad_archive_exception());
  1038. ar.reset_object_address(
  1039. boost::addressof(p.first->value()),boost::addressof(value.get()));
  1040. lm.add(p.first,ar,version);
  1041. }
  1042. lm.add_track(header(),ar,version);
  1043. super::load_(ar,version,lm);
  1044. }
  1045. #endif
  1046. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  1047. /* invariant stuff */
  1048. bool invariant_()const
  1049. {
  1050. return super::invariant_();
  1051. }
  1052. void check_invariant_()const
  1053. {
  1054. BOOST_MULTI_INDEX_INVARIANT_ASSERT(invariant_());
  1055. }
  1056. #endif
  1057. private:
  1058. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1059. void vartempl_construct_value_impl(
  1060. final_node_type* x,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1061. {
  1062. node_alloc_traits::construct(
  1063. bfm_allocator::member,boost::addressof(x->value()),
  1064. BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1065. }
  1066. size_type node_count;
  1067. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  1068. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  1069. #pragma parse_mfunc_templ reset
  1070. #endif
  1071. };
  1072. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  1073. #pragma warning(pop) /* C4522 */
  1074. #endif
  1075. /* retrieval of indices by number */
  1076. template<typename MultiIndexContainer,int N>
  1077. struct nth_index
  1078. {
  1079. BOOST_STATIC_CONSTANT(
  1080. int,
  1081. M=mpl::size<typename MultiIndexContainer::index_type_list>::type::value);
  1082. BOOST_STATIC_ASSERT(N>=0&&N<M);
  1083. typedef typename mpl::at_c<
  1084. typename MultiIndexContainer::index_type_list,N>::type type;
  1085. };
  1086. template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
  1087. typename nth_index<
  1088. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
  1089. get(
  1090. multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
  1091. {
  1092. typedef multi_index_container<
  1093. Value,IndexSpecifierList,Allocator> multi_index_type;
  1094. typedef typename nth_index<
  1095. multi_index_container<
  1096. Value,IndexSpecifierList,Allocator>,
  1097. N
  1098. >::type index_type;
  1099. BOOST_STATIC_ASSERT(N>=0&&
  1100. N<
  1101. mpl::size<
  1102. BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
  1103. >::type::value);
  1104. return detail::converter<multi_index_type,index_type>::index(m);
  1105. }
  1106. template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
  1107. const typename nth_index<
  1108. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type&
  1109. get(
  1110. const multi_index_container<Value,IndexSpecifierList,Allocator>& m
  1111. )BOOST_NOEXCEPT
  1112. {
  1113. typedef multi_index_container<
  1114. Value,IndexSpecifierList,Allocator> multi_index_type;
  1115. typedef typename nth_index<
  1116. multi_index_container<
  1117. Value,IndexSpecifierList,Allocator>,
  1118. N
  1119. >::type index_type;
  1120. BOOST_STATIC_ASSERT(N>=0&&
  1121. N<
  1122. mpl::size<
  1123. BOOST_DEDUCED_TYPENAME multi_index_type::index_type_list
  1124. >::type::value);
  1125. return detail::converter<multi_index_type,index_type>::index(m);
  1126. }
  1127. /* retrieval of indices by tag */
  1128. template<typename MultiIndexContainer,typename Tag>
  1129. struct index
  1130. {
  1131. typedef typename MultiIndexContainer::index_type_list index_type_list;
  1132. typedef typename mpl::find_if<
  1133. index_type_list,
  1134. detail::has_tag<Tag>
  1135. >::type iter;
  1136. BOOST_STATIC_CONSTANT(
  1137. bool,index_found=!(is_same<iter,typename mpl::end<index_type_list>::type >::value));
  1138. BOOST_STATIC_ASSERT(index_found);
  1139. typedef typename mpl::deref<iter>::type type;
  1140. };
  1141. template<
  1142. typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
  1143. >
  1144. typename ::boost::multi_index::index<
  1145. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
  1146. get(
  1147. multi_index_container<Value,IndexSpecifierList,Allocator>& m)BOOST_NOEXCEPT
  1148. {
  1149. typedef multi_index_container<
  1150. Value,IndexSpecifierList,Allocator> multi_index_type;
  1151. typedef typename ::boost::multi_index::index<
  1152. multi_index_container<
  1153. Value,IndexSpecifierList,Allocator>,
  1154. Tag
  1155. >::type index_type;
  1156. return detail::converter<multi_index_type,index_type>::index(m);
  1157. }
  1158. template<
  1159. typename Tag,typename Value,typename IndexSpecifierList,typename Allocator
  1160. >
  1161. const typename ::boost::multi_index::index<
  1162. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type&
  1163. get(
  1164. const multi_index_container<Value,IndexSpecifierList,Allocator>& m
  1165. )BOOST_NOEXCEPT
  1166. {
  1167. typedef multi_index_container<
  1168. Value,IndexSpecifierList,Allocator> multi_index_type;
  1169. typedef typename ::boost::multi_index::index<
  1170. multi_index_container<
  1171. Value,IndexSpecifierList,Allocator>,
  1172. Tag
  1173. >::type index_type;
  1174. return detail::converter<multi_index_type,index_type>::index(m);
  1175. }
  1176. /* projection of iterators by number */
  1177. template<typename MultiIndexContainer,int N>
  1178. struct nth_index_iterator
  1179. {
  1180. typedef typename nth_index<MultiIndexContainer,N>::type::iterator type;
  1181. };
  1182. template<typename MultiIndexContainer,int N>
  1183. struct nth_index_const_iterator
  1184. {
  1185. typedef typename nth_index<MultiIndexContainer,N>::type::const_iterator type;
  1186. };
  1187. template<
  1188. int N,typename IteratorType,
  1189. typename Value,typename IndexSpecifierList,typename Allocator>
  1190. typename nth_index_iterator<
  1191. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
  1192. project(
  1193. multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1194. IteratorType it)
  1195. {
  1196. typedef multi_index_container<
  1197. Value,IndexSpecifierList,Allocator> multi_index_type;
  1198. typedef typename nth_index<multi_index_type,N>::type index_type;
  1199. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1200. BOOST_STATIC_ASSERT((
  1201. mpl::contains<
  1202. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1203. IteratorType>::value));
  1204. #endif
  1205. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1206. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1207. return detail::converter<multi_index_type,index_type>::iterator(
  1208. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1209. }
  1210. template<
  1211. int N,typename IteratorType,
  1212. typename Value,typename IndexSpecifierList,typename Allocator>
  1213. typename nth_index_const_iterator<
  1214. multi_index_container<Value,IndexSpecifierList,Allocator>,N>::type
  1215. project(
  1216. const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1217. IteratorType it)
  1218. {
  1219. typedef multi_index_container<
  1220. Value,IndexSpecifierList,Allocator> multi_index_type;
  1221. typedef typename nth_index<multi_index_type,N>::type index_type;
  1222. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1223. BOOST_STATIC_ASSERT((
  1224. mpl::contains<
  1225. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1226. IteratorType>::value||
  1227. mpl::contains<
  1228. BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
  1229. IteratorType>::value));
  1230. #endif
  1231. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1232. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1233. return detail::converter<multi_index_type,index_type>::const_iterator(
  1234. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1235. }
  1236. /* projection of iterators by tag */
  1237. template<typename MultiIndexContainer,typename Tag>
  1238. struct index_iterator
  1239. {
  1240. typedef typename ::boost::multi_index::index<
  1241. MultiIndexContainer,Tag>::type::iterator type;
  1242. };
  1243. template<typename MultiIndexContainer,typename Tag>
  1244. struct index_const_iterator
  1245. {
  1246. typedef typename ::boost::multi_index::index<
  1247. MultiIndexContainer,Tag>::type::const_iterator type;
  1248. };
  1249. template<
  1250. typename Tag,typename IteratorType,
  1251. typename Value,typename IndexSpecifierList,typename Allocator>
  1252. typename index_iterator<
  1253. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
  1254. project(
  1255. multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1256. IteratorType it)
  1257. {
  1258. typedef multi_index_container<
  1259. Value,IndexSpecifierList,Allocator> multi_index_type;
  1260. typedef typename ::boost::multi_index::index<
  1261. multi_index_type,Tag>::type index_type;
  1262. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1263. BOOST_STATIC_ASSERT((
  1264. mpl::contains<
  1265. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1266. IteratorType>::value));
  1267. #endif
  1268. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1269. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1270. return detail::converter<multi_index_type,index_type>::iterator(
  1271. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1272. }
  1273. template<
  1274. typename Tag,typename IteratorType,
  1275. typename Value,typename IndexSpecifierList,typename Allocator>
  1276. typename index_const_iterator<
  1277. multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type
  1278. project(
  1279. const multi_index_container<Value,IndexSpecifierList,Allocator>& m,
  1280. IteratorType it)
  1281. {
  1282. typedef multi_index_container<
  1283. Value,IndexSpecifierList,Allocator> multi_index_type;
  1284. typedef typename ::boost::multi_index::index<
  1285. multi_index_type,Tag>::type index_type;
  1286. #if !defined(__SUNPRO_CC)||!(__SUNPRO_CC<0x580) /* Sun C++ 5.7 fails */
  1287. BOOST_STATIC_ASSERT((
  1288. mpl::contains<
  1289. BOOST_DEDUCED_TYPENAME multi_index_type::iterator_type_list,
  1290. IteratorType>::value||
  1291. mpl::contains<
  1292. BOOST_DEDUCED_TYPENAME multi_index_type::const_iterator_type_list,
  1293. IteratorType>::value));
  1294. #endif
  1295. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it);
  1296. BOOST_MULTI_INDEX_CHECK_BELONGS_IN_SOME_INDEX(it,m);
  1297. return detail::converter<multi_index_type,index_type>::const_iterator(
  1298. m,static_cast<typename multi_index_type::final_node_type*>(it.get_node()));
  1299. }
  1300. /* Comparison. Simple forward to first index. */
  1301. template<
  1302. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1303. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1304. >
  1305. bool operator==(
  1306. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1307. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1308. {
  1309. return get<0>(x)==get<0>(y);
  1310. }
  1311. template<
  1312. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1313. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1314. >
  1315. bool operator<(
  1316. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1317. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1318. {
  1319. return get<0>(x)<get<0>(y);
  1320. }
  1321. template<
  1322. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1323. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1324. >
  1325. bool operator!=(
  1326. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1327. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1328. {
  1329. return get<0>(x)!=get<0>(y);
  1330. }
  1331. template<
  1332. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1333. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1334. >
  1335. bool operator>(
  1336. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1337. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1338. {
  1339. return get<0>(x)>get<0>(y);
  1340. }
  1341. template<
  1342. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1343. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1344. >
  1345. bool operator>=(
  1346. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1347. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1348. {
  1349. return get<0>(x)>=get<0>(y);
  1350. }
  1351. template<
  1352. typename Value1,typename IndexSpecifierList1,typename Allocator1,
  1353. typename Value2,typename IndexSpecifierList2,typename Allocator2
  1354. >
  1355. bool operator<=(
  1356. const multi_index_container<Value1,IndexSpecifierList1,Allocator1>& x,
  1357. const multi_index_container<Value2,IndexSpecifierList2,Allocator2>& y)
  1358. {
  1359. return get<0>(x)<=get<0>(y);
  1360. }
  1361. /* specialized algorithms */
  1362. template<typename Value,typename IndexSpecifierList,typename Allocator>
  1363. void swap(
  1364. multi_index_container<Value,IndexSpecifierList,Allocator>& x,
  1365. multi_index_container<Value,IndexSpecifierList,Allocator>& y)
  1366. {
  1367. x.swap(y);
  1368. }
  1369. } /* namespace multi_index */
  1370. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  1371. /* class version = 1 : we now serialize the size through
  1372. * boost::serialization::collection_size_type.
  1373. * class version = 2 : proper use of {save|load}_construct_data.
  1374. * class version = 3 : dropped boost::serialization::collection_size_type
  1375. * in favor of unsigned long --this allows us to provide serialization
  1376. * support without including any header from Boost.Serialization.
  1377. * class version = 4 : uses std::size_t rather than unsigned long (which
  1378. * is smaller in LLP64 data models).
  1379. */
  1380. namespace serialization {
  1381. template<typename Value,typename IndexSpecifierList,typename Allocator>
  1382. struct version<
  1383. boost::multi_index_container<Value,IndexSpecifierList,Allocator>
  1384. >
  1385. {
  1386. BOOST_STATIC_CONSTANT(int,value=4);
  1387. };
  1388. } /* namespace serialization */
  1389. #endif
  1390. /* Associated global functions are promoted to namespace boost, except
  1391. * comparison operators and swap, which are meant to be Koenig looked-up.
  1392. */
  1393. using multi_index::get;
  1394. using multi_index::project;
  1395. } /* namespace boost */
  1396. #undef BOOST_MULTI_INDEX_CHECK_INVARIANT
  1397. #undef BOOST_MULTI_INDEX_CHECK_INVARIANT_OF
  1398. #endif