/Src/Dependencies/Boost/boost/multi_index/ordered_index.hpp

http://hadesmem.googlecode.com/ · C++ Header · 1390 lines · 1121 code · 187 blank · 82 comment · 83 complexity · d55baa0bae95d20868bc176ff65987ee MD5 · raw file

  1. /* Copyright 2003-2010 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. *
  8. * The internal implementation of red-black trees is based on that of SGI STL
  9. * stl_tree.h file:
  10. *
  11. * Copyright (c) 1996,1997
  12. * Silicon Graphics Computer Systems, Inc.
  13. *
  14. * Permission to use, copy, modify, distribute and sell this software
  15. * and its documentation for any purpose is hereby granted without fee,
  16. * provided that the above copyright notice appear in all copies and
  17. * that both that copyright notice and this permission notice appear
  18. * in supporting documentation. Silicon Graphics makes no
  19. * representations about the suitability of this software for any
  20. * purpose. It is provided "as is" without express or implied warranty.
  21. *
  22. *
  23. * Copyright (c) 1994
  24. * Hewlett-Packard Company
  25. *
  26. * Permission to use, copy, modify, distribute and sell this software
  27. * and its documentation for any purpose is hereby granted without fee,
  28. * provided that the above copyright notice appear in all copies and
  29. * that both that copyright notice and this permission notice appear
  30. * in supporting documentation. Hewlett-Packard Company makes no
  31. * representations about the suitability of this software for any
  32. * purpose. It is provided "as is" without express or implied warranty.
  33. *
  34. */
  35. #ifndef BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
  36. #define BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
  37. #if defined(_MSC_VER)&&(_MSC_VER>=1200)
  38. #pragma once
  39. #endif
  40. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  41. #include <algorithm>
  42. #include <boost/call_traits.hpp>
  43. #include <boost/detail/no_exceptions_support.hpp>
  44. #include <boost/detail/workaround.hpp>
  45. #include <boost/iterator/reverse_iterator.hpp>
  46. #include <boost/mpl/if.hpp>
  47. #include <boost/mpl/push_front.hpp>
  48. #include <boost/multi_index/detail/access_specifier.hpp>
  49. #include <boost/multi_index/detail/bidir_node_iterator.hpp>
  50. #include <boost/multi_index/detail/index_node_base.hpp>
  51. #include <boost/multi_index/detail/modify_key_adaptor.hpp>
  52. #include <boost/multi_index/detail/ord_index_node.hpp>
  53. #include <boost/multi_index/detail/ord_index_ops.hpp>
  54. #include <boost/multi_index/detail/safe_ctr_proxy.hpp>
  55. #include <boost/multi_index/detail/safe_mode.hpp>
  56. #include <boost/multi_index/detail/scope_guard.hpp>
  57. #include <boost/multi_index/detail/unbounded.hpp>
  58. #include <boost/multi_index/detail/value_compare.hpp>
  59. #include <boost/multi_index/ordered_index_fwd.hpp>
  60. #include <boost/ref.hpp>
  61. #include <boost/tuple/tuple.hpp>
  62. #include <boost/type_traits/is_same.hpp>
  63. #include <utility>
  64. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  65. #include <boost/archive/archive_exception.hpp>
  66. #include <boost/bind.hpp>
  67. #include <boost/multi_index/detail/duplicates_iterator.hpp>
  68. #include <boost/throw_exception.hpp>
  69. #endif
  70. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  71. #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT \
  72. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  73. detail::make_obj_guard(*this,&ordered_index::check_invariant_); \
  74. BOOST_JOIN(check_invariant_,__LINE__).touch();
  75. #else
  76. #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
  77. #endif
  78. namespace boost{
  79. namespace multi_index{
  80. namespace detail{
  81. /* ordered_index adds a layer of ordered indexing to a given Super */
  82. /* Most of the implementation of unique and non-unique indices is
  83. * shared. We tell from one another on instantiation time by using
  84. * these tags.
  85. */
  86. struct ordered_unique_tag{};
  87. struct ordered_non_unique_tag{};
  88. template<
  89. typename KeyFromValue,typename Compare,
  90. typename SuperMeta,typename TagList,typename Category
  91. >
  92. class ordered_index:
  93. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
  94. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  95. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  96. ,public safe_ctr_proxy_impl<
  97. bidir_node_iterator<
  98. ordered_index_node<typename SuperMeta::type::node_type> >,
  99. ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
  100. #else
  101. ,public safe_mode::safe_container<
  102. ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
  103. #endif
  104. #endif
  105. {
  106. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  107. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  108. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  109. * lifetime of const references bound to temporaries --precisely what
  110. * scopeguards are.
  111. */
  112. #pragma parse_mfunc_templ off
  113. #endif
  114. typedef typename SuperMeta::type super;
  115. protected:
  116. typedef ordered_index_node<
  117. typename super::node_type> node_type;
  118. private:
  119. typedef typename node_type::impl_type node_impl_type;
  120. typedef typename node_impl_type::pointer node_impl_pointer;
  121. public:
  122. /* types */
  123. typedef typename KeyFromValue::result_type key_type;
  124. typedef typename node_type::value_type value_type;
  125. typedef KeyFromValue key_from_value;
  126. typedef Compare key_compare;
  127. typedef value_comparison<
  128. value_type,KeyFromValue,Compare> value_compare;
  129. typedef tuple<key_from_value,key_compare> ctor_args;
  130. typedef typename super::final_allocator_type allocator_type;
  131. typedef typename allocator_type::reference reference;
  132. typedef typename allocator_type::const_reference const_reference;
  133. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  134. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  135. typedef safe_mode::safe_iterator<
  136. bidir_node_iterator<node_type>,
  137. safe_ctr_proxy<
  138. bidir_node_iterator<node_type> > > iterator;
  139. #else
  140. typedef safe_mode::safe_iterator<
  141. bidir_node_iterator<node_type>,
  142. ordered_index> iterator;
  143. #endif
  144. #else
  145. typedef bidir_node_iterator<node_type> iterator;
  146. #endif
  147. typedef iterator const_iterator;
  148. typedef std::size_t size_type;
  149. typedef std::ptrdiff_t difference_type;
  150. typedef typename allocator_type::pointer pointer;
  151. typedef typename allocator_type::const_pointer const_pointer;
  152. typedef typename
  153. boost::reverse_iterator<iterator> reverse_iterator;
  154. typedef typename
  155. boost::reverse_iterator<const_iterator> const_reverse_iterator;
  156. typedef TagList tag_list;
  157. protected:
  158. typedef typename super::final_node_type final_node_type;
  159. typedef tuples::cons<
  160. ctor_args,
  161. typename super::ctor_args_list> ctor_args_list;
  162. typedef typename mpl::push_front<
  163. typename super::index_type_list,
  164. ordered_index>::type index_type_list;
  165. typedef typename mpl::push_front<
  166. typename super::iterator_type_list,
  167. iterator>::type iterator_type_list;
  168. typedef typename mpl::push_front<
  169. typename super::const_iterator_type_list,
  170. const_iterator>::type const_iterator_type_list;
  171. typedef typename super::copy_map_type copy_map_type;
  172. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  173. typedef typename super::index_saver_type index_saver_type;
  174. typedef typename super::index_loader_type index_loader_type;
  175. #endif
  176. private:
  177. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  178. #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
  179. typedef safe_ctr_proxy_impl<
  180. bidir_node_iterator<node_type>,
  181. ordered_index> safe_super;
  182. #else
  183. typedef safe_mode::safe_container<ordered_index> safe_super;
  184. #endif
  185. #endif
  186. typedef typename call_traits<
  187. value_type>::param_type value_param_type;
  188. typedef typename call_traits<
  189. key_type>::param_type key_param_type;
  190. public:
  191. /* construct/copy/destroy
  192. * Default and copy ctors are in the protected section as indices are
  193. * not supposed to be created on their own. No range ctor either.
  194. */
  195. ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& operator=(
  196. const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
  197. {
  198. this->final()=x.final();
  199. return *this;
  200. }
  201. allocator_type get_allocator()const
  202. {
  203. return this->final().get_allocator();
  204. }
  205. /* iterators */
  206. iterator begin(){return make_iterator(leftmost());}
  207. const_iterator begin()const{return make_iterator(leftmost());}
  208. iterator end(){return make_iterator(header());}
  209. const_iterator end()const{return make_iterator(header());}
  210. reverse_iterator rbegin(){return make_reverse_iterator(end());}
  211. const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
  212. reverse_iterator rend(){return make_reverse_iterator(begin());}
  213. const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
  214. const_iterator cbegin()const{return begin();}
  215. const_iterator cend()const{return end();}
  216. const_reverse_iterator crbegin()const{return rbegin();}
  217. const_reverse_iterator crend()const{return rend();}
  218. iterator iterator_to(const value_type& x)
  219. {
  220. return make_iterator(node_from_value<node_type>(&x));
  221. }
  222. const_iterator iterator_to(const value_type& x)const
  223. {
  224. return make_iterator(node_from_value<node_type>(&x));
  225. }
  226. /* capacity */
  227. bool empty()const{return this->final_empty_();}
  228. size_type size()const{return this->final_size_();}
  229. size_type max_size()const{return this->final_max_size_();}
  230. /* modifiers */
  231. std::pair<iterator,bool> insert(value_param_type x)
  232. {
  233. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  234. std::pair<final_node_type*,bool> p=this->final_insert_(x);
  235. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  236. }
  237. iterator insert(iterator position,value_param_type x)
  238. {
  239. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  240. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  241. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  242. std::pair<final_node_type*,bool> p=this->final_insert_(
  243. x,static_cast<final_node_type*>(position.get_node()));
  244. return make_iterator(p.first);
  245. }
  246. template<typename InputIterator>
  247. void insert(InputIterator first,InputIterator last)
  248. {
  249. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  250. iterator hint=end();
  251. for(;first!=last;++first)hint=insert(hint,*first);
  252. }
  253. iterator erase(iterator position)
  254. {
  255. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  256. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  257. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  258. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  259. this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
  260. return position;
  261. }
  262. size_type erase(key_param_type x)
  263. {
  264. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  265. std::pair<iterator,iterator> p=equal_range(x);
  266. size_type s=0;
  267. while(p.first!=p.second){
  268. p.first=erase(p.first);
  269. ++s;
  270. }
  271. return s;
  272. }
  273. iterator erase(iterator first,iterator last)
  274. {
  275. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  276. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  277. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  278. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  279. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  280. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  281. while(first!=last){
  282. first=erase(first);
  283. }
  284. return first;
  285. }
  286. bool replace(iterator position,value_param_type x)
  287. {
  288. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  289. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  290. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  291. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  292. return this->final_replace_(
  293. x,static_cast<final_node_type*>(position.get_node()));
  294. }
  295. template<typename Modifier>
  296. bool modify(iterator position,Modifier mod)
  297. {
  298. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  299. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  300. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  301. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  302. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  303. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  304. * this is not added. Left it for all compilers as it does no
  305. * harm.
  306. */
  307. position.detach();
  308. #endif
  309. return this->final_modify_(
  310. mod,static_cast<final_node_type*>(position.get_node()));
  311. }
  312. template<typename Modifier,typename Rollback>
  313. bool modify(iterator position,Modifier mod,Rollback back)
  314. {
  315. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  316. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  317. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  318. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  319. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  320. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  321. * this is not added. Left it for all compilers as it does no
  322. * harm.
  323. */
  324. position.detach();
  325. #endif
  326. return this->final_modify_(
  327. mod,back,static_cast<final_node_type*>(position.get_node()));
  328. }
  329. template<typename Modifier>
  330. bool modify_key(iterator position,Modifier mod)
  331. {
  332. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  333. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  334. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  335. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  336. return modify(
  337. position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
  338. }
  339. template<typename Modifier,typename Rollback>
  340. bool modify_key(iterator position,Modifier mod,Rollback back)
  341. {
  342. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  343. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  344. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  345. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  346. return modify(
  347. position,
  348. modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
  349. modify_key_adaptor<Rollback,value_type,KeyFromValue>(back,key));
  350. }
  351. void swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
  352. {
  353. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  354. this->final_swap_(x.final());
  355. }
  356. void clear()
  357. {
  358. BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
  359. this->final_clear_();
  360. }
  361. /* observers */
  362. key_from_value key_extractor()const{return key;}
  363. key_compare key_comp()const{return comp;}
  364. value_compare value_comp()const{return value_compare(key,comp);}
  365. /* set operations */
  366. /* Internally, these ops rely on const_iterator being the same
  367. * type as iterator.
  368. */
  369. template<typename CompatibleKey>
  370. iterator find(const CompatibleKey& x)const
  371. {
  372. return make_iterator(ordered_index_find(root(),header(),key,x,comp));
  373. }
  374. template<typename CompatibleKey,typename CompatibleCompare>
  375. iterator find(
  376. const CompatibleKey& x,const CompatibleCompare& comp)const
  377. {
  378. return make_iterator(ordered_index_find(root(),header(),key,x,comp));
  379. }
  380. template<typename CompatibleKey>
  381. size_type count(const CompatibleKey& x)const
  382. {
  383. return count(x,comp);
  384. }
  385. template<typename CompatibleKey,typename CompatibleCompare>
  386. size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
  387. {
  388. std::pair<iterator,iterator> p=equal_range(x,comp);
  389. size_type n=std::distance(p.first,p.second);
  390. return n;
  391. }
  392. template<typename CompatibleKey>
  393. iterator lower_bound(const CompatibleKey& x)const
  394. {
  395. return make_iterator(
  396. ordered_index_lower_bound(root(),header(),key,x,comp));
  397. }
  398. template<typename CompatibleKey,typename CompatibleCompare>
  399. iterator lower_bound(
  400. const CompatibleKey& x,const CompatibleCompare& comp)const
  401. {
  402. return make_iterator(
  403. ordered_index_lower_bound(root(),header(),key,x,comp));
  404. }
  405. template<typename CompatibleKey>
  406. iterator upper_bound(const CompatibleKey& x)const
  407. {
  408. return make_iterator(
  409. ordered_index_upper_bound(root(),header(),key,x,comp));
  410. }
  411. template<typename CompatibleKey,typename CompatibleCompare>
  412. iterator upper_bound(
  413. const CompatibleKey& x,const CompatibleCompare& comp)const
  414. {
  415. return make_iterator(
  416. ordered_index_upper_bound(root(),header(),key,x,comp));
  417. }
  418. template<typename CompatibleKey>
  419. std::pair<iterator,iterator> equal_range(
  420. const CompatibleKey& x)const
  421. {
  422. std::pair<node_type*,node_type*> p=
  423. ordered_index_equal_range(root(),header(),key,x,comp);
  424. return std::pair<iterator,iterator>(
  425. make_iterator(p.first),make_iterator(p.second));
  426. }
  427. template<typename CompatibleKey,typename CompatibleCompare>
  428. std::pair<iterator,iterator> equal_range(
  429. const CompatibleKey& x,const CompatibleCompare& comp)const
  430. {
  431. std::pair<node_type*,node_type*> p=
  432. ordered_index_equal_range(root(),header(),key,x,comp);
  433. return std::pair<iterator,iterator>(
  434. make_iterator(p.first),make_iterator(p.second));
  435. }
  436. /* range */
  437. template<typename LowerBounder,typename UpperBounder>
  438. std::pair<iterator,iterator>
  439. range(LowerBounder lower,UpperBounder upper)const
  440. {
  441. typedef typename mpl::if_<
  442. is_same<LowerBounder,unbounded_type>,
  443. BOOST_DEDUCED_TYPENAME mpl::if_<
  444. is_same<UpperBounder,unbounded_type>,
  445. both_unbounded_tag,
  446. lower_unbounded_tag
  447. >::type,
  448. BOOST_DEDUCED_TYPENAME mpl::if_<
  449. is_same<UpperBounder,unbounded_type>,
  450. upper_unbounded_tag,
  451. none_unbounded_tag
  452. >::type
  453. >::type dispatch;
  454. return range(lower,upper,dispatch());
  455. }
  456. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  457. ordered_index(const ctor_args_list& args_list,const allocator_type& al):
  458. super(args_list.get_tail(),al),
  459. key(tuples::get<0>(args_list.get_head())),
  460. comp(tuples::get<1>(args_list.get_head()))
  461. {
  462. empty_initialize();
  463. }
  464. ordered_index(
  465. const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x):
  466. super(x),
  467. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  468. safe_super(),
  469. #endif
  470. key(x.key),
  471. comp(x.comp)
  472. {
  473. /* Copy ctor just takes the key and compare objects from x. The rest is
  474. * done in subsequent call to copy_().
  475. */
  476. }
  477. ~ordered_index()
  478. {
  479. /* the container is guaranteed to be empty by now */
  480. }
  481. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  482. iterator make_iterator(node_type* node){return iterator(node,this);}
  483. const_iterator make_iterator(node_type* node)const
  484. {return const_iterator(node,const_cast<ordered_index*>(this));}
  485. #else
  486. iterator make_iterator(node_type* node){return iterator(node);}
  487. const_iterator make_iterator(node_type* node)const
  488. {return const_iterator(node);}
  489. #endif
  490. void copy_(
  491. const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
  492. const copy_map_type& map)
  493. {
  494. if(!x.root()){
  495. empty_initialize();
  496. }
  497. else{
  498. header()->color()=x.header()->color();
  499. node_type* root_cpy=map.find(static_cast<final_node_type*>(x.root()));
  500. header()->parent()=root_cpy->impl();
  501. node_type* leftmost_cpy=map.find(
  502. static_cast<final_node_type*>(x.leftmost()));
  503. header()->left()=leftmost_cpy->impl();
  504. node_type* rightmost_cpy=map.find(
  505. static_cast<final_node_type*>(x.rightmost()));
  506. header()->right()=rightmost_cpy->impl();
  507. typedef typename copy_map_type::const_iterator copy_map_iterator;
  508. for(copy_map_iterator it=map.begin(),it_end=map.end();it!=it_end;++it){
  509. node_type* org=it->first;
  510. node_type* cpy=it->second;
  511. cpy->color()=org->color();
  512. node_impl_pointer parent_org=org->parent();
  513. if(parent_org==node_impl_pointer(0))cpy->parent()=node_impl_pointer(0);
  514. else{
  515. node_type* parent_cpy=map.find(
  516. static_cast<final_node_type*>(node_type::from_impl(parent_org)));
  517. cpy->parent()=parent_cpy->impl();
  518. if(parent_org->left()==org->impl()){
  519. parent_cpy->left()=cpy->impl();
  520. }
  521. else if(parent_org->right()==org->impl()){
  522. /* header() does not satisfy this nor the previous check */
  523. parent_cpy->right()=cpy->impl();
  524. }
  525. }
  526. if(org->left()==node_impl_pointer(0))
  527. cpy->left()=node_impl_pointer(0);
  528. if(org->right()==node_impl_pointer(0))
  529. cpy->right()=node_impl_pointer(0);
  530. }
  531. }
  532. super::copy_(x,map);
  533. }
  534. node_type* insert_(value_param_type v,node_type* x)
  535. {
  536. link_info inf;
  537. if(!link_point(key(v),inf,Category())){
  538. return node_type::from_impl(inf.pos);
  539. }
  540. node_type* res=static_cast<node_type*>(super::insert_(v,x));
  541. if(res==x){
  542. node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
  543. }
  544. return res;
  545. }
  546. node_type* insert_(value_param_type v,node_type* position,node_type* x)
  547. {
  548. link_info inf;
  549. if(!hinted_link_point(key(v),position,inf,Category())){
  550. return node_type::from_impl(inf.pos);
  551. }
  552. node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
  553. if(res==x){
  554. node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
  555. }
  556. return res;
  557. }
  558. void erase_(node_type* x)
  559. {
  560. node_impl_type::rebalance_for_erase(
  561. x->impl(),header()->parent(),header()->left(),header()->right());
  562. super::erase_(x);
  563. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  564. detach_iterators(x);
  565. #endif
  566. }
  567. void delete_all_nodes_()
  568. {
  569. delete_all_nodes(root());
  570. }
  571. void clear_()
  572. {
  573. super::clear_();
  574. empty_initialize();
  575. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  576. safe_super::detach_dereferenceable_iterators();
  577. #endif
  578. }
  579. void swap_(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
  580. {
  581. std::swap(key,x.key);
  582. std::swap(comp,x.comp);
  583. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  584. safe_super::swap(x);
  585. #endif
  586. super::swap_(x);
  587. }
  588. bool replace_(value_param_type v,node_type* x)
  589. {
  590. if(in_place(v,x,Category())){
  591. return super::replace_(v,x);
  592. }
  593. node_type* next=x;
  594. node_type::increment(next);
  595. node_impl_type::rebalance_for_erase(
  596. x->impl(),header()->parent(),header()->left(),header()->right());
  597. BOOST_TRY{
  598. link_info inf;
  599. if(link_point(key(v),inf,Category())&&super::replace_(v,x)){
  600. node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
  601. return true;
  602. }
  603. node_impl_type::restore(x->impl(),next->impl(),header()->impl());
  604. return false;
  605. }
  606. BOOST_CATCH(...){
  607. node_impl_type::restore(x->impl(),next->impl(),header()->impl());
  608. BOOST_RETHROW;
  609. }
  610. BOOST_CATCH_END
  611. }
  612. bool modify_(node_type* x)
  613. {
  614. bool b;
  615. BOOST_TRY{
  616. b=in_place(x->value(),x,Category());
  617. }
  618. BOOST_CATCH(...){
  619. erase_(x);
  620. BOOST_RETHROW;
  621. }
  622. BOOST_CATCH_END
  623. if(!b){
  624. node_impl_type::rebalance_for_erase(
  625. x->impl(),header()->parent(),header()->left(),header()->right());
  626. BOOST_TRY{
  627. link_info inf;
  628. if(!link_point(key(x->value()),inf,Category())){
  629. super::erase_(x);
  630. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  631. detach_iterators(x);
  632. #endif
  633. return false;
  634. }
  635. node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
  636. }
  637. BOOST_CATCH(...){
  638. super::erase_(x);
  639. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  640. detach_iterators(x);
  641. #endif
  642. BOOST_RETHROW;
  643. }
  644. BOOST_CATCH_END
  645. }
  646. BOOST_TRY{
  647. if(!super::modify_(x)){
  648. node_impl_type::rebalance_for_erase(
  649. x->impl(),header()->parent(),header()->left(),header()->right());
  650. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  651. detach_iterators(x);
  652. #endif
  653. return false;
  654. }
  655. else return true;
  656. }
  657. BOOST_CATCH(...){
  658. node_impl_type::rebalance_for_erase(
  659. x->impl(),header()->parent(),header()->left(),header()->right());
  660. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  661. detach_iterators(x);
  662. #endif
  663. BOOST_RETHROW;
  664. }
  665. BOOST_CATCH_END
  666. }
  667. bool modify_rollback_(node_type* x)
  668. {
  669. if(in_place(x->value(),x,Category())){
  670. return super::modify_rollback_(x);
  671. }
  672. node_type* next=x;
  673. node_type::increment(next);
  674. node_impl_type::rebalance_for_erase(
  675. x->impl(),header()->parent(),header()->left(),header()->right());
  676. BOOST_TRY{
  677. link_info inf;
  678. if(link_point(key(x->value()),inf,Category())&&
  679. super::modify_rollback_(x)){
  680. node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
  681. return true;
  682. }
  683. node_impl_type::restore(x->impl(),next->impl(),header()->impl());
  684. return false;
  685. }
  686. BOOST_CATCH(...){
  687. node_impl_type::restore(x->impl(),next->impl(),header()->impl());
  688. BOOST_RETHROW;
  689. }
  690. BOOST_CATCH_END
  691. }
  692. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  693. /* serialization */
  694. template<typename Archive>
  695. void save_(
  696. Archive& ar,const unsigned int version,const index_saver_type& sm)const
  697. {
  698. save_(ar,version,sm,Category());
  699. }
  700. template<typename Archive>
  701. void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
  702. {
  703. load_(ar,version,lm,Category());
  704. }
  705. #endif
  706. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  707. /* invariant stuff */
  708. bool invariant_()const
  709. {
  710. if(size()==0||begin()==end()){
  711. if(size()!=0||begin()!=end()||
  712. header()->left()!=header()->impl()||
  713. header()->right()!=header()->impl())return false;
  714. }
  715. else{
  716. if((size_type)std::distance(begin(),end())!=size())return false;
  717. std::size_t len=node_impl_type::black_count(
  718. leftmost()->impl(),root()->impl());
  719. for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
  720. node_type* x=it.get_node();
  721. node_type* left_x=node_type::from_impl(x->left());
  722. node_type* right_x=node_type::from_impl(x->right());
  723. if(x->color()==red){
  724. if((left_x&&left_x->color()==red)||
  725. (right_x&&right_x->color()==red))return false;
  726. }
  727. if(left_x&&comp(key(x->value()),key(left_x->value())))return false;
  728. if(right_x&&comp(key(right_x->value()),key(x->value())))return false;
  729. if(!left_x&&!right_x&&
  730. node_impl_type::black_count(x->impl(),root()->impl())!=len)
  731. return false;
  732. }
  733. if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
  734. return false;
  735. if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
  736. return false;
  737. }
  738. return super::invariant_();
  739. }
  740. /* This forwarding function eases things for the boost::mem_fn construct
  741. * in BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT. Actually,
  742. * final_check_invariant is already an inherited member function of
  743. * ordered_index.
  744. */
  745. void check_invariant_()const{this->final_check_invariant_();}
  746. #endif
  747. private:
  748. node_type* header()const{return this->final_header();}
  749. node_type* root()const{return node_type::from_impl(header()->parent());}
  750. node_type* leftmost()const{return node_type::from_impl(header()->left());}
  751. node_type* rightmost()const{return node_type::from_impl(header()->right());}
  752. void empty_initialize()
  753. {
  754. header()->color()=red;
  755. /* used to distinguish header() from root, in iterator.operator++ */
  756. header()->parent()=node_impl_pointer(0);
  757. header()->left()=header()->impl();
  758. header()->right()=header()->impl();
  759. }
  760. struct link_info
  761. {
  762. link_info():side(to_left){}
  763. ordered_index_side side;
  764. node_impl_pointer pos;
  765. };
  766. bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
  767. {
  768. node_type* y=header();
  769. node_type* x=root();
  770. bool c=true;
  771. while(x){
  772. y=x;
  773. c=comp(k,key(x->value()));
  774. x=node_type::from_impl(c?x->left():x->right());
  775. }
  776. node_type* yy=y;
  777. if(c){
  778. if(yy==leftmost()){
  779. inf.side=to_left;
  780. inf.pos=y->impl();
  781. return true;
  782. }
  783. else node_type::decrement(yy);
  784. }
  785. if(comp(key(yy->value()),k)){
  786. inf.side=c?to_left:to_right;
  787. inf.pos=y->impl();
  788. return true;
  789. }
  790. else{
  791. inf.pos=yy->impl();
  792. return false;
  793. }
  794. }
  795. bool link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
  796. {
  797. node_type* y=header();
  798. node_type* x=root();
  799. bool c=true;
  800. while (x){
  801. y=x;
  802. c=comp(k,key(x->value()));
  803. x=node_type::from_impl(c?x->left():x->right());
  804. }
  805. inf.side=c?to_left:to_right;
  806. inf.pos=y->impl();
  807. return true;
  808. }
  809. bool lower_link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
  810. {
  811. node_type* y=header();
  812. node_type* x=root();
  813. bool c=false;
  814. while (x){
  815. y=x;
  816. c=comp(key(x->value()),k);
  817. x=node_type::from_impl(c?x->right():x->left());
  818. }
  819. inf.side=c?to_right:to_left;
  820. inf.pos=y->impl();
  821. return true;
  822. }
  823. bool hinted_link_point(
  824. key_param_type k,node_type* position,link_info& inf,ordered_unique_tag)
  825. {
  826. if(position->impl()==header()->left()){
  827. if(size()>0&&comp(k,key(position->value()))){
  828. inf.side=to_left;
  829. inf.pos=position->impl();
  830. return true;
  831. }
  832. else return link_point(k,inf,ordered_unique_tag());
  833. }
  834. else if(position==header()){
  835. if(comp(key(rightmost()->value()),k)){
  836. inf.side=to_right;
  837. inf.pos=rightmost()->impl();
  838. return true;
  839. }
  840. else return link_point(k,inf,ordered_unique_tag());
  841. }
  842. else{
  843. node_type* before=position;
  844. node_type::decrement(before);
  845. if(comp(key(before->value()),k)&&comp(k,key(position->value()))){
  846. if(before->right()==node_impl_pointer(0)){
  847. inf.side=to_right;
  848. inf.pos=before->impl();
  849. return true;
  850. }
  851. else{
  852. inf.side=to_left;
  853. inf.pos=position->impl();
  854. return true;
  855. }
  856. }
  857. else return link_point(k,inf,ordered_unique_tag());
  858. }
  859. }
  860. bool hinted_link_point(
  861. key_param_type k,node_type* position,link_info& inf,ordered_non_unique_tag)
  862. {
  863. if(position->impl()==header()->left()){
  864. if(size()>0&&!comp(key(position->value()),k)){
  865. inf.side=to_left;
  866. inf.pos=position->impl();
  867. return true;
  868. }
  869. else return lower_link_point(k,inf,ordered_non_unique_tag());
  870. }
  871. else if(position==header()){
  872. if(!comp(k,key(rightmost()->value()))){
  873. inf.side=to_right;
  874. inf.pos=rightmost()->impl();
  875. return true;
  876. }
  877. else return link_point(k,inf,ordered_non_unique_tag());
  878. }
  879. else{
  880. node_type* before=position;
  881. node_type::decrement(before);
  882. if(!comp(k,key(before->value()))){
  883. if(!comp(key(position->value()),k)){
  884. if(before->right()==node_impl_pointer(0)){
  885. inf.side=to_right;
  886. inf.pos=before->impl();
  887. return true;
  888. }
  889. else{
  890. inf.side=to_left;
  891. inf.pos=position->impl();
  892. return true;
  893. }
  894. }
  895. else return lower_link_point(k,inf,ordered_non_unique_tag());
  896. }
  897. else return link_point(k,inf,ordered_non_unique_tag());
  898. }
  899. }
  900. void delete_all_nodes(node_type* x)
  901. {
  902. if(!x)return;
  903. delete_all_nodes(node_type::from_impl(x->left()));
  904. delete_all_nodes(node_type::from_impl(x->right()));
  905. this->final_delete_node_(static_cast<final_node_type*>(x));
  906. }
  907. bool in_place(value_param_type v,node_type* x,ordered_unique_tag)
  908. {
  909. node_type* y;
  910. if(x!=leftmost()){
  911. y=x;
  912. node_type::decrement(y);
  913. if(!comp(key(y->value()),key(v)))return false;
  914. }
  915. y=x;
  916. node_type::increment(y);
  917. return y==header()||comp(key(v),key(y->value()));
  918. }
  919. bool in_place(value_param_type v,node_type* x,ordered_non_unique_tag)
  920. {
  921. node_type* y;
  922. if(x!=leftmost()){
  923. y=x;
  924. node_type::decrement(y);
  925. if(comp(key(v),key(y->value())))return false;
  926. }
  927. y=x;
  928. node_type::increment(y);
  929. return y==header()||!comp(key(y->value()),key(v));
  930. }
  931. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  932. void detach_iterators(node_type* x)
  933. {
  934. iterator it=make_iterator(x);
  935. safe_mode::detach_equivalent_iterators(it);
  936. }
  937. #endif
  938. template<typename LowerBounder,typename UpperBounder>
  939. std::pair<iterator,iterator>
  940. range(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
  941. {
  942. node_type* y=header();
  943. node_type* z=root();
  944. while(z){
  945. if(!lower(key(z->value()))){
  946. z=node_type::from_impl(z->right());
  947. }
  948. else if(!upper(key(z->value()))){
  949. y=z;
  950. z=node_type::from_impl(z->left());
  951. }
  952. else{
  953. return std::pair<iterator,iterator>(
  954. make_iterator(
  955. lower_range(node_type::from_impl(z->left()),z,lower)),
  956. make_iterator(
  957. upper_range(node_type::from_impl(z->right()),y,upper)));
  958. }
  959. }
  960. return std::pair<iterator,iterator>(make_iterator(y),make_iterator(y));
  961. }
  962. template<typename LowerBounder,typename UpperBounder>
  963. std::pair<iterator,iterator>
  964. range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
  965. {
  966. return std::pair<iterator,iterator>(
  967. begin(),
  968. make_iterator(upper_range(root(),header(),upper)));
  969. }
  970. template<typename LowerBounder,typename UpperBounder>
  971. std::pair<iterator,iterator>
  972. range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
  973. {
  974. return std::pair<iterator,iterator>(
  975. make_iterator(lower_range(root(),header(),lower)),
  976. end());
  977. }
  978. template<typename LowerBounder,typename UpperBounder>
  979. std::pair<iterator,iterator>
  980. range(LowerBounder,UpperBounder,both_unbounded_tag)const
  981. {
  982. return std::pair<iterator,iterator>(begin(),end());
  983. }
  984. template<typename LowerBounder>
  985. node_type * lower_range(node_type* top,node_type* y,LowerBounder lower)const
  986. {
  987. while(top){
  988. if(lower(key(top->value()))){
  989. y=top;
  990. top=node_type::from_impl(top->left());
  991. }
  992. else top=node_type::from_impl(top->right());
  993. }
  994. return y;
  995. }
  996. template<typename UpperBounder>
  997. node_type * upper_range(node_type* top,node_type* y,UpperBounder upper)const
  998. {
  999. while(top){
  1000. if(!upper(key(top->value()))){
  1001. y=top;
  1002. top=node_type::from_impl(top->left());
  1003. }
  1004. else top=node_type::from_impl(top->right());
  1005. }
  1006. return y;
  1007. }
  1008. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  1009. template<typename Archive>
  1010. void save_(
  1011. Archive& ar,const unsigned int version,const index_saver_type& sm,
  1012. ordered_unique_tag)const
  1013. {
  1014. super::save_(ar,version,sm);
  1015. }
  1016. template<typename Archive>
  1017. void load_(
  1018. Archive& ar,const unsigned int version,const index_loader_type& lm,
  1019. ordered_unique_tag)
  1020. {
  1021. super::load_(ar,version,lm);
  1022. }
  1023. template<typename Archive>
  1024. void save_(
  1025. Archive& ar,const unsigned int version,const index_saver_type& sm,
  1026. ordered_non_unique_tag)const
  1027. {
  1028. typedef duplicates_iterator<node_type,value_compare> dup_iterator;
  1029. sm.save(
  1030. dup_iterator(begin().get_node(),end().get_node(),value_comp()),
  1031. dup_iterator(end().get_node(),value_comp()),
  1032. ar,version);
  1033. super::save_(ar,version,sm);
  1034. }
  1035. template<typename Archive>
  1036. void load_(
  1037. Archive& ar,const unsigned int version,const index_loader_type& lm,
  1038. ordered_non_unique_tag)
  1039. {
  1040. lm.load(
  1041. ::boost::bind(&ordered_index::rearranger,this,_1,_2),
  1042. ar,version);
  1043. super::load_(ar,version,lm);
  1044. }
  1045. void rearranger(node_type* position,node_type *x)
  1046. {
  1047. if(!position||comp(key(position->value()),key(x->value()))){
  1048. position=lower_bound(key(x->value())).get_node();
  1049. }
  1050. else if(comp(key(x->value()),key(position->value()))){
  1051. /* inconsistent rearrangement */
  1052. throw_exception(
  1053. archive::archive_exception(
  1054. archive::archive_exception::other_exception));
  1055. }
  1056. else node_type::increment(position);
  1057. if(position!=x){
  1058. node_impl_type::rebalance_for_erase(
  1059. x->impl(),header()->parent(),header()->left(),header()->right());
  1060. node_impl_type::restore(
  1061. x->impl(),position->impl(),header()->impl());
  1062. }
  1063. }
  1064. #endif /* serialization */
  1065. key_from_value key;
  1066. key_compare comp;
  1067. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  1068. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  1069. #pragma parse_mfunc_templ reset
  1070. #endif
  1071. };
  1072. /* comparison */
  1073. template<
  1074. typename KeyFromValue1,typename Compare1,
  1075. typename SuperMeta1,typename TagList1,typename Category1,
  1076. typename KeyFromValue2,typename Compare2,
  1077. typename SuperMeta2,typename TagList2,typename Category2
  1078. >
  1079. bool operator==(
  1080. const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
  1081. const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
  1082. {
  1083. return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
  1084. }
  1085. template<
  1086. typename KeyFromValue1,typename Compare1,
  1087. typename SuperMeta1,typename TagList1,typename Category1,
  1088. typename KeyFromValue2,typename Compare2,
  1089. typename SuperMeta2,typename TagList2,typename Category2
  1090. >
  1091. bool operator<(
  1092. const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
  1093. const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
  1094. {
  1095. return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
  1096. }
  1097. template<
  1098. typename KeyFromValue1,typename Compare1,
  1099. typename SuperMeta1,typename TagList1,typename Category1,
  1100. typename KeyFromValue2,typename Compare2,
  1101. typename SuperMeta2,typename TagList2,typename Category2
  1102. >
  1103. bool operator!=(
  1104. const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
  1105. const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
  1106. {
  1107. return !(x==y);
  1108. }
  1109. template<
  1110. typename KeyFromValue1,typename Compare1,
  1111. typename SuperMeta1,typename TagList1,typename Category1,
  1112. typename KeyFromValue2,typename Compare2,
  1113. typename SuperMeta2,typename TagList2,typename Category2
  1114. >
  1115. bool operator>(
  1116. const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
  1117. const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
  1118. {
  1119. return y<x;
  1120. }
  1121. template<
  1122. typename KeyFromValue1,typename Compare1,
  1123. typename SuperMeta1,typename TagList1,typename Category1,
  1124. typename KeyFromValue2,typename Compare2,
  1125. typename SuperMeta2,typename TagList2,typename Category2
  1126. >
  1127. bool operator>=(
  1128. const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
  1129. const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
  1130. {
  1131. return !(x<y);
  1132. }
  1133. template<
  1134. typename KeyFromValue1,typename Compare1,
  1135. typename SuperMeta1,typename TagList1,typename Category1,
  1136. typename KeyFromValue2,typename Compare2,
  1137. typename SuperMeta2,typename TagList2,typename Category2
  1138. >
  1139. bool operator<=(
  1140. const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
  1141. const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
  1142. {
  1143. return !(x>y);
  1144. }
  1145. /* specialized algorithms */
  1146. template<
  1147. typename KeyFromValue,typename Compare,
  1148. typename SuperMeta,typename TagList,typename Category
  1149. >
  1150. void swap(
  1151. ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
  1152. ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& y)
  1153. {
  1154. x.swap(y);
  1155. }
  1156. } /* namespace multi_index::detail */
  1157. /* ordered_index specifiers */
  1158. template<typename Arg1,typename Arg2,typename Arg3>
  1159. struct ordered_unique
  1160. {
  1161. typedef typename detail::ordered_index_args<
  1162. Arg1,Arg2,Arg3> index_args;
  1163. typedef typename index_args::tag_list_type::type tag_list_type;
  1164. typedef typename index_args::key_from_value_type key_from_value_type;
  1165. typedef typename index_args::compare_type compare_type;
  1166. template<typename Super>
  1167. struct node_class
  1168. {
  1169. typedef detail::ordered_index_node<Super> type;
  1170. };
  1171. template<typename SuperMeta>
  1172. struct index_class
  1173. {
  1174. typedef detail::ordered_index<
  1175. key_from_value_type,compare_type,
  1176. SuperMeta,tag_list_type,detail::ordered_unique_tag> type;
  1177. };
  1178. };
  1179. template<typename Arg1,typename Arg2,typename Arg3>
  1180. struct ordered_non_unique
  1181. {
  1182. typedef detail::ordered_index_args<
  1183. Arg1,Arg2,Arg3> index_args;
  1184. typedef typename index_args::tag_list_type::type tag_list_type;
  1185. typedef typename index_args::key_from_value_type key_from_value_type;
  1186. typedef typename index_args::compare_type compare_type;
  1187. template<typename Super>
  1188. struct node_class
  1189. {
  1190. typedef detail::ordered_index_node<Super> type;
  1191. };
  1192. template<typename SuperMeta>
  1193. struct index_class
  1194. {
  1195. typedef detail::ordered_index<
  1196. key_from_value_type,compare_type,
  1197. SuperMeta,tag_list_type,detail::ordered_non_unique_tag> type;
  1198. };
  1199. };
  1200. } /* namespace multi_index */
  1201. } /* namespace boost */
  1202. #undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
  1203. #endif