1 /* Copyright 2003-2020 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 
36 #ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_IMPL_HPP
37 #define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_IMPL_HPP
38 
39 #if defined(_MSC_VER)
40 #pragma once
41 #endif
42 
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/core/addressof.hpp>
47 #include <boost/core/no_exceptions_support.hpp>
48 #include <boost/detail/workaround.hpp>
49 #include <boost/foreach_fwd.hpp>
50 #include <boost/iterator/reverse_iterator.hpp>
51 #include <boost/move/core.hpp>
52 #include <boost/move/utility_core.hpp>
53 #include <boost/mpl/bool.hpp>
54 #include <boost/mpl/if.hpp>
55 #include <boost/mpl/push_front.hpp>
56 #include <boost/multi_index/detail/access_specifier.hpp>
57 #include <boost/multi_index/detail/adl_swap.hpp>
58 #include <boost/multi_index/detail/allocator_traits.hpp>
59 #include <boost/multi_index/detail/bidir_node_iterator.hpp>
60 #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
61 #include <boost/multi_index/detail/index_node_base.hpp>
62 #include <boost/multi_index/detail/modify_key_adaptor.hpp>
63 #include <boost/multi_index/detail/node_handle.hpp>
64 #include <boost/multi_index/detail/ord_index_node.hpp>
65 #include <boost/multi_index/detail/ord_index_ops.hpp>
66 #include <boost/multi_index/detail/safe_mode.hpp>
67 #include <boost/multi_index/detail/scope_guard.hpp>
68 #include <boost/multi_index/detail/unbounded.hpp>
69 #include <boost/multi_index/detail/value_compare.hpp>
70 #include <boost/multi_index/detail/vartempl_support.hpp>
71 #include <boost/multi_index/detail/ord_index_impl_fwd.hpp>
72 #include <boost/ref.hpp>
73 #include <boost/tuple/tuple.hpp>
74 #include <boost/type_traits/is_same.hpp>
75 #include <utility>
76 
77 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
78 #include <initializer_list>
79 #endif
80 
81 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
82 #include <boost/archive/archive_exception.hpp>
83 #include <boost/bind/bind.hpp>
84 #include <boost/multi_index/detail/duplicates_iterator.hpp>
85 #include <boost/throw_exception.hpp>
86 #endif
87 
88 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
89 #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x)                    \
90   detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
91     detail::make_obj_guard(x,&ordered_index_impl::check_invariant_);         \
92   BOOST_JOIN(check_invariant_,__LINE__).touch();
93 #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT                          \
94   BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(*this)
95 #else
96 #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x)
97 #define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
98 #endif
99 
100 namespace boost{
101 
102 namespace multi_index{
103 
104 namespace detail{
105 
106 /* ordered_index adds a layer of ordered indexing to a given Super and accepts
107  * an augmenting policy for optional addition of order statistics.
108  */
109 
110 /* Most of the implementation of unique and non-unique indices is
111  * shared. We tell from one another on instantiation time by using
112  * these tags.
113  */
114 
115 struct ordered_unique_tag{};
116 struct ordered_non_unique_tag{};
117 
118 template<
119   typename KeyFromValue,typename Compare,
120   typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
121 >
122 class ordered_index;
123 
124 template<
125   typename KeyFromValue,typename Compare,
126   typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
127 >
128 class ordered_index_impl:
129   BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
130 
131 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
132   ,public safe_mode::safe_container<
133     ordered_index_impl<
134       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> >
135 #endif
136 
137 {
138 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
139     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
140 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
141  * lifetime of const references bound to temporaries --precisely what
142  * scopeguards are.
143  */
144 
145 #pragma parse_mfunc_templ off
146 #endif
147 
148   typedef typename SuperMeta::type                   super;
149 
150 protected:
151   typedef ordered_index_node<
152     AugmentPolicy,typename super::index_node_type>   index_node_type;
153 
154 protected: /* for the benefit of AugmentPolicy::augmented_interface */
155   typedef typename index_node_type::impl_type        node_impl_type;
156   typedef typename node_impl_type::pointer           node_impl_pointer;
157 
158 public:
159   /* types */
160 
161   typedef typename KeyFromValue::result_type         key_type;
162   typedef typename index_node_type::value_type       value_type;
163   typedef KeyFromValue                               key_from_value;
164   typedef Compare                                    key_compare;
165   typedef value_comparison<
166     value_type,KeyFromValue,Compare>                 value_compare;
167   typedef tuple<key_from_value,key_compare>          ctor_args;
168   typedef typename super::final_allocator_type       allocator_type;
169   typedef value_type&                                reference;
170   typedef const value_type&                          const_reference;
171 
172 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
173   typedef safe_mode::safe_iterator<
174     bidir_node_iterator<index_node_type>,
175     ordered_index_impl>                              iterator;
176 #else
177   typedef bidir_node_iterator<index_node_type>       iterator;
178 #endif
179 
180   typedef iterator                                   const_iterator;
181 
182 private:
183   typedef allocator_traits<allocator_type>           alloc_traits;
184 
185 public:
186   typedef typename alloc_traits::size_type           size_type;
187   typedef typename alloc_traits::difference_type     difference_type;
188   typedef typename alloc_traits::pointer             pointer;
189   typedef typename alloc_traits::const_pointer       const_pointer;
190   typedef typename
191     boost::reverse_iterator<iterator>                reverse_iterator;
192   typedef typename
193     boost::reverse_iterator<const_iterator>          const_reverse_iterator;
194   typedef typename super::final_node_handle_type     node_type;
195   typedef detail::insert_return_type<
196     iterator,node_type>                              insert_return_type;
197   typedef TagList                                    tag_list;
198 
199 protected:
200   typedef typename super::final_node_type            final_node_type;
201   typedef tuples::cons<
202     ctor_args,
203     typename super::ctor_args_list>                  ctor_args_list;
204   typedef typename mpl::push_front<
205     typename super::index_type_list,
206     ordered_index<
207       KeyFromValue,Compare,
208       SuperMeta,TagList,Category,AugmentPolicy
209     > >::type                                        index_type_list;
210   typedef typename mpl::push_front<
211     typename super::iterator_type_list,
212     iterator>::type    iterator_type_list;
213   typedef typename mpl::push_front<
214     typename super::const_iterator_type_list,
215     const_iterator>::type                            const_iterator_type_list;
216   typedef typename super::copy_map_type              copy_map_type;
217 
218 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
219   typedef typename super::index_saver_type           index_saver_type;
220   typedef typename super::index_loader_type          index_loader_type;
221 #endif
222 
223 protected:
224 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
225   typedef safe_mode::safe_container<
226     ordered_index_impl>                              safe_super;
227 #endif
228 
229   typedef typename call_traits<
230     value_type>::param_type                          value_param_type;
231   typedef typename call_traits<
232     key_type>::param_type                            key_param_type;
233 
234   /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
235    * expansion.
236    */
237 
238   typedef std::pair<iterator,bool>                   emplace_return_type;
239 
240 public:
241 
242   /* construct/copy/destroy
243    * Default and copy ctors are in the protected section as indices are
244    * not supposed to be created on their own. No range ctor either.
245    * Assignment operators defined at ordered_index rather than here.
246    */
247 
get_allocator() const248   allocator_type get_allocator()const BOOST_NOEXCEPT
249   {
250     return this->final().get_allocator();
251   }
252 
253   /* iterators */
254 
255   iterator
begin()256     begin()BOOST_NOEXCEPT{return make_iterator(leftmost());}
257   const_iterator
begin() const258     begin()const BOOST_NOEXCEPT{return make_iterator(leftmost());}
259   iterator
end()260     end()BOOST_NOEXCEPT{return make_iterator(header());}
261   const_iterator
end() const262     end()const BOOST_NOEXCEPT{return make_iterator(header());}
263   reverse_iterator
rbegin()264     rbegin()BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
265   const_reverse_iterator
rbegin() const266     rbegin()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
267   reverse_iterator
rend()268     rend()BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
269   const_reverse_iterator
rend() const270     rend()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
271   const_iterator
cbegin() const272     cbegin()const BOOST_NOEXCEPT{return begin();}
273   const_iterator
cend() const274     cend()const BOOST_NOEXCEPT{return end();}
275   const_reverse_iterator
crbegin() const276     crbegin()const BOOST_NOEXCEPT{return rbegin();}
277   const_reverse_iterator
crend() const278     crend()const BOOST_NOEXCEPT{return rend();}
279 
iterator_to(const value_type & x)280   iterator iterator_to(const value_type& x)
281   {
282     return make_iterator(
283       node_from_value<index_node_type>(boost::addressof(x)));
284   }
285 
iterator_to(const value_type & x) const286   const_iterator iterator_to(const value_type& x)const
287   {
288     return make_iterator(
289       node_from_value<index_node_type>(boost::addressof(x)));
290   }
291 
292   /* capacity */
293 
empty() const294   bool      empty()const BOOST_NOEXCEPT{return this->final_empty_();}
size() const295   size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
max_size() const296   size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
297 
298   /* modifiers */
299 
BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(emplace_return_type,emplace,emplace_impl)300   BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
301     emplace_return_type,emplace,emplace_impl)
302 
303   BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
304     iterator,emplace_hint,emplace_hint_impl,iterator,position)
305 
306   std::pair<iterator,bool> insert(const value_type& x)
307   {
308     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
309     std::pair<final_node_type*,bool> p=this->final_insert_(x);
310     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
311   }
312 
insert(BOOST_RV_REF (value_type)x)313   std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
314   {
315     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
316     std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
317     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
318   }
319 
insert(iterator position,const value_type & x)320   iterator insert(iterator position,const value_type& x)
321   {
322     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
323     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
324     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
325     std::pair<final_node_type*,bool> p=this->final_insert_(
326       x,static_cast<final_node_type*>(position.get_node()));
327     return make_iterator(p.first);
328   }
329 
insert(iterator position,BOOST_RV_REF (value_type)x)330   iterator insert(iterator position,BOOST_RV_REF(value_type) x)
331   {
332     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
333     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
334     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
335     std::pair<final_node_type*,bool> p=this->final_insert_rv_(
336       x,static_cast<final_node_type*>(position.get_node()));
337     return make_iterator(p.first);
338   }
339 
340   template<typename InputIterator>
insert(InputIterator first,InputIterator last)341   void insert(InputIterator first,InputIterator last)
342   {
343     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
344     index_node_type* hint=header(); /* end() */
345     for(;first!=last;++first){
346       hint=this->final_insert_ref_(
347         *first,static_cast<final_node_type*>(hint)).first;
348       index_node_type::increment(hint);
349     }
350   }
351 
352 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
insert(std::initializer_list<value_type> list)353   void insert(std::initializer_list<value_type> list)
354   {
355     insert(list.begin(),list.end());
356   }
357 #endif
358 
insert(BOOST_RV_REF (node_type)nh)359   insert_return_type insert(BOOST_RV_REF(node_type) nh)
360   {
361     if(nh)BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,nh);
362     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
363     std::pair<final_node_type*,bool> p=this->final_insert_nh_(nh);
364     return insert_return_type(make_iterator(p.first),p.second,boost::move(nh));
365   }
366 
insert(const_iterator position,BOOST_RV_REF (node_type)nh)367   iterator insert(const_iterator position,BOOST_RV_REF(node_type) nh)
368   {
369     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
370     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
371     if(nh)BOOST_MULTI_INDEX_CHECK_EQUAL_ALLOCATORS(*this,nh);
372     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
373     std::pair<final_node_type*,bool> p=this->final_insert_nh_(
374       nh,static_cast<final_node_type*>(position.get_node()));
375     return make_iterator(p.first);
376   }
377 
extract(const_iterator position)378   node_type extract(const_iterator position)
379   {
380     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
381     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
382     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
383     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
384     return this->final_extract_(
385       static_cast<final_node_type*>(position.get_node()));
386   }
387 
extract(key_param_type x)388   node_type extract(key_param_type x)
389   {
390     iterator position=lower_bound(x);
391     if(position==end()||comp_(x,key(*position)))return node_type();
392     else return extract(position);
393   }
394 
erase(iterator position)395   iterator erase(iterator position)
396   {
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     this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
402     return position;
403   }
404 
erase(key_param_type x)405   size_type erase(key_param_type x)
406   {
407     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
408     std::pair<iterator,iterator> p=equal_range(x);
409     size_type s=0;
410     while(p.first!=p.second){
411       p.first=erase(p.first);
412       ++s;
413     }
414     return s;
415   }
416 
erase(iterator first,iterator last)417   iterator erase(iterator first,iterator last)
418   {
419     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
420     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
421     BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
422     BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
423     BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
424     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
425     while(first!=last){
426       first=erase(first);
427     }
428     return first;
429   }
430 
replace(iterator position,const value_type & x)431   bool replace(iterator position,const value_type& x)
432   {
433     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
434     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
435     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
436     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
437     return this->final_replace_(
438       x,static_cast<final_node_type*>(position.get_node()));
439   }
440 
replace(iterator position,BOOST_RV_REF (value_type)x)441   bool replace(iterator position,BOOST_RV_REF(value_type) x)
442   {
443     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
444     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
445     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
446     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
447     return this->final_replace_rv_(
448       x,static_cast<final_node_type*>(position.get_node()));
449   }
450 
451   template<typename Modifier>
modify(iterator position,Modifier mod)452   bool modify(iterator position,Modifier mod)
453   {
454     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
455     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
456     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
457     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
458 
459 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
460     /* MSVC++ 6.0 optimizer on safe mode code chokes if this
461      * this is not added. Left it for all compilers as it does no
462      * harm.
463      */
464 
465     position.detach();
466 #endif
467 
468     return this->final_modify_(
469       mod,static_cast<final_node_type*>(position.get_node()));
470   }
471 
472   template<typename Modifier,typename Rollback>
modify(iterator position,Modifier mod,Rollback back_)473   bool modify(iterator position,Modifier mod,Rollback back_)
474   {
475     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
476     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
477     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
478     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
479 
480 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
481     /* MSVC++ 6.0 optimizer on safe mode code chokes if this
482      * this is not added. Left it for all compilers as it does no
483      * harm.
484      */
485 
486     position.detach();
487 #endif
488 
489     return this->final_modify_(
490       mod,back_,static_cast<final_node_type*>(position.get_node()));
491   }
492 
493   template<typename Modifier>
modify_key(iterator position,Modifier mod)494   bool modify_key(iterator position,Modifier mod)
495   {
496     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
497     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
498     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
499     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
500     return modify(
501       position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
502   }
503 
504   template<typename Modifier,typename Rollback>
modify_key(iterator position,Modifier mod,Rollback back_)505   bool modify_key(iterator position,Modifier mod,Rollback back_)
506   {
507     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
508     BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
509     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
510     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
511     return modify(
512       position,
513       modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
514       modify_key_adaptor<Rollback,value_type,KeyFromValue>(back_,key));
515   }
516 
swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x)517   void swap(
518     ordered_index<
519       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x)
520   {
521     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
522     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x);
523     this->final_swap_(x.final());
524   }
525 
clear()526   void clear()BOOST_NOEXCEPT
527   {
528     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
529     this->final_clear_();
530   }
531 
532   /* observers */
533 
key_extractor() const534   key_from_value key_extractor()const{return key;}
key_comp() const535   key_compare    key_comp()const{return comp_;}
value_comp() const536   value_compare  value_comp()const{return value_compare(key,comp_);}
537 
538   /* set operations */
539 
540   /* Internally, these ops rely on const_iterator being the same
541    * type as iterator.
542    */
543 
544   template<typename CompatibleKey>
find(const CompatibleKey & x) const545   iterator find(const CompatibleKey& x)const
546   {
547     return make_iterator(ordered_index_find(root(),header(),key,x,comp_));
548   }
549 
550   template<typename CompatibleKey,typename CompatibleCompare>
find(const CompatibleKey & x,const CompatibleCompare & comp) const551   iterator find(
552     const CompatibleKey& x,const CompatibleCompare& comp)const
553   {
554     return make_iterator(ordered_index_find(root(),header(),key,x,comp));
555   }
556 
557   template<typename CompatibleKey>
count(const CompatibleKey & x) const558   size_type count(const CompatibleKey& x)const
559   {
560     return count(x,comp_);
561   }
562 
563   template<typename CompatibleKey,typename CompatibleCompare>
count(const CompatibleKey & x,const CompatibleCompare & comp) const564   size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
565   {
566     std::pair<iterator,iterator> p=equal_range(x,comp);
567     size_type n=static_cast<size_type>(std::distance(p.first,p.second));
568     return n;
569   }
570 
571   template<typename CompatibleKey>
lower_bound(const CompatibleKey & x) const572   iterator lower_bound(const CompatibleKey& x)const
573   {
574     return make_iterator(
575       ordered_index_lower_bound(root(),header(),key,x,comp_));
576   }
577 
578   template<typename CompatibleKey,typename CompatibleCompare>
lower_bound(const CompatibleKey & x,const CompatibleCompare & comp) const579   iterator lower_bound(
580     const CompatibleKey& x,const CompatibleCompare& comp)const
581   {
582     return make_iterator(
583       ordered_index_lower_bound(root(),header(),key,x,comp));
584   }
585 
586   template<typename CompatibleKey>
upper_bound(const CompatibleKey & x) const587   iterator upper_bound(const CompatibleKey& x)const
588   {
589     return make_iterator(
590       ordered_index_upper_bound(root(),header(),key,x,comp_));
591   }
592 
593   template<typename CompatibleKey,typename CompatibleCompare>
upper_bound(const CompatibleKey & x,const CompatibleCompare & comp) const594   iterator upper_bound(
595     const CompatibleKey& x,const CompatibleCompare& comp)const
596   {
597     return make_iterator(
598       ordered_index_upper_bound(root(),header(),key,x,comp));
599   }
600 
601   template<typename CompatibleKey>
equal_range(const CompatibleKey & x) const602   std::pair<iterator,iterator> equal_range(
603     const CompatibleKey& x)const
604   {
605     std::pair<index_node_type*,index_node_type*> p=
606       ordered_index_equal_range(root(),header(),key,x,comp_);
607     return std::pair<iterator,iterator>(
608       make_iterator(p.first),make_iterator(p.second));
609   }
610 
611   template<typename CompatibleKey,typename CompatibleCompare>
equal_range(const CompatibleKey & x,const CompatibleCompare & comp) const612   std::pair<iterator,iterator> equal_range(
613     const CompatibleKey& x,const CompatibleCompare& comp)const
614   {
615     std::pair<index_node_type*,index_node_type*> p=
616       ordered_index_equal_range(root(),header(),key,x,comp);
617     return std::pair<iterator,iterator>(
618       make_iterator(p.first),make_iterator(p.second));
619   }
620 
621   /* range */
622 
623   template<typename LowerBounder,typename UpperBounder>
624   std::pair<iterator,iterator>
range(LowerBounder lower,UpperBounder upper) const625   range(LowerBounder lower,UpperBounder upper)const
626   {
627     typedef typename mpl::if_<
628       is_same<LowerBounder,unbounded_type>,
629       BOOST_DEDUCED_TYPENAME mpl::if_<
630         is_same<UpperBounder,unbounded_type>,
631         both_unbounded_tag,
632         lower_unbounded_tag
633       >::type,
634       BOOST_DEDUCED_TYPENAME mpl::if_<
635         is_same<UpperBounder,unbounded_type>,
636         upper_unbounded_tag,
637         none_unbounded_tag
638       >::type
639     >::type dispatch;
640 
641     return range(lower,upper,dispatch());
642   }
643 
644 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
645   ordered_index_impl(const ctor_args_list& args_list,const allocator_type& al):
646     super(args_list.get_tail(),al),
647     key(tuples::get<0>(args_list.get_head())),
648     comp_(tuples::get<1>(args_list.get_head()))
649   {
650     empty_initialize();
651   }
652 
ordered_index_impl(const ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x)653   ordered_index_impl(
654     const ordered_index_impl<
655       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x):
656     super(x),
657 
658 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
659     safe_super(),
660 #endif
661 
662     key(x.key),
663     comp_(x.comp_)
664   {
665     /* Copy ctor just takes the key and compare objects from x. The rest is
666      * done in a subsequent call to copy_().
667      */
668   }
669 
ordered_index_impl(const ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x,do_not_copy_elements_tag)670   ordered_index_impl(
671      const ordered_index_impl<
672        KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
673      do_not_copy_elements_tag):
674     super(x,do_not_copy_elements_tag()),
675 
676 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
677     safe_super(),
678 #endif
679 
680     key(x.key),
681     comp_(x.comp_)
682   {
683     empty_initialize();
684   }
685 
~ordered_index_impl()686   ~ordered_index_impl()
687   {
688     /* the container is guaranteed to be empty by now */
689   }
690 
691 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
make_iterator(index_node_type * node)692   iterator       make_iterator(index_node_type* node)
693     {return iterator(node,this);}
make_iterator(index_node_type * node) const694   const_iterator make_iterator(index_node_type* node)const
695     {return const_iterator(node,const_cast<ordered_index_impl*>(this));}
696 #else
make_iterator(index_node_type * node)697   iterator       make_iterator(index_node_type* node){return iterator(node);}
make_iterator(index_node_type * node) const698   const_iterator make_iterator(index_node_type* node)const
699                    {return const_iterator(node);}
700 #endif
701 
copy_(const ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x,const copy_map_type & map)702   void copy_(
703     const ordered_index_impl<
704       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
705     const copy_map_type& map)
706   {
707     if(!x.root()){
708       empty_initialize();
709     }
710     else{
711       header()->color()=x.header()->color();
712       AugmentPolicy::copy(x.header()->impl(),header()->impl());
713 
714       index_node_type* root_cpy=map.find(
715         static_cast<final_node_type*>(x.root()));
716       header()->parent()=root_cpy->impl();
717 
718       index_node_type* leftmost_cpy=map.find(
719         static_cast<final_node_type*>(x.leftmost()));
720       header()->left()=leftmost_cpy->impl();
721 
722       index_node_type* rightmost_cpy=map.find(
723         static_cast<final_node_type*>(x.rightmost()));
724       header()->right()=rightmost_cpy->impl();
725 
726       typedef typename copy_map_type::const_iterator copy_map_iterator;
727       for(copy_map_iterator it=map.begin(),it_end=map.end();it!=it_end;++it){
728         index_node_type* org=it->first;
729         index_node_type* cpy=it->second;
730 
731         cpy->color()=org->color();
732         AugmentPolicy::copy(org->impl(),cpy->impl());
733 
734         node_impl_pointer parent_org=org->parent();
735         if(parent_org==node_impl_pointer(0))cpy->parent()=node_impl_pointer(0);
736         else{
737           index_node_type* parent_cpy=map.find(
738             static_cast<final_node_type*>(
739               index_node_type::from_impl(parent_org)));
740           cpy->parent()=parent_cpy->impl();
741           if(parent_org->left()==org->impl()){
742             parent_cpy->left()=cpy->impl();
743           }
744           else if(parent_org->right()==org->impl()){
745             /* header() does not satisfy this nor the previous check */
746             parent_cpy->right()=cpy->impl();
747           }
748         }
749 
750         if(org->left()==node_impl_pointer(0))
751           cpy->left()=node_impl_pointer(0);
752         if(org->right()==node_impl_pointer(0))
753           cpy->right()=node_impl_pointer(0);
754       }
755     }
756 
757     super::copy_(x,map);
758   }
759 
760   template<typename Variant>
insert_(value_param_type v,final_node_type * & x,Variant variant)761   final_node_type* insert_(
762     value_param_type v,final_node_type*& x,Variant variant)
763   {
764     link_info inf;
765     if(!link_point(key(v),inf,Category())){
766       return static_cast<final_node_type*>(
767         index_node_type::from_impl(inf.pos));
768     }
769 
770     final_node_type* res=super::insert_(v,x,variant);
771     if(res==x){
772       node_impl_type::link(
773         static_cast<index_node_type*>(x)->impl(),
774         inf.side,inf.pos,header()->impl());
775     }
776     return res;
777   }
778 
779   template<typename Variant>
insert_(value_param_type v,index_node_type * position,final_node_type * & x,Variant variant)780   final_node_type* insert_(
781     value_param_type v,index_node_type* position,
782     final_node_type*& x,Variant variant)
783   {
784     link_info inf;
785     if(!hinted_link_point(key(v),position,inf,Category())){
786       return static_cast<final_node_type*>(
787         index_node_type::from_impl(inf.pos));
788     }
789 
790     final_node_type* res=super::insert_(v,position,x,variant);
791     if(res==x){
792       node_impl_type::link(
793         static_cast<index_node_type*>(x)->impl(),
794         inf.side,inf.pos,header()->impl());
795     }
796     return res;
797   }
798 
extract_(index_node_type * x)799   void extract_(index_node_type* x)
800   {
801     node_impl_type::rebalance_for_extract(
802       x->impl(),header()->parent(),header()->left(),header()->right());
803     super::extract_(x);
804 
805 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
806     detach_iterators(x);
807 #endif
808   }
809 
delete_all_nodes_()810   void delete_all_nodes_()
811   {
812     delete_all_nodes(root());
813   }
814 
clear_()815   void clear_()
816   {
817     super::clear_();
818     empty_initialize();
819 
820 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
821     safe_super::detach_dereferenceable_iterators();
822 #endif
823   }
824 
825   template<typename BoolConstant>
swap_(ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x,BoolConstant swap_allocators)826   void swap_(
827     ordered_index_impl<
828       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
829     BoolConstant swap_allocators)
830   {
831     adl_swap(key,x.key);
832     adl_swap(comp_,x.comp_);
833 
834 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
835     safe_super::swap(x);
836 #endif
837 
838     super::swap_(x,swap_allocators);
839   }
840 
swap_elements_(ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x)841   void swap_elements_(
842     ordered_index_impl<
843       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x)
844   {
845 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
846     safe_super::swap(x);
847 #endif
848 
849     super::swap_elements_(x);
850   }
851 
852   template<typename Variant>
replace_(value_param_type v,index_node_type * x,Variant variant)853   bool replace_(value_param_type v,index_node_type* x,Variant variant)
854   {
855     if(in_place(v,x,Category())){
856       return super::replace_(v,x,variant);
857     }
858 
859     index_node_type* next=x;
860     index_node_type::increment(next);
861 
862     node_impl_type::rebalance_for_extract(
863       x->impl(),header()->parent(),header()->left(),header()->right());
864 
865     BOOST_TRY{
866       link_info inf;
867       if(link_point(key(v),inf,Category())&&super::replace_(v,x,variant)){
868         node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
869         return true;
870       }
871       node_impl_type::restore(x->impl(),next->impl(),header()->impl());
872       return false;
873     }
874     BOOST_CATCH(...){
875       node_impl_type::restore(x->impl(),next->impl(),header()->impl());
876       BOOST_RETHROW;
877     }
878     BOOST_CATCH_END
879   }
880 
modify_(index_node_type * x)881   bool modify_(index_node_type* x)
882   {
883     bool b;
884     BOOST_TRY{
885       b=in_place(x->value(),x,Category());
886     }
887     BOOST_CATCH(...){
888       extract_(x);
889       BOOST_RETHROW;
890     }
891     BOOST_CATCH_END
892     if(!b){
893       node_impl_type::rebalance_for_extract(
894         x->impl(),header()->parent(),header()->left(),header()->right());
895       BOOST_TRY{
896         link_info inf;
897         if(!link_point(key(x->value()),inf,Category())){
898           super::extract_(x);
899 
900 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
901           detach_iterators(x);
902 #endif
903           return false;
904         }
905         node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
906       }
907       BOOST_CATCH(...){
908         super::extract_(x);
909 
910 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
911         detach_iterators(x);
912 #endif
913 
914         BOOST_RETHROW;
915       }
916       BOOST_CATCH_END
917     }
918 
919     BOOST_TRY{
920       if(!super::modify_(x)){
921         node_impl_type::rebalance_for_extract(
922           x->impl(),header()->parent(),header()->left(),header()->right());
923 
924 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
925         detach_iterators(x);
926 #endif
927 
928         return false;
929       }
930       else return true;
931     }
932     BOOST_CATCH(...){
933       node_impl_type::rebalance_for_extract(
934         x->impl(),header()->parent(),header()->left(),header()->right());
935 
936 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
937       detach_iterators(x);
938 #endif
939 
940       BOOST_RETHROW;
941     }
942     BOOST_CATCH_END
943   }
944 
modify_rollback_(index_node_type * x)945   bool modify_rollback_(index_node_type* x)
946   {
947     if(in_place(x->value(),x,Category())){
948       return super::modify_rollback_(x);
949     }
950 
951     index_node_type* next=x;
952     index_node_type::increment(next);
953 
954     node_impl_type::rebalance_for_extract(
955       x->impl(),header()->parent(),header()->left(),header()->right());
956 
957     BOOST_TRY{
958       link_info inf;
959       if(link_point(key(x->value()),inf,Category())&&
960          super::modify_rollback_(x)){
961         node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
962         return true;
963       }
964       node_impl_type::restore(x->impl(),next->impl(),header()->impl());
965       return false;
966     }
967     BOOST_CATCH(...){
968       node_impl_type::restore(x->impl(),next->impl(),header()->impl());
969       BOOST_RETHROW;
970     }
971     BOOST_CATCH_END
972   }
973 
check_rollback_(index_node_type * x) const974   bool check_rollback_(index_node_type* x)const
975   {
976     return in_place(x->value(),x,Category())&&super::check_rollback_(x);
977   }
978 
979 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
980   /* serialization */
981 
982   template<typename Archive>
save_(Archive & ar,const unsigned int version,const index_saver_type & sm) const983   void save_(
984     Archive& ar,const unsigned int version,const index_saver_type& sm)const
985   {
986     save_(ar,version,sm,Category());
987   }
988 
989   template<typename Archive>
load_(Archive & ar,const unsigned int version,const index_loader_type & lm)990   void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
991   {
992     load_(ar,version,lm,Category());
993   }
994 #endif
995 
996 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
997   /* invariant stuff */
998 
invariant_() const999   bool invariant_()const
1000   {
1001     if(size()==0||begin()==end()){
1002       if(size()!=0||begin()!=end()||
1003          header()->left()!=header()->impl()||
1004          header()->right()!=header()->impl())return false;
1005     }
1006     else{
1007       if((size_type)std::distance(begin(),end())!=size())return false;
1008 
1009       std::size_t len=node_impl_type::black_count(
1010         leftmost()->impl(),root()->impl());
1011       for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
1012         index_node_type* x=it.get_node();
1013         index_node_type* left_x=index_node_type::from_impl(x->left());
1014         index_node_type* right_x=index_node_type::from_impl(x->right());
1015 
1016         if(x->color()==red){
1017           if((left_x&&left_x->color()==red)||
1018              (right_x&&right_x->color()==red))return false;
1019         }
1020         if(left_x&&comp_(key(x->value()),key(left_x->value())))return false;
1021         if(right_x&&comp_(key(right_x->value()),key(x->value())))return false;
1022         if(!left_x&&!right_x&&
1023            node_impl_type::black_count(x->impl(),root()->impl())!=len)
1024           return false;
1025         if(!AugmentPolicy::invariant(x->impl()))return false;
1026       }
1027 
1028       if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
1029         return false;
1030       if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
1031         return false;
1032     }
1033 
1034     return super::invariant_();
1035   }
1036 
1037 
1038   /* This forwarding function eases things for the boost::mem_fn construct
1039    * in BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT. Actually,
1040    * final_check_invariant is already an inherited member function of
1041    * ordered_index_impl.
1042    */
check_invariant_() const1043   void check_invariant_()const{this->final_check_invariant_();}
1044 #endif
1045 
1046 protected: /* for the benefit of AugmentPolicy::augmented_interface */
header() const1047   index_node_type* header()const
1048     {return this->final_header();}
root() const1049   index_node_type* root()const
1050     {return index_node_type::from_impl(header()->parent());}
leftmost() const1051   index_node_type* leftmost()const
1052     {return index_node_type::from_impl(header()->left());}
rightmost() const1053   index_node_type* rightmost()const
1054     {return index_node_type::from_impl(header()->right());}
1055 
1056 private:
empty_initialize()1057   void empty_initialize()
1058   {
1059     header()->color()=red;
1060     /* used to distinguish header() from root, in iterator.operator++ */
1061 
1062     header()->parent()=node_impl_pointer(0);
1063     header()->left()=header()->impl();
1064     header()->right()=header()->impl();
1065   }
1066 
1067   struct link_info
1068   {
1069     /* coverity[uninit_ctor]: suppress warning */
link_infoboost::multi_index::detail::ordered_index_impl::link_info1070     link_info():side(to_left){}
1071 
1072     ordered_index_side side;
1073     node_impl_pointer  pos;
1074   };
1075 
link_point(key_param_type k,link_info & inf,ordered_unique_tag)1076   bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
1077   {
1078     index_node_type* y=header();
1079     index_node_type* x=root();
1080     bool c=true;
1081     while(x){
1082       y=x;
1083       c=comp_(k,key(x->value()));
1084       x=index_node_type::from_impl(c?x->left():x->right());
1085     }
1086     index_node_type* yy=y;
1087     if(c){
1088       if(yy==leftmost()){
1089         inf.side=to_left;
1090         inf.pos=y->impl();
1091         return true;
1092       }
1093       else index_node_type::decrement(yy);
1094     }
1095 
1096     if(comp_(key(yy->value()),k)){
1097       inf.side=c?to_left:to_right;
1098       inf.pos=y->impl();
1099       return true;
1100     }
1101     else{
1102       inf.pos=yy->impl();
1103       return false;
1104     }
1105   }
1106 
link_point(key_param_type k,link_info & inf,ordered_non_unique_tag)1107   bool link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
1108   {
1109     index_node_type* y=header();
1110     index_node_type* x=root();
1111     bool c=true;
1112     while (x){
1113      y=x;
1114      c=comp_(k,key(x->value()));
1115      x=index_node_type::from_impl(c?x->left():x->right());
1116     }
1117     inf.side=c?to_left:to_right;
1118     inf.pos=y->impl();
1119     return true;
1120   }
1121 
lower_link_point(key_param_type k,link_info & inf,ordered_non_unique_tag)1122   bool lower_link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
1123   {
1124     index_node_type* y=header();
1125     index_node_type* x=root();
1126     bool c=false;
1127     while (x){
1128      y=x;
1129      c=comp_(key(x->value()),k);
1130      x=index_node_type::from_impl(c?x->right():x->left());
1131     }
1132     inf.side=c?to_right:to_left;
1133     inf.pos=y->impl();
1134     return true;
1135   }
1136 
hinted_link_point(key_param_type k,index_node_type * position,link_info & inf,ordered_unique_tag)1137   bool hinted_link_point(
1138     key_param_type k,index_node_type* position,
1139     link_info& inf,ordered_unique_tag)
1140   {
1141     if(position->impl()==header()->left()){
1142       if(size()>0&&comp_(k,key(position->value()))){
1143         inf.side=to_left;
1144         inf.pos=position->impl();
1145         return true;
1146       }
1147       else return link_point(k,inf,ordered_unique_tag());
1148     }
1149     else if(position==header()){
1150       if(comp_(key(rightmost()->value()),k)){
1151         inf.side=to_right;
1152         inf.pos=rightmost()->impl();
1153         return true;
1154       }
1155       else return link_point(k,inf,ordered_unique_tag());
1156     }
1157     else{
1158       index_node_type* before=position;
1159       index_node_type::decrement(before);
1160       if(comp_(key(before->value()),k)&&comp_(k,key(position->value()))){
1161         if(before->right()==node_impl_pointer(0)){
1162           inf.side=to_right;
1163           inf.pos=before->impl();
1164           return true;
1165         }
1166         else{
1167           inf.side=to_left;
1168           inf.pos=position->impl();
1169           return true;
1170         }
1171       }
1172       else return link_point(k,inf,ordered_unique_tag());
1173     }
1174   }
1175 
hinted_link_point(key_param_type k,index_node_type * position,link_info & inf,ordered_non_unique_tag)1176   bool hinted_link_point(
1177     key_param_type k,index_node_type* position,
1178     link_info& inf,ordered_non_unique_tag)
1179   {
1180     if(position->impl()==header()->left()){
1181       if(size()>0&&!comp_(key(position->value()),k)){
1182         inf.side=to_left;
1183         inf.pos=position->impl();
1184         return true;
1185       }
1186       else return lower_link_point(k,inf,ordered_non_unique_tag());
1187     }
1188     else if(position==header()){
1189       if(!comp_(k,key(rightmost()->value()))){
1190         inf.side=to_right;
1191         inf.pos=rightmost()->impl();
1192         return true;
1193       }
1194       else return link_point(k,inf,ordered_non_unique_tag());
1195     }
1196     else{
1197       index_node_type* before=position;
1198       index_node_type::decrement(before);
1199       if(!comp_(k,key(before->value()))){
1200         if(!comp_(key(position->value()),k)){
1201           if(before->right()==node_impl_pointer(0)){
1202             inf.side=to_right;
1203             inf.pos=before->impl();
1204             return true;
1205           }
1206           else{
1207             inf.side=to_left;
1208             inf.pos=position->impl();
1209             return true;
1210           }
1211         }
1212         else return lower_link_point(k,inf,ordered_non_unique_tag());
1213       }
1214       else return link_point(k,inf,ordered_non_unique_tag());
1215     }
1216   }
1217 
delete_all_nodes(index_node_type * x)1218   void delete_all_nodes(index_node_type* x)
1219   {
1220     if(!x)return;
1221 
1222     delete_all_nodes(index_node_type::from_impl(x->left()));
1223     delete_all_nodes(index_node_type::from_impl(x->right()));
1224     this->final_delete_node_(static_cast<final_node_type*>(x));
1225   }
1226 
in_place(value_param_type v,index_node_type * x,ordered_unique_tag) const1227   bool in_place(value_param_type v,index_node_type* x,ordered_unique_tag)const
1228   {
1229     index_node_type* y;
1230     if(x!=leftmost()){
1231       y=x;
1232       index_node_type::decrement(y);
1233       if(!comp_(key(y->value()),key(v)))return false;
1234     }
1235 
1236     y=x;
1237     index_node_type::increment(y);
1238     return y==header()||comp_(key(v),key(y->value()));
1239   }
1240 
in_place(value_param_type v,index_node_type * x,ordered_non_unique_tag) const1241   bool in_place(
1242     value_param_type v,index_node_type* x,ordered_non_unique_tag)const
1243   {
1244     index_node_type* y;
1245     if(x!=leftmost()){
1246       y=x;
1247       index_node_type::decrement(y);
1248       if(comp_(key(v),key(y->value())))return false;
1249     }
1250 
1251     y=x;
1252     index_node_type::increment(y);
1253     return y==header()||!comp_(key(y->value()),key(v));
1254   }
1255 
1256 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(index_node_type * x)1257   void detach_iterators(index_node_type* x)
1258   {
1259     iterator it=make_iterator(x);
1260     safe_mode::detach_equivalent_iterators(it);
1261   }
1262 #endif
1263 
1264   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)1265   std::pair<iterator,bool> emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1266   {
1267     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
1268     std::pair<final_node_type*,bool>p=
1269       this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1270     return std::pair<iterator,bool>(make_iterator(p.first),p.second);
1271   }
1272 
1273   template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
emplace_hint_impl(iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)1274   iterator emplace_hint_impl(
1275     iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
1276   {
1277     BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
1278     BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
1279     BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
1280     std::pair<final_node_type*,bool>p=
1281       this->final_emplace_hint_(
1282         static_cast<final_node_type*>(position.get_node()),
1283         BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
1284     return make_iterator(p.first);
1285   }
1286 
1287   template<typename LowerBounder,typename UpperBounder>
1288   std::pair<iterator,iterator>
range(LowerBounder lower,UpperBounder upper,none_unbounded_tag) const1289   range(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
1290   {
1291     index_node_type* y=header();
1292     index_node_type* z=root();
1293 
1294     while(z){
1295       if(!lower(key(z->value()))){
1296         z=index_node_type::from_impl(z->right());
1297       }
1298       else if(!upper(key(z->value()))){
1299         y=z;
1300         z=index_node_type::from_impl(z->left());
1301       }
1302       else{
1303         return std::pair<iterator,iterator>(
1304           make_iterator(
1305             lower_range(index_node_type::from_impl(z->left()),z,lower)),
1306           make_iterator(
1307             upper_range(index_node_type::from_impl(z->right()),y,upper)));
1308       }
1309     }
1310 
1311     return std::pair<iterator,iterator>(make_iterator(y),make_iterator(y));
1312   }
1313 
1314   template<typename LowerBounder,typename UpperBounder>
1315   std::pair<iterator,iterator>
range(LowerBounder,UpperBounder upper,lower_unbounded_tag) const1316   range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
1317   {
1318     return std::pair<iterator,iterator>(
1319       begin(),
1320       make_iterator(upper_range(root(),header(),upper)));
1321   }
1322 
1323   template<typename LowerBounder,typename UpperBounder>
1324   std::pair<iterator,iterator>
range(LowerBounder lower,UpperBounder,upper_unbounded_tag) const1325   range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
1326   {
1327     return std::pair<iterator,iterator>(
1328       make_iterator(lower_range(root(),header(),lower)),
1329       end());
1330   }
1331 
1332   template<typename LowerBounder,typename UpperBounder>
1333   std::pair<iterator,iterator>
range(LowerBounder,UpperBounder,both_unbounded_tag) const1334   range(LowerBounder,UpperBounder,both_unbounded_tag)const
1335   {
1336     return std::pair<iterator,iterator>(begin(),end());
1337   }
1338 
1339   template<typename LowerBounder>
lower_range(index_node_type * top,index_node_type * y,LowerBounder lower) const1340   index_node_type * lower_range(
1341     index_node_type* top,index_node_type* y,LowerBounder lower)const
1342   {
1343     while(top){
1344       if(lower(key(top->value()))){
1345         y=top;
1346         top=index_node_type::from_impl(top->left());
1347       }
1348       else top=index_node_type::from_impl(top->right());
1349     }
1350 
1351     return y;
1352   }
1353 
1354   template<typename UpperBounder>
upper_range(index_node_type * top,index_node_type * y,UpperBounder upper) const1355   index_node_type * upper_range(
1356     index_node_type* top,index_node_type* y,UpperBounder upper)const
1357   {
1358     while(top){
1359       if(!upper(key(top->value()))){
1360         y=top;
1361         top=index_node_type::from_impl(top->left());
1362       }
1363       else top=index_node_type::from_impl(top->right());
1364     }
1365 
1366     return y;
1367   }
1368 
1369 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
1370   template<typename Archive>
save_(Archive & ar,const unsigned int version,const index_saver_type & sm,ordered_unique_tag) const1371   void save_(
1372     Archive& ar,const unsigned int version,const index_saver_type& sm,
1373     ordered_unique_tag)const
1374   {
1375     super::save_(ar,version,sm);
1376   }
1377 
1378   template<typename Archive>
load_(Archive & ar,const unsigned int version,const index_loader_type & lm,ordered_unique_tag)1379   void load_(
1380     Archive& ar,const unsigned int version,const index_loader_type& lm,
1381     ordered_unique_tag)
1382   {
1383     super::load_(ar,version,lm);
1384   }
1385 
1386   template<typename Archive>
save_(Archive & ar,const unsigned int version,const index_saver_type & sm,ordered_non_unique_tag) const1387   void save_(
1388     Archive& ar,const unsigned int version,const index_saver_type& sm,
1389     ordered_non_unique_tag)const
1390   {
1391     typedef duplicates_iterator<index_node_type,value_compare> dup_iterator;
1392 
1393     sm.save(
1394       dup_iterator(begin().get_node(),end().get_node(),value_comp()),
1395       dup_iterator(end().get_node(),value_comp()),
1396       ar,version);
1397     super::save_(ar,version,sm);
1398   }
1399 
1400   template<typename Archive>
load_(Archive & ar,const unsigned int version,const index_loader_type & lm,ordered_non_unique_tag)1401   void load_(
1402     Archive& ar,const unsigned int version,const index_loader_type& lm,
1403     ordered_non_unique_tag)
1404   {
1405     lm.load(
1406       ::boost::bind(
1407         &ordered_index_impl::rearranger,this,
1408         ::boost::arg<1>(),::boost::arg<2>()),
1409       ar,version);
1410     super::load_(ar,version,lm);
1411   }
1412 
rearranger(index_node_type * position,index_node_type * x)1413   void rearranger(index_node_type* position,index_node_type *x)
1414   {
1415     if(!position||comp_(key(position->value()),key(x->value()))){
1416       position=lower_bound(key(x->value())).get_node();
1417     }
1418     else if(comp_(key(x->value()),key(position->value()))){
1419       /* inconsistent rearrangement */
1420       throw_exception(
1421         archive::archive_exception(
1422           archive::archive_exception::other_exception));
1423     }
1424     else index_node_type::increment(position);
1425 
1426     if(position!=x){
1427       node_impl_type::rebalance_for_extract(
1428         x->impl(),header()->parent(),header()->left(),header()->right());
1429       node_impl_type::restore(
1430         x->impl(),position->impl(),header()->impl());
1431     }
1432   }
1433 #endif /* serialization */
1434 
1435 protected: /* for the benefit of AugmentPolicy::augmented_interface */
1436   key_from_value key;
1437   key_compare    comp_;
1438 
1439 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
1440     BOOST_WORKAROUND(__MWERKS__,<=0x3003)
1441 #pragma parse_mfunc_templ reset
1442 #endif
1443 };
1444 
1445 template<
1446   typename KeyFromValue,typename Compare,
1447   typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
1448 >
1449 class ordered_index:
1450   public AugmentPolicy::template augmented_interface<
1451     ordered_index_impl<
1452       KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy
1453     >
1454   >::type
1455 {
1456   typedef typename AugmentPolicy::template
1457     augmented_interface<
1458       ordered_index_impl<
1459         KeyFromValue,Compare,
1460         SuperMeta,TagList,Category,AugmentPolicy
1461       >
1462     >::type                                       super;
1463 public:
1464   typedef typename super::ctor_args_list          ctor_args_list;
1465   typedef typename super::allocator_type          allocator_type;
1466   typedef typename super::iterator                iterator;
1467 
1468   /* construct/copy/destroy
1469    * Default and copy ctors are in the protected section as indices are
1470    * not supposed to be created on their own. No range ctor either.
1471    */
1472 
operator =(const ordered_index & x)1473   ordered_index& operator=(const ordered_index& x)
1474   {
1475     this->final()=x.final();
1476     return *this;
1477   }
1478 
1479 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
operator =(std::initializer_list<BOOST_DEDUCED_TYPENAME super::value_type> list)1480   ordered_index& operator=(
1481     std::initializer_list<BOOST_DEDUCED_TYPENAME super::value_type> list)
1482   {
1483     this->final()=list;
1484     return *this;
1485   }
1486 #endif
1487 
1488 protected:
ordered_index(const ctor_args_list & args_list,const allocator_type & al)1489   ordered_index(
1490     const ctor_args_list& args_list,const allocator_type& al):
1491     super(args_list,al){}
1492 
ordered_index(const ordered_index & x)1493   ordered_index(const ordered_index& x):super(x){}
1494 
ordered_index(const ordered_index & x,do_not_copy_elements_tag)1495   ordered_index(const ordered_index& x,do_not_copy_elements_tag):
1496     super(x,do_not_copy_elements_tag()){}
1497 };
1498 
1499 /* comparison */
1500 
1501 template<
1502   typename KeyFromValue1,typename Compare1,
1503   typename SuperMeta1,typename TagList1,typename Category1,
1504   typename AugmentPolicy1,
1505   typename KeyFromValue2,typename Compare2,
1506   typename SuperMeta2,typename TagList2,typename Category2,
1507   typename AugmentPolicy2
1508 >
operator ==(const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1> & x,const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2> & y)1509 bool operator==(
1510   const ordered_index<
1511     KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
1512   const ordered_index<
1513     KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
1514 {
1515   return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
1516 }
1517 
1518 template<
1519   typename KeyFromValue1,typename Compare1,
1520   typename SuperMeta1,typename TagList1,typename Category1,
1521   typename AugmentPolicy1,
1522   typename KeyFromValue2,typename Compare2,
1523   typename SuperMeta2,typename TagList2,typename Category2,
1524   typename AugmentPolicy2
1525 >
operator <(const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1> & x,const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2> & y)1526 bool operator<(
1527   const ordered_index<
1528     KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
1529   const ordered_index<
1530     KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
1531 {
1532   return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
1533 }
1534 
1535 template<
1536   typename KeyFromValue1,typename Compare1,
1537   typename SuperMeta1,typename TagList1,typename Category1,
1538   typename AugmentPolicy1,
1539   typename KeyFromValue2,typename Compare2,
1540   typename SuperMeta2,typename TagList2,typename Category2,
1541   typename AugmentPolicy2
1542 >
operator !=(const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1> & x,const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2> & y)1543 bool operator!=(
1544   const ordered_index<
1545     KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
1546   const ordered_index<
1547     KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
1548 {
1549   return !(x==y);
1550 }
1551 
1552 template<
1553   typename KeyFromValue1,typename Compare1,
1554   typename SuperMeta1,typename TagList1,typename Category1,
1555   typename AugmentPolicy1,
1556   typename KeyFromValue2,typename Compare2,
1557   typename SuperMeta2,typename TagList2,typename Category2,
1558   typename AugmentPolicy2
1559 >
operator >(const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1> & x,const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2> & y)1560 bool operator>(
1561   const ordered_index<
1562     KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
1563   const ordered_index<
1564     KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
1565 {
1566   return y<x;
1567 }
1568 
1569 template<
1570   typename KeyFromValue1,typename Compare1,
1571   typename SuperMeta1,typename TagList1,typename Category1,
1572   typename AugmentPolicy1,
1573   typename KeyFromValue2,typename Compare2,
1574   typename SuperMeta2,typename TagList2,typename Category2,
1575   typename AugmentPolicy2
1576 >
operator >=(const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1> & x,const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2> & y)1577 bool operator>=(
1578   const ordered_index<
1579     KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
1580   const ordered_index<
1581     KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
1582 {
1583   return !(x<y);
1584 }
1585 
1586 template<
1587   typename KeyFromValue1,typename Compare1,
1588   typename SuperMeta1,typename TagList1,typename Category1,
1589   typename AugmentPolicy1,
1590   typename KeyFromValue2,typename Compare2,
1591   typename SuperMeta2,typename TagList2,typename Category2,
1592   typename AugmentPolicy2
1593 >
operator <=(const ordered_index<KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1> & x,const ordered_index<KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2> & y)1594 bool operator<=(
1595   const ordered_index<
1596     KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
1597   const ordered_index<
1598     KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
1599 {
1600   return !(x>y);
1601 }
1602 
1603 /*  specialized algorithms */
1604 
1605 template<
1606   typename KeyFromValue,typename Compare,
1607   typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
1608 >
swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & x,ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> & y)1609 void swap(
1610   ordered_index<
1611     KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
1612   ordered_index<
1613     KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& y)
1614 {
1615   x.swap(y);
1616 }
1617 
1618 } /* namespace multi_index::detail */
1619 
1620 } /* namespace multi_index */
1621 
1622 } /* namespace boost */
1623 
1624 /* Boost.Foreach compatibility */
1625 
1626 template<
1627   typename KeyFromValue,typename Compare,
1628   typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
1629 >
boost_foreach_is_noncopyable(boost::multi_index::detail::ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> * &,boost_foreach_argument_dependent_lookup_hack)1630 inline boost::mpl::true_* boost_foreach_is_noncopyable(
1631   boost::multi_index::detail::ordered_index<
1632     KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>*&,
1633   boost_foreach_argument_dependent_lookup_hack)
1634 {
1635   return 0;
1636 }
1637 
1638 #undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
1639 #undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF
1640 
1641 #endif
1642