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