multi_index_container.hpp 39 KB

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