multi_index_container.hpp 39 KB

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