fix doc example typo
[boost.git] / boost / multi_index / ordered_index.hpp
blobf4b2519c4048511ba48e7260a42c2116a87a5cd5
1 /* Copyright 2003-2008 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)
6 * See http://www.boost.org/libs/multi_index for library home page.
8 * The internal implementation of red-black trees is based on that of SGI STL
9 * stl_tree.h file:
11 * Copyright (c) 1996,1997
12 * Silicon Graphics Computer Systems, Inc.
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.
23 * Copyright (c) 1994
24 * Hewlett-Packard Company
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.
36 #ifndef BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
37 #define BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
39 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
40 #pragma once
41 #endif
43 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
44 #include <algorithm>
45 #include <boost/call_traits.hpp>
46 #include <boost/detail/no_exceptions_support.hpp>
47 #include <boost/detail/workaround.hpp>
48 #include <boost/iterator/reverse_iterator.hpp>
49 #include <boost/mpl/if.hpp>
50 #include <boost/mpl/push_front.hpp>
51 #include <boost/multi_index/detail/access_specifier.hpp>
52 #include <boost/multi_index/detail/bidir_node_iterator.hpp>
53 #include <boost/multi_index/detail/index_node_base.hpp>
54 #include <boost/multi_index/detail/modify_key_adaptor.hpp>
55 #include <boost/multi_index/detail/ord_index_node.hpp>
56 #include <boost/multi_index/detail/ord_index_ops.hpp>
57 #include <boost/multi_index/detail/safe_ctr_proxy.hpp>
58 #include <boost/multi_index/detail/safe_mode.hpp>
59 #include <boost/multi_index/detail/scope_guard.hpp>
60 #include <boost/multi_index/detail/unbounded.hpp>
61 #include <boost/multi_index/detail/value_compare.hpp>
62 #include <boost/multi_index/ordered_index_fwd.hpp>
63 #include <boost/ref.hpp>
64 #include <boost/tuple/tuple.hpp>
65 #include <boost/type_traits/is_same.hpp>
66 #include <utility>
68 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
69 #include <boost/archive/archive_exception.hpp>
70 #include <boost/bind.hpp>
71 #include <boost/multi_index/detail/duplicates_iterator.hpp>
72 #include <boost/throw_exception.hpp>
73 #endif
75 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
76 #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT \
77 detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
78 detail::make_obj_guard(*this,&ordered_index::check_invariant_); \
79 BOOST_JOIN(check_invariant_,__LINE__).touch();
80 #else
81 #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
82 #endif
84 namespace boost{
86 namespace multi_index{
88 namespace detail{
90 /* ordered_index adds a layer of ordered indexing to a given Super */
92 /* Most of the implementation of unique and non-unique indices is
93 * shared. We tell from one another on instantiation time by using
94 * these tags.
97 struct ordered_unique_tag{};
98 struct ordered_non_unique_tag{};
100 template<
101 typename KeyFromValue,typename Compare,
102 typename SuperMeta,typename TagList,typename Category
104 class ordered_index:
105 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
107 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
108 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
109 ,public safe_ctr_proxy_impl<
110 bidir_node_iterator<
111 ordered_index_node<typename SuperMeta::type::node_type> >,
112 ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
113 #else
114 ,public safe_mode::safe_container<
115 ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category> >
116 #endif
117 #endif
120 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
121 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
122 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
123 * lifetime of const references bound to temporaries --precisely what
124 * scopeguards are.
127 #pragma parse_mfunc_templ off
128 #endif
130 typedef typename SuperMeta::type super;
132 protected:
133 typedef ordered_index_node<
134 typename super::node_type> node_type;
136 private:
137 typedef typename node_type::impl_type node_impl_type;
138 typedef typename node_impl_type::pointer node_impl_pointer;
140 public:
141 /* types */
143 typedef typename KeyFromValue::result_type key_type;
144 typedef typename node_type::value_type value_type;
145 typedef KeyFromValue key_from_value;
146 typedef Compare key_compare;
147 typedef value_comparison<
148 value_type,KeyFromValue,Compare> value_compare;
149 typedef tuple<key_from_value,key_compare> ctor_args;
150 typedef typename super::final_allocator_type allocator_type;
151 typedef typename allocator_type::reference reference;
152 typedef typename allocator_type::const_reference const_reference;
154 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
155 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
156 typedef safe_mode::safe_iterator<
157 bidir_node_iterator<node_type>,
158 safe_ctr_proxy<
159 bidir_node_iterator<node_type> > > iterator;
160 #else
161 typedef safe_mode::safe_iterator<
162 bidir_node_iterator<node_type>,
163 ordered_index> iterator;
164 #endif
165 #else
166 typedef bidir_node_iterator<node_type> iterator;
167 #endif
169 typedef iterator const_iterator;
171 typedef std::size_t size_type;
172 typedef std::ptrdiff_t difference_type;
173 typedef typename allocator_type::pointer pointer;
174 typedef typename allocator_type::const_pointer const_pointer;
175 typedef typename
176 boost::reverse_iterator<iterator> reverse_iterator;
177 typedef typename
178 boost::reverse_iterator<const_iterator> const_reverse_iterator;
179 typedef TagList tag_list;
181 protected:
182 typedef typename super::final_node_type final_node_type;
183 typedef tuples::cons<
184 ctor_args,
185 typename super::ctor_args_list> ctor_args_list;
186 typedef typename mpl::push_front<
187 typename super::index_type_list,
188 ordered_index>::type index_type_list;
189 typedef typename mpl::push_front<
190 typename super::iterator_type_list,
191 iterator>::type iterator_type_list;
192 typedef typename mpl::push_front<
193 typename super::const_iterator_type_list,
194 const_iterator>::type const_iterator_type_list;
195 typedef typename super::copy_map_type copy_map_type;
197 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
198 typedef typename super::index_saver_type index_saver_type;
199 typedef typename super::index_loader_type index_loader_type;
200 #endif
202 private:
203 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
204 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
205 typedef safe_ctr_proxy_impl<
206 bidir_node_iterator<node_type>,
207 ordered_index> safe_super;
208 #else
209 typedef safe_mode::safe_container<ordered_index> safe_super;
210 #endif
211 #endif
213 typedef typename call_traits<
214 value_type>::param_type value_param_type;
215 typedef typename call_traits<
216 key_type>::param_type key_param_type;
218 public:
220 /* construct/copy/destroy
221 * Default and copy ctors are in the protected section as indices are
222 * not supposed to be created on their own. No range ctor either.
225 ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& operator=(
226 const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
228 this->final()=x.final();
229 return *this;
232 allocator_type get_allocator()const
234 return this->final().get_allocator();
237 /* iterators */
239 iterator begin(){return make_iterator(leftmost());}
240 const_iterator begin()const{return make_iterator(leftmost());}
241 iterator end(){return make_iterator(header());}
242 const_iterator end()const{return make_iterator(header());}
243 reverse_iterator rbegin(){return make_reverse_iterator(end());}
244 const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
245 reverse_iterator rend(){return make_reverse_iterator(begin());}
246 const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
247 const_iterator cbegin()const{return begin();}
248 const_iterator cend()const{return end();}
249 const_reverse_iterator crbegin()const{return rbegin();}
250 const_reverse_iterator crend()const{return rend();}
252 iterator iterator_to(const value_type& x)
254 return make_iterator(node_from_value<node_type>(&x));
257 const_iterator iterator_to(const value_type& x)const
259 return make_iterator(node_from_value<node_type>(&x));
262 /* capacity */
264 bool empty()const{return this->final_empty_();}
265 size_type size()const{return this->final_size_();}
266 size_type max_size()const{return this->final_max_size_();}
268 /* modifiers */
270 std::pair<iterator,bool> insert(value_param_type x)
272 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
273 std::pair<final_node_type*,bool> p=this->final_insert_(x);
274 return std::pair<iterator,bool>(make_iterator(p.first),p.second);
277 iterator insert(iterator position,value_param_type x)
279 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
280 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
281 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
282 std::pair<final_node_type*,bool> p=this->final_insert_(
283 x,static_cast<final_node_type*>(position.get_node()));
284 return make_iterator(p.first);
287 template<typename InputIterator>
288 void insert(InputIterator first,InputIterator last)
290 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
291 iterator hint=end();
292 for(;first!=last;++first)hint=insert(hint,*first);
295 iterator erase(iterator position)
297 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
298 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
299 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
300 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
301 this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
302 return position;
305 size_type erase(key_param_type x)
307 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
308 std::pair<iterator,iterator> p=equal_range(x);
309 size_type s=0;
310 while(p.first!=p.second){
311 p.first=erase(p.first);
312 ++s;
314 return s;
317 iterator erase(iterator first,iterator last)
319 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
320 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
321 BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
322 BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
323 BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
324 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
325 while(first!=last){
326 first=erase(first);
328 return first;
331 bool replace(iterator position,value_param_type x)
333 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
334 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
335 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
336 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
337 return this->final_replace_(
338 x,static_cast<final_node_type*>(position.get_node()));
341 template<typename Modifier>
342 bool modify(iterator position,Modifier mod)
344 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
345 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
346 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
347 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
349 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
350 /* MSVC++ 6.0 optimizer on safe mode code chokes if this
351 * this is not added. Left it for all compilers as it does no
352 * harm.
355 position.detach();
356 #endif
358 return this->final_modify_(
359 mod,static_cast<final_node_type*>(position.get_node()));
362 template<typename Modifier,typename Rollback>
363 bool modify(iterator position,Modifier mod,Rollback back)
365 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
366 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
367 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
368 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
370 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
371 /* MSVC++ 6.0 optimizer on safe mode code chokes if this
372 * this is not added. Left it for all compilers as it does no
373 * harm.
376 position.detach();
377 #endif
379 return this->final_modify_(
380 mod,back,static_cast<final_node_type*>(position.get_node()));
383 template<typename Modifier>
384 bool modify_key(iterator position,Modifier mod)
386 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
387 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
388 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
389 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
390 return modify(
391 position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
394 template<typename Modifier,typename Rollback>
395 bool modify_key(iterator position,Modifier mod,Rollback back)
397 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
398 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
399 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
400 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
401 return modify(
402 position,
403 modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
404 modify_key_adaptor<Modifier,value_type,KeyFromValue>(back,key));
407 void swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
409 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
410 this->final_swap_(x.final());
413 void clear()
415 BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
416 this->final_clear_();
419 /* observers */
421 key_from_value key_extractor()const{return key;}
422 key_compare key_comp()const{return comp;}
423 value_compare value_comp()const{return value_compare(key,comp);}
425 /* set operations */
427 /* Internally, these ops rely on const_iterator being the same
428 * type as iterator.
431 template<typename CompatibleKey>
432 iterator find(const CompatibleKey& x)const
434 return make_iterator(ordered_index_find(root(),header(),key,x,comp));
437 template<typename CompatibleKey,typename CompatibleCompare>
438 iterator find(
439 const CompatibleKey& x,const CompatibleCompare& comp)const
441 return make_iterator(ordered_index_find(root(),header(),key,x,comp));
444 template<typename CompatibleKey>
445 size_type count(const CompatibleKey& x)const
447 return count(x,comp);
450 template<typename CompatibleKey,typename CompatibleCompare>
451 size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
453 std::pair<iterator,iterator> p=equal_range(x,comp);
454 size_type n=std::distance(p.first,p.second);
455 return n;
458 template<typename CompatibleKey>
459 iterator lower_bound(const CompatibleKey& x)const
461 return make_iterator(
462 ordered_index_lower_bound(root(),header(),key,x,comp));
465 template<typename CompatibleKey,typename CompatibleCompare>
466 iterator lower_bound(
467 const CompatibleKey& x,const CompatibleCompare& comp)const
469 return make_iterator(
470 ordered_index_lower_bound(root(),header(),key,x,comp));
473 template<typename CompatibleKey>
474 iterator upper_bound(const CompatibleKey& x)const
476 return make_iterator(
477 ordered_index_upper_bound(root(),header(),key,x,comp));
480 template<typename CompatibleKey,typename CompatibleCompare>
481 iterator upper_bound(
482 const CompatibleKey& x,const CompatibleCompare& comp)const
484 return make_iterator(
485 ordered_index_upper_bound(root(),header(),key,x,comp));
488 template<typename CompatibleKey>
489 std::pair<iterator,iterator> equal_range(
490 const CompatibleKey& x)const
492 std::pair<node_type*,node_type*> p=
493 ordered_index_equal_range(root(),header(),key,x,comp);
494 return std::pair<iterator,iterator>(
495 make_iterator(p.first),make_iterator(p.second));
498 template<typename CompatibleKey,typename CompatibleCompare>
499 std::pair<iterator,iterator> equal_range(
500 const CompatibleKey& x,const CompatibleCompare& comp)const
502 std::pair<node_type*,node_type*> p=
503 ordered_index_equal_range(root(),header(),key,x,comp);
504 return std::pair<iterator,iterator>(
505 make_iterator(p.first),make_iterator(p.second));
508 /* range */
510 template<typename LowerBounder,typename UpperBounder>
511 std::pair<iterator,iterator>
512 range(LowerBounder lower,UpperBounder upper)const
514 typedef typename mpl::if_<
515 is_same<LowerBounder,unbounded_type>,
516 BOOST_DEDUCED_TYPENAME mpl::if_<
517 is_same<UpperBounder,unbounded_type>,
518 both_unbounded_tag,
519 lower_unbounded_tag
520 >::type,
521 BOOST_DEDUCED_TYPENAME mpl::if_<
522 is_same<UpperBounder,unbounded_type>,
523 upper_unbounded_tag,
524 none_unbounded_tag
525 >::type
526 >::type dispatch;
528 return range(lower,upper,dispatch());
531 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
532 ordered_index(const ctor_args_list& args_list,const allocator_type& al):
533 super(args_list.get_tail(),al),
534 key(tuples::get<0>(args_list.get_head())),
535 comp(tuples::get<1>(args_list.get_head()))
537 empty_initialize();
540 ordered_index(
541 const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x):
542 super(x),
544 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
545 safe_super(),
546 #endif
548 key(x.key),
549 comp(x.comp)
551 /* Copy ctor just takes the key and compare objects from x. The rest is
552 * done in subsequent call to copy_().
556 ~ordered_index()
558 /* the container is guaranteed to be empty by now */
561 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
562 iterator make_iterator(node_type* node){return iterator(node,this);}
563 const_iterator make_iterator(node_type* node)const
564 {return const_iterator(node,const_cast<ordered_index*>(this));}
565 #else
566 iterator make_iterator(node_type* node){return iterator(node);}
567 const_iterator make_iterator(node_type* node)const
568 {return const_iterator(node);}
569 #endif
571 void copy_(
572 const ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
573 const copy_map_type& map)
575 if(!x.root()){
576 empty_initialize();
578 else{
579 header()->color()=x.header()->color();
581 node_type* root_cpy=map.find(static_cast<final_node_type*>(x.root()));
582 header()->parent()=root_cpy->impl();
584 node_type* leftmost_cpy=map.find(
585 static_cast<final_node_type*>(x.leftmost()));
586 header()->left()=leftmost_cpy->impl();
588 node_type* rightmost_cpy=map.find(
589 static_cast<final_node_type*>(x.rightmost()));
590 header()->right()=rightmost_cpy->impl();
592 typedef typename copy_map_type::const_iterator copy_map_iterator;
593 for(copy_map_iterator it=map.begin(),it_end=map.end();it!=it_end;++it){
594 node_type* org=it->first;
595 node_type* cpy=it->second;
597 cpy->color()=org->color();
599 node_impl_pointer parent_org=org->parent();
600 if(parent_org==node_impl_pointer(0))cpy->parent()=node_impl_pointer(0);
601 else{
602 node_type* parent_cpy=map.find(
603 static_cast<final_node_type*>(node_type::from_impl(parent_org)));
604 cpy->parent()=parent_cpy->impl();
605 if(parent_org->left()==org->impl()){
606 parent_cpy->left()=cpy->impl();
608 else if(parent_org->right()==org->impl()){
609 /* header() does not satisfy this nor the previous check */
610 parent_cpy->right()=cpy->impl();
614 if(org->left()==node_impl_pointer(0))
615 cpy->left()=node_impl_pointer(0);
616 if(org->right()==node_impl_pointer(0))
617 cpy->right()=node_impl_pointer(0);
621 super::copy_(x,map);
624 node_type* insert_(value_param_type v,node_type* x)
626 link_info inf;
627 if(!link_point(key(v),inf,Category())){
628 return node_type::from_impl(inf.pos);
631 node_type* res=static_cast<node_type*>(super::insert_(v,x));
632 if(res==x){
633 node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
635 return res;
638 node_type* insert_(value_param_type v,node_type* position,node_type* x)
640 link_info inf;
641 if(!hinted_link_point(key(v),position,inf,Category())){
642 return node_type::from_impl(inf.pos);
645 node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
646 if(res==x){
647 node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
649 return res;
652 void erase_(node_type* x)
654 node_impl_type::rebalance_for_erase(
655 x->impl(),header()->parent(),header()->left(),header()->right());
656 super::erase_(x);
658 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
659 detach_iterators(x);
660 #endif
663 void delete_all_nodes_()
665 delete_all_nodes(root());
668 void clear_()
670 super::clear_();
671 empty_initialize();
673 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
674 safe_super::detach_dereferenceable_iterators();
675 #endif
678 void swap_(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
680 std::swap(key,x.key);
681 std::swap(comp,x.comp);
683 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
684 safe_super::swap(x);
685 #endif
687 super::swap_(x);
690 bool replace_(value_param_type v,node_type* x)
692 if(in_place(v,x,Category())){
693 return super::replace_(v,x);
696 node_type* next=x;
697 node_type::increment(next);
699 node_impl_type::rebalance_for_erase(
700 x->impl(),header()->parent(),header()->left(),header()->right());
702 BOOST_TRY{
703 link_info inf;
704 if(link_point(key(v),inf,Category())&&super::replace_(v,x)){
705 node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
706 return true;
708 node_impl_type::restore(x->impl(),next->impl(),header()->impl());
709 return false;
711 BOOST_CATCH(...){
712 node_impl_type::restore(x->impl(),next->impl(),header()->impl());
713 BOOST_RETHROW;
715 BOOST_CATCH_END
718 bool modify_(node_type* x)
720 bool b;
721 BOOST_TRY{
722 b=in_place(x->value(),x,Category());
724 BOOST_CATCH(...){
725 erase_(x);
726 BOOST_RETHROW;
728 BOOST_CATCH_END
729 if(!b){
730 node_impl_type::rebalance_for_erase(
731 x->impl(),header()->parent(),header()->left(),header()->right());
732 BOOST_TRY{
733 link_info inf;
734 if(!link_point(key(x->value()),inf,Category())){
735 super::erase_(x);
737 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
738 detach_iterators(x);
739 #endif
740 return false;
742 node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
744 BOOST_CATCH(...){
745 super::erase_(x);
747 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
748 detach_iterators(x);
749 #endif
751 BOOST_RETHROW;
753 BOOST_CATCH_END
756 BOOST_TRY{
757 if(!super::modify_(x)){
758 node_impl_type::rebalance_for_erase(
759 x->impl(),header()->parent(),header()->left(),header()->right());
761 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
762 detach_iterators(x);
763 #endif
765 return false;
767 else return true;
769 BOOST_CATCH(...){
770 node_impl_type::rebalance_for_erase(
771 x->impl(),header()->parent(),header()->left(),header()->right());
773 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
774 detach_iterators(x);
775 #endif
777 BOOST_RETHROW;
779 BOOST_CATCH_END
782 bool modify_rollback_(node_type* x)
784 if(in_place(x->value(),x,Category())){
785 return super::modify_rollback_(x);
788 node_type* next=x;
789 node_type::increment(next);
791 node_impl_type::rebalance_for_erase(
792 x->impl(),header()->parent(),header()->left(),header()->right());
794 BOOST_TRY{
795 link_info inf;
796 if(link_point(key(x->value()),inf,Category())&&
797 super::modify_rollback_(x)){
798 node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
799 return true;
801 node_impl_type::restore(x->impl(),next->impl(),header()->impl());
802 return false;
804 BOOST_CATCH(...){
805 node_impl_type::restore(x->impl(),next->impl(),header()->impl());
806 BOOST_RETHROW;
808 BOOST_CATCH_END
811 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
812 /* serialization */
814 template<typename Archive>
815 void save_(
816 Archive& ar,const unsigned int version,const index_saver_type& sm)const
818 save_(ar,version,sm,Category());
821 template<typename Archive>
822 void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
824 load_(ar,version,lm,Category());
826 #endif
828 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
829 /* invariant stuff */
831 bool invariant_()const
833 if(size()==0||begin()==end()){
834 if(size()!=0||begin()!=end()||
835 header()->left()!=header()->impl()||
836 header()->right()!=header()->impl())return false;
838 else{
839 if((size_type)std::distance(begin(),end())!=size())return false;
841 std::size_t len=node_impl_type::black_count(
842 leftmost()->impl(),root()->impl());
843 for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
844 node_type* x=it.get_node();
845 node_type* left_x=node_type::from_impl(x->left());
846 node_type* right_x=node_type::from_impl(x->right());
848 if(x->color()==red){
849 if((left_x&&left_x->color()==red)||
850 (right_x&&right_x->color()==red))return false;
852 if(left_x&&comp(key(x->value()),key(left_x->value())))return false;
853 if(right_x&&comp(key(right_x->value()),key(x->value())))return false;
854 if(!left_x&&!right_x&&
855 node_impl_type::black_count(x->impl(),root()->impl())!=len)
856 return false;
859 if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
860 return false;
861 if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
862 return false;
865 return super::invariant_();
869 /* This forwarding function eases things for the boost::mem_fn construct
870 * in BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT. Actually,
871 * final_check_invariant is already an inherited member function of
872 * ordered_index.
874 void check_invariant_()const{this->final_check_invariant_();}
875 #endif
877 private:
878 node_type* header()const{return this->final_header();}
879 node_type* root()const{return node_type::from_impl(header()->parent());}
880 node_type* leftmost()const{return node_type::from_impl(header()->left());}
881 node_type* rightmost()const{return node_type::from_impl(header()->right());}
883 void empty_initialize()
885 header()->color()=red;
886 /* used to distinguish header() from root, in iterator.operator++ */
888 header()->parent()=node_impl_pointer(0);
889 header()->left()=header()->impl();
890 header()->right()=header()->impl();
893 struct link_info
895 link_info():side(to_left){}
897 ordered_index_side side;
898 node_impl_pointer pos;
901 bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
903 node_type* y=header();
904 node_type* x=root();
905 bool c=true;
906 while(x){
907 y=x;
908 c=comp(k,key(x->value()));
909 x=node_type::from_impl(c?x->left():x->right());
911 node_type* yy=y;
912 if(c){
913 if(yy==leftmost()){
914 inf.side=to_left;
915 inf.pos=y->impl();
916 return true;
918 else node_type::decrement(yy);
921 if(comp(key(yy->value()),k)){
922 inf.side=c?to_left:to_right;
923 inf.pos=y->impl();
924 return true;
926 else{
927 inf.pos=yy->impl();
928 return false;
932 bool link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
934 node_type* y=header();
935 node_type* x=root();
936 bool c=true;
937 while (x){
938 y=x;
939 c=comp(k,key(x->value()));
940 x=node_type::from_impl(c?x->left():x->right());
942 inf.side=c?to_left:to_right;
943 inf.pos=y->impl();
944 return true;
947 bool lower_link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
949 node_type* y=header();
950 node_type* x=root();
951 bool c=false;
952 while (x){
953 y=x;
954 c=comp(key(x->value()),k);
955 x=node_type::from_impl(c?x->right():x->left());
957 inf.side=c?to_right:to_left;
958 inf.pos=y->impl();
959 return true;
962 bool hinted_link_point(
963 key_param_type k,node_type* position,link_info& inf,ordered_unique_tag)
965 if(position->impl()==header()->left()){
966 if(size()>0&&comp(k,key(position->value()))){
967 inf.side=to_left;
968 inf.pos=position->impl();
969 return true;
971 else return link_point(k,inf,ordered_unique_tag());
973 else if(position==header()){
974 if(comp(key(rightmost()->value()),k)){
975 inf.side=to_right;
976 inf.pos=rightmost()->impl();
977 return true;
979 else return link_point(k,inf,ordered_unique_tag());
981 else{
982 node_type* before=position;
983 node_type::decrement(before);
984 if(comp(key(before->value()),k)&&comp(k,key(position->value()))){
985 if(before->right()==node_impl_pointer(0)){
986 inf.side=to_right;
987 inf.pos=before->impl();
988 return true;
990 else{
991 inf.side=to_left;
992 inf.pos=position->impl();
993 return true;
996 else return link_point(k,inf,ordered_unique_tag());
1000 bool hinted_link_point(
1001 key_param_type k,node_type* position,link_info& inf,ordered_non_unique_tag)
1003 if(position->impl()==header()->left()){
1004 if(size()>0&&!comp(key(position->value()),k)){
1005 inf.side=to_left;
1006 inf.pos=position->impl();
1007 return true;
1009 else return lower_link_point(k,inf,ordered_non_unique_tag());
1011 else if(position==header()){
1012 if(!comp(k,key(rightmost()->value()))){
1013 inf.side=to_right;
1014 inf.pos=rightmost()->impl();
1015 return true;
1017 else return link_point(k,inf,ordered_non_unique_tag());
1019 else{
1020 node_type* before=position;
1021 node_type::decrement(before);
1022 if(!comp(k,key(before->value()))){
1023 if(!comp(key(position->value()),k)){
1024 if(before->right()==node_impl_pointer(0)){
1025 inf.side=to_right;
1026 inf.pos=before->impl();
1027 return true;
1029 else{
1030 inf.side=to_left;
1031 inf.pos=position->impl();
1032 return true;
1035 else return lower_link_point(k,inf,ordered_non_unique_tag());
1037 else return link_point(k,inf,ordered_non_unique_tag());
1041 void delete_all_nodes(node_type* x)
1043 if(!x)return;
1045 delete_all_nodes(node_type::from_impl(x->left()));
1046 delete_all_nodes(node_type::from_impl(x->right()));
1047 this->final_delete_node_(static_cast<final_node_type*>(x));
1050 bool in_place(value_param_type v,node_type* x,ordered_unique_tag)
1052 node_type* y;
1053 if(x!=leftmost()){
1054 y=x;
1055 node_type::decrement(y);
1056 if(!comp(key(y->value()),key(v)))return false;
1059 y=x;
1060 node_type::increment(y);
1061 return y==header()||comp(key(v),key(y->value()));
1064 bool in_place(value_param_type v,node_type* x,ordered_non_unique_tag)
1066 node_type* y;
1067 if(x!=leftmost()){
1068 y=x;
1069 node_type::decrement(y);
1070 if(comp(key(v),key(y->value())))return false;
1073 y=x;
1074 node_type::increment(y);
1075 return y==header()||!comp(key(y->value()),key(v));
1078 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
1079 void detach_iterators(node_type* x)
1081 iterator it=make_iterator(x);
1082 safe_mode::detach_equivalent_iterators(it);
1084 #endif
1086 template<typename LowerBounder,typename UpperBounder>
1087 std::pair<iterator,iterator>
1088 range(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
1090 node_type* y=header();
1091 node_type* z=root();
1093 while(z){
1094 if(!lower(key(z->value()))){
1095 z=node_type::from_impl(z->right());
1097 else if(!upper(key(z->value()))){
1098 y=z;
1099 z=node_type::from_impl(z->left());
1101 else{
1102 return std::pair<iterator,iterator>(
1103 make_iterator(
1104 lower_range(node_type::from_impl(z->left()),z,lower)),
1105 make_iterator(
1106 upper_range(node_type::from_impl(z->right()),y,upper)));
1110 return std::pair<iterator,iterator>(make_iterator(y),make_iterator(y));
1113 template<typename LowerBounder,typename UpperBounder>
1114 std::pair<iterator,iterator>
1115 range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
1117 return std::pair<iterator,iterator>(
1118 begin(),
1119 make_iterator(upper_range(root(),header(),upper)));
1122 template<typename LowerBounder,typename UpperBounder>
1123 std::pair<iterator,iterator>
1124 range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
1126 return std::pair<iterator,iterator>(
1127 make_iterator(lower_range(root(),header(),lower)),
1128 end());
1131 template<typename LowerBounder,typename UpperBounder>
1132 std::pair<iterator,iterator>
1133 range(LowerBounder,UpperBounder,both_unbounded_tag)const
1135 return std::pair<iterator,iterator>(begin(),end());
1138 template<typename LowerBounder>
1139 node_type * lower_range(node_type* top,node_type* y,LowerBounder lower)const
1141 while(top){
1142 if(lower(key(top->value()))){
1143 y=top;
1144 top=node_type::from_impl(top->left());
1146 else top=node_type::from_impl(top->right());
1149 return y;
1152 template<typename UpperBounder>
1153 node_type * upper_range(node_type* top,node_type* y,UpperBounder upper)const
1155 while(top){
1156 if(!upper(key(top->value()))){
1157 y=top;
1158 top=node_type::from_impl(top->left());
1160 else top=node_type::from_impl(top->right());
1163 return y;
1166 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1167 template<typename Archive>
1168 void save_(
1169 Archive& ar,const unsigned int version,const index_saver_type& sm,
1170 ordered_unique_tag)const
1172 super::save_(ar,version,sm);
1175 template<typename Archive>
1176 void load_(
1177 Archive& ar,const unsigned int version,const index_loader_type& lm,
1178 ordered_unique_tag)
1180 super::load_(ar,version,lm);
1183 template<typename Archive>
1184 void save_(
1185 Archive& ar,const unsigned int version,const index_saver_type& sm,
1186 ordered_non_unique_tag)const
1188 typedef duplicates_iterator<node_type,value_compare> dup_iterator;
1190 sm.save(
1191 dup_iterator(begin().get_node(),end().get_node(),value_comp()),
1192 dup_iterator(end().get_node(),value_comp()),
1193 ar,version);
1194 super::save_(ar,version,sm);
1197 template<typename Archive>
1198 void load_(
1199 Archive& ar,const unsigned int version,const index_loader_type& lm,
1200 ordered_non_unique_tag)
1202 lm.load(
1203 ::boost::bind(&ordered_index::rearranger,this,_1,_2),
1204 ar,version);
1205 super::load_(ar,version,lm);
1208 void rearranger(node_type* position,node_type *x)
1210 if(!position||comp(key(position->value()),key(x->value()))){
1211 position=lower_bound(key(x->value())).get_node();
1213 else if(comp(key(x->value()),key(position->value()))){
1214 /* inconsistent rearrangement */
1215 throw_exception(
1216 archive::archive_exception(
1217 archive::archive_exception::other_exception));
1219 else node_type::increment(position);
1221 if(position!=x){
1222 node_impl_type::rebalance_for_erase(
1223 x->impl(),header()->parent(),header()->left(),header()->right());
1224 node_impl_type::restore(
1225 x->impl(),position->impl(),header()->impl());
1228 #endif /* serialization */
1230 key_from_value key;
1231 key_compare comp;
1233 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
1234 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
1235 #pragma parse_mfunc_templ reset
1236 #endif
1239 /* comparison */
1241 template<
1242 typename KeyFromValue1,typename Compare1,
1243 typename SuperMeta1,typename TagList1,typename Category1,
1244 typename KeyFromValue2,typename Compare2,
1245 typename SuperMeta2,typename TagList2,typename Category2
1247 bool operator==(
1248 const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
1249 const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
1251 return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
1254 template<
1255 typename KeyFromValue1,typename Compare1,
1256 typename SuperMeta1,typename TagList1,typename Category1,
1257 typename KeyFromValue2,typename Compare2,
1258 typename SuperMeta2,typename TagList2,typename Category2
1260 bool operator<(
1261 const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
1262 const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
1264 return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
1267 template<
1268 typename KeyFromValue1,typename Compare1,
1269 typename SuperMeta1,typename TagList1,typename Category1,
1270 typename KeyFromValue2,typename Compare2,
1271 typename SuperMeta2,typename TagList2,typename Category2
1273 bool operator!=(
1274 const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
1275 const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
1277 return !(x==y);
1280 template<
1281 typename KeyFromValue1,typename Compare1,
1282 typename SuperMeta1,typename TagList1,typename Category1,
1283 typename KeyFromValue2,typename Compare2,
1284 typename SuperMeta2,typename TagList2,typename Category2
1286 bool operator>(
1287 const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
1288 const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
1290 return y<x;
1293 template<
1294 typename KeyFromValue1,typename Compare1,
1295 typename SuperMeta1,typename TagList1,typename Category1,
1296 typename KeyFromValue2,typename Compare2,
1297 typename SuperMeta2,typename TagList2,typename Category2
1299 bool operator>=(
1300 const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
1301 const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
1303 return !(x<y);
1306 template<
1307 typename KeyFromValue1,typename Compare1,
1308 typename SuperMeta1,typename TagList1,typename Category1,
1309 typename KeyFromValue2,typename Compare2,
1310 typename SuperMeta2,typename TagList2,typename Category2
1312 bool operator<=(
1313 const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1>& x,
1314 const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2>& y)
1316 return !(x>y);
1319 /* specialized algorithms */
1321 template<
1322 typename KeyFromValue,typename Compare,
1323 typename SuperMeta,typename TagList,typename Category
1325 void swap(
1326 ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x,
1327 ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& y)
1329 x.swap(y);
1332 } /* namespace multi_index::detail */
1334 /* ordered_index specifiers */
1336 template<typename Arg1,typename Arg2,typename Arg3>
1337 struct ordered_unique
1339 typedef typename detail::ordered_index_args<
1340 Arg1,Arg2,Arg3> index_args;
1341 typedef typename index_args::tag_list_type::type tag_list_type;
1342 typedef typename index_args::key_from_value_type key_from_value_type;
1343 typedef typename index_args::compare_type compare_type;
1345 template<typename Super>
1346 struct node_class
1348 typedef detail::ordered_index_node<Super> type;
1351 template<typename SuperMeta>
1352 struct index_class
1354 typedef detail::ordered_index<
1355 key_from_value_type,compare_type,
1356 SuperMeta,tag_list_type,detail::ordered_unique_tag> type;
1360 template<typename Arg1,typename Arg2,typename Arg3>
1361 struct ordered_non_unique
1363 typedef detail::ordered_index_args<
1364 Arg1,Arg2,Arg3> index_args;
1365 typedef typename index_args::tag_list_type::type tag_list_type;
1366 typedef typename index_args::key_from_value_type key_from_value_type;
1367 typedef typename index_args::compare_type compare_type;
1369 template<typename Super>
1370 struct node_class
1372 typedef detail::ordered_index_node<Super> type;
1375 template<typename SuperMeta>
1376 struct index_class
1378 typedef detail::ordered_index<
1379 key_from_value_type,compare_type,
1380 SuperMeta,tag_list_type,detail::ordered_non_unique_tag> type;
1384 } /* namespace multi_index */
1386 } /* namespace boost */
1388 #undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
1390 #endif