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