1 /////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2007-2008
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // See http://www.boost.org/libs/intrusive for documentation.
11 /////////////////////////////////////////////////////////////////////////////
12 #ifndef BOOST_INTRUSIVE_AVLTREE_HPP
13 #define BOOST_INTRUSIVE_AVLTREE_HPP
15 #include <boost/intrusive/detail/config_begin.hpp>
22 #include <boost/intrusive/detail/assert.hpp>
23 #include <boost/static_assert.hpp>
24 #include <boost/intrusive/intrusive_fwd.hpp>
25 #include <boost/intrusive/avl_set_hook.hpp>
26 #include <boost/intrusive/detail/avltree_node.hpp>
27 #include <boost/intrusive/detail/tree_node.hpp>
28 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
29 #include <boost/intrusive/detail/mpl.hpp>
30 #include <boost/intrusive/detail/pointer_to_other.hpp>
31 #include <boost/intrusive/detail/clear_on_destructor_base.hpp>
32 #include <boost/intrusive/options.hpp>
33 #include <boost/intrusive/avltree_algorithms.hpp>
34 #include <boost/intrusive/link_mode.hpp>
41 template <class ValueTraits
, class Compare
, class SizeType
, bool ConstantTimeSize
>
44 typedef ValueTraits value_traits
;
45 typedef Compare compare
;
46 typedef SizeType size_type
;
47 static const bool constant_time_size
= ConstantTimeSize
;
51 struct avl_set_defaults
54 , base_hook
<detail::default_avl_set_hook
>
55 , constant_time_size
<true>
56 , size_type
<std::size_t>
57 , compare
<std::less
<T
> >
63 //! The class template avltree is an intrusive AVL tree container, that
64 //! is used to construct intrusive avl_set and avl_multiset containers.
65 //! The no-throw guarantee holds only, if the value_compare object
68 //! The template parameter \c T is the type to be managed by the container.
69 //! The user can specify additional options and if no options are provided
70 //! default options are used.
72 //! The container supports the following options:
73 //! \c base_hook<>/member_hook<>/value_traits<>,
74 //! \c constant_time_size<>, \c size_type<> and
76 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
77 template<class T
, class ...Options
>
79 template<class Config
>
82 : private detail::clear_on_destructor_base
<avltree_impl
<Config
> >
84 template<class C
> friend class detail::clear_on_destructor_base
;
86 typedef typename
Config::value_traits value_traits
;
88 static const bool external_value_traits
=
89 detail::external_value_traits_is_true
<value_traits
>::value
;
90 typedef typename
detail::eval_if_c
91 < external_value_traits
92 , detail::eval_value_traits
<value_traits
>
93 , detail::identity
<value_traits
>
94 >::type real_value_traits
;
96 typedef typename
real_value_traits::pointer pointer
;
97 typedef typename
real_value_traits::const_pointer const_pointer
;
98 typedef typename
std::iterator_traits
<pointer
>::value_type value_type
;
99 typedef value_type key_type
;
100 typedef typename
std::iterator_traits
<pointer
>::reference reference
;
101 typedef typename
std::iterator_traits
<const_pointer
>::reference const_reference
;
102 typedef typename
std::iterator_traits
<pointer
>::difference_type difference_type
;
103 typedef typename
Config::size_type size_type
;
104 typedef typename
Config::compare value_compare
;
105 typedef value_compare key_compare
;
106 typedef tree_iterator
<avltree_impl
, false> iterator
;
107 typedef tree_iterator
<avltree_impl
, true> const_iterator
;
108 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
109 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
110 typedef typename
real_value_traits::node_traits node_traits
;
111 typedef typename
node_traits::node node
;
112 typedef typename
boost::pointer_to_other
113 <pointer
, node
>::type node_ptr
;
114 typedef typename
boost::pointer_to_other
115 <node_ptr
, const node
>::type const_node_ptr
;
116 typedef avltree_algorithms
<node_traits
> node_algorithms
;
118 static const bool constant_time_size
= Config::constant_time_size
;
119 static const bool stateful_value_traits
= detail::store_cont_ptr_on_it
<avltree_impl
>::value
;
123 typedef detail::size_holder
<constant_time_size
, size_type
> size_traits
;
126 avltree_impl (const avltree_impl
&);
127 avltree_impl
operator =(const avltree_impl
&);
129 enum { safemode_or_autounlink
=
130 (int)real_value_traits::link_mode
== (int)auto_unlink
||
131 (int)real_value_traits::link_mode
== (int)safe_link
};
133 //Constant-time size is incompatible with auto-unlink hooks!
134 BOOST_STATIC_ASSERT(!(constant_time_size
&& ((int)real_value_traits::link_mode
== (int)auto_unlink
)));
136 struct header_plus_size
: public size_traits
139 struct node_plus_pred_t
: public detail::ebo_functor_holder
<value_compare
>
141 node_plus_pred_t(const value_compare
&comp
)
142 : detail::ebo_functor_holder
<value_compare
>(comp
)
144 header_plus_size header_plus_size_
;
147 struct data_t
: public avltree_impl::value_traits
149 typedef typename
avltree_impl::value_traits value_traits
;
150 data_t(const value_compare
& comp
, const value_traits
&val_traits
)
151 : value_traits(val_traits
), node_plus_pred_(comp
)
153 node_plus_pred_t node_plus_pred_
;
156 const value_compare
&priv_comp() const
157 { return data_
.node_plus_pred_
.get(); }
159 value_compare
&priv_comp()
160 { return data_
.node_plus_pred_
.get(); }
162 const node
&priv_header() const
163 { return data_
.node_plus_pred_
.header_plus_size_
.header_
; }
166 { return data_
.node_plus_pred_
.header_plus_size_
.header_
; }
168 static node_ptr
uncast(const_node_ptr ptr
)
170 return node_ptr(const_cast<node
*>(detail::get_pointer(ptr
)));
173 size_traits
&priv_size_traits()
174 { return data_
.node_plus_pred_
.header_plus_size_
; }
176 const size_traits
&priv_size_traits() const
177 { return data_
.node_plus_pred_
.header_plus_size_
; }
179 const real_value_traits
&get_real_value_traits(detail::bool_
<false>) const
182 const real_value_traits
&get_real_value_traits(detail::bool_
<true>) const
183 { return data_
.get_value_traits(*this); }
185 real_value_traits
&get_real_value_traits(detail::bool_
<false>)
188 real_value_traits
&get_real_value_traits(detail::bool_
<true>)
189 { return data_
.get_value_traits(*this); }
195 const real_value_traits
&get_real_value_traits() const
196 { return this->get_real_value_traits(detail::bool_
<external_value_traits
>()); }
198 real_value_traits
&get_real_value_traits()
199 { return this->get_real_value_traits(detail::bool_
<external_value_traits
>()); }
201 typedef typename
node_algorithms::insert_commit_data insert_commit_data
;
203 //! <b>Effects</b>: Constructs an empty tree.
205 //! <b>Complexity</b>: Constant.
207 //! <b>Throws</b>: If value_traits::node_traits::node
208 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
209 //! or the copy constructor of the value_compare object throws. Basic guarantee.
210 avltree_impl( const value_compare
&cmp
= value_compare()
211 , const value_traits
&v_traits
= value_traits())
212 : data_(cmp
, v_traits
)
214 node_algorithms::init_header(&priv_header());
215 this->priv_size_traits().set_size(size_type(0));
218 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
219 //! cmp must be a comparison function that induces a strict weak ordering.
221 //! <b>Effects</b>: Constructs an empty tree and inserts elements from
224 //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using
225 //! comp and otherwise N * log N, where N is the distance between first and last.
227 //! <b>Throws</b>: If value_traits::node_traits::node
228 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
229 //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee.
230 template<class Iterator
>
231 avltree_impl( bool unique
, Iterator b
, Iterator e
232 , const value_compare
&cmp
= value_compare()
233 , const value_traits
&v_traits
= value_traits())
234 : data_(cmp
, v_traits
)
236 node_algorithms::init_header(&priv_header());
237 this->priv_size_traits().set_size(size_type(0));
239 this->insert_unique(b
, e
);
241 this->insert_equal(b
, e
);
244 //! <b>Effects</b>: Detaches all elements from this. The objects in the set
245 //! are not deleted (i.e. no destructors are called), but the nodes according to
246 //! the value_traits template parameter are reinitialized and thus can be reused.
248 //! <b>Complexity</b>: Linear to elements contained in *this.
250 //! <b>Throws</b>: Nothing.
254 //! <b>Effects</b>: Returns an iterator pointing to the beginning of the tree.
256 //! <b>Complexity</b>: Constant.
258 //! <b>Throws</b>: Nothing.
260 { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); }
262 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
264 //! <b>Complexity</b>: Constant.
266 //! <b>Throws</b>: Nothing.
267 const_iterator
begin() const
270 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
272 //! <b>Complexity</b>: Constant.
274 //! <b>Throws</b>: Nothing.
275 const_iterator
cbegin() const
276 { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); }
278 //! <b>Effects</b>: Returns an iterator pointing to the end of the tree.
280 //! <b>Complexity</b>: Constant.
282 //! <b>Throws</b>: Nothing.
284 { return iterator (node_ptr(&priv_header()), this); }
286 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
288 //! <b>Complexity</b>: Constant.
290 //! <b>Throws</b>: Nothing.
291 const_iterator
end() const
294 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
296 //! <b>Complexity</b>: Constant.
298 //! <b>Throws</b>: Nothing.
299 const_iterator
cend() const
300 { return const_iterator (uncast(const_node_ptr(&priv_header())), this); }
302 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning of the
305 //! <b>Complexity</b>: Constant.
307 //! <b>Throws</b>: Nothing.
308 reverse_iterator
rbegin()
309 { return reverse_iterator(end()); }
311 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
312 //! of the reversed tree.
314 //! <b>Complexity</b>: Constant.
316 //! <b>Throws</b>: Nothing.
317 const_reverse_iterator
rbegin() const
318 { return const_reverse_iterator(end()); }
320 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
321 //! of the reversed tree.
323 //! <b>Complexity</b>: Constant.
325 //! <b>Throws</b>: Nothing.
326 const_reverse_iterator
crbegin() const
327 { return const_reverse_iterator(end()); }
329 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
330 //! of the reversed tree.
332 //! <b>Complexity</b>: Constant.
334 //! <b>Throws</b>: Nothing.
335 reverse_iterator
rend()
336 { return reverse_iterator(begin()); }
338 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
339 //! of the reversed tree.
341 //! <b>Complexity</b>: Constant.
343 //! <b>Throws</b>: Nothing.
344 const_reverse_iterator
rend() const
345 { return const_reverse_iterator(begin()); }
347 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
348 //! of the reversed tree.
350 //! <b>Complexity</b>: Constant.
352 //! <b>Throws</b>: Nothing.
353 const_reverse_iterator
crend() const
354 { return const_reverse_iterator(begin()); }
356 //! <b>Precondition</b>: end_iterator must be a valid end iterator
359 //! <b>Effects</b>: Returns a const reference to the avltree associated to the end iterator
361 //! <b>Throws</b>: Nothing.
363 //! <b>Complexity</b>: Constant.
364 static avltree_impl
&container_from_end_iterator(iterator end_iterator
)
365 { return priv_container_from_end_iterator(end_iterator
); }
367 //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
370 //! <b>Effects</b>: Returns a const reference to the avltree associated to the end iterator
372 //! <b>Throws</b>: Nothing.
374 //! <b>Complexity</b>: Constant.
375 static const avltree_impl
&container_from_end_iterator(const_iterator end_iterator
)
376 { return priv_container_from_end_iterator(end_iterator
); }
378 //! <b>Precondition</b>: it must be a valid iterator
381 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
383 //! <b>Throws</b>: Nothing.
385 //! <b>Complexity</b>: Logarithmic.
386 static avltree_impl
&container_from_iterator(iterator it
)
387 { return priv_container_from_iterator(it
); }
389 //! <b>Precondition</b>: it must be a valid end const_iterator
392 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
394 //! <b>Throws</b>: Nothing.
396 //! <b>Complexity</b>: Logarithmic.
397 static const avltree_impl
&container_from_iterator(const_iterator it
)
398 { return priv_container_from_iterator(it
); }
400 //! <b>Effects</b>: Returns the value_compare object used by the tree.
402 //! <b>Complexity</b>: Constant.
404 //! <b>Throws</b>: If value_compare copy-constructor throws.
405 value_compare
value_comp() const
406 { return priv_comp(); }
408 //! <b>Effects</b>: Returns true if the container is empty.
410 //! <b>Complexity</b>: Constant.
412 //! <b>Throws</b>: Nothing.
414 { return node_algorithms::unique(const_node_ptr(&priv_header())); }
416 //! <b>Effects</b>: Returns the number of elements stored in the tree.
418 //! <b>Complexity</b>: Linear to elements contained in *this
419 //! if constant-time size option is disabled. Constant time otherwise.
421 //! <b>Throws</b>: Nothing.
422 size_type
size() const
424 if(constant_time_size
)
425 return this->priv_size_traits().get_size();
427 return (size_type
)node_algorithms::size(const_node_ptr(&priv_header()));
431 //! <b>Effects</b>: Swaps the contents of two avltrees.
433 //! <b>Complexity</b>: Constant.
435 //! <b>Throws</b>: If the comparison functor's swap call throws.
436 void swap(avltree_impl
& other
)
440 swap(priv_comp(), priv_comp());
442 node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other
.priv_header()));
443 if(constant_time_size
){
444 size_type backup
= this->priv_size_traits().get_size();
445 this->priv_size_traits().set_size(other
.priv_size_traits().get_size());
446 other
.priv_size_traits().set_size(backup
);
450 //! <b>Requires</b>: value must be an lvalue
452 //! <b>Effects</b>: Inserts value into the tree before the upper bound.
454 //! <b>Complexity</b>: Average complexity for insert element is at
455 //! most logarithmic.
457 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
459 //! <b>Note</b>: Does not affect the validity of iterators and references.
460 //! No copy-constructors are called.
461 iterator
insert_equal(reference value
)
463 detail::key_nodeptr_comp
<value_compare
, avltree_impl
>
464 key_node_comp(priv_comp(), this);
465 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
466 if(safemode_or_autounlink
)
467 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
468 this->priv_size_traits().increment();
469 return iterator(node_algorithms::insert_equal_upper_bound
470 (node_ptr(&priv_header()), to_insert
, key_node_comp
), this);
473 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
474 //! a valid iterator.
476 //! <b>Effects</b>: Inserts x into the tree, using "hint" as a hint to
477 //! where it will be inserted. If "hint" is the upper_bound
478 //! the insertion takes constant time (two comparisons in the worst case)
480 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
481 //! constant time if t is inserted immediately before hint.
483 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
485 //! <b>Note</b>: Does not affect the validity of iterators and references.
486 //! No copy-constructors are called.
487 iterator
insert_equal(const_iterator hint
, reference value
)
489 detail::key_nodeptr_comp
<value_compare
, avltree_impl
>
490 key_node_comp(priv_comp(), this);
491 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
492 if(safemode_or_autounlink
)
493 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
494 this->priv_size_traits().increment();
495 return iterator(node_algorithms::insert_equal
496 (node_ptr(&priv_header()), hint
.pointed_node(), to_insert
, key_node_comp
), this);
499 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
500 //! of type value_type.
502 //! <b>Effects</b>: Inserts a each element of a range into the tree
503 //! before the upper bound of the key of each element.
505 //! <b>Complexity</b>: Insert range is in general O(N * log(N)), where N is the
506 //! size of the range. However, it is linear in N if the range is already sorted
509 //! <b>Throws</b>: Nothing.
511 //! <b>Note</b>: Does not affect the validity of iterators and references.
512 //! No copy-constructors are called.
513 template<class Iterator
>
514 void insert_equal(Iterator b
, Iterator e
)
516 iterator
end(this->end());
518 this->insert_equal(end
, *b
);
521 //! <b>Requires</b>: value must be an lvalue
523 //! <b>Effects</b>: Inserts value into the tree if the value
524 //! is not already present.
526 //! <b>Complexity</b>: Average complexity for insert element is at
527 //! most logarithmic.
529 //! <b>Throws</b>: Nothing.
531 //! <b>Note</b>: Does not affect the validity of iterators and references.
532 //! No copy-constructors are called.
533 std::pair
<iterator
, bool> insert_unique(reference value
)
535 insert_commit_data commit_data
;
536 std::pair
<iterator
, bool> ret
= insert_unique_check(value
, priv_comp(), commit_data
);
539 return std::pair
<iterator
, bool> (insert_unique_commit(value
, commit_data
), true);
542 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
545 //! <b>Effects</b>: Tries to insert x into the tree, using "hint" as a hint
546 //! to where it will be inserted.
548 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
549 //! constant time (two comparisons in the worst case)
550 //! if t is inserted immediately before hint.
552 //! <b>Throws</b>: Nothing.
554 //! <b>Note</b>: Does not affect the validity of iterators and references.
555 //! No copy-constructors are called.
556 iterator
insert_unique(const_iterator hint
, reference value
)
558 insert_commit_data commit_data
;
559 std::pair
<iterator
, bool> ret
= insert_unique_check(hint
, value
, priv_comp(), commit_data
);
562 return insert_unique_commit(value
, commit_data
);
565 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
566 //! of type value_type.
568 //! <b>Effects</b>: Tries to insert each element of a range into the tree.
570 //! <b>Complexity</b>: Insert range is in general O(N * log(N)), where N is the
571 //! size of the range. However, it is linear in N if the range is already sorted
574 //! <b>Throws</b>: Nothing.
576 //! <b>Note</b>: Does not affect the validity of iterators and references.
577 //! No copy-constructors are called.
578 template<class Iterator
>
579 void insert_unique(Iterator b
, Iterator e
)
582 iterator
end(this->end());
584 this->insert_unique(end
, *b
);
588 this->insert_unique(*b
);
592 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
593 //! the same strict weak ordering as value_compare. The difference is that
594 //! key_value_comp compares an arbitrary key with the contained values.
596 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
597 //! a user provided key instead of the value itself.
599 //! <b>Returns</b>: If there is an equivalent value
600 //! returns a pair containing an iterator to the already present value
601 //! and false. If the value can be inserted returns true in the returned
602 //! pair boolean and fills "commit_data" that is meant to be used with
603 //! the "insert_commit" function.
605 //! <b>Complexity</b>: Average complexity is at most logarithmic.
607 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
609 //! <b>Notes</b>: This function is used to improve performance when constructing
610 //! a value_type is expensive: if there is an equivalent value
611 //! the constructed object must be discarded. Many times, the part of the
612 //! node that is used to impose the order is much cheaper to construct
613 //! than the value_type and this function offers the possibility to use that
614 //! part to check if the insertion will be successful.
616 //! If the check is successful, the user can construct the value_type and use
617 //! "insert_commit" to insert the object in constant-time. This gives a total
618 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
620 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
621 //! objects are inserted or erased from the container.
622 template<class KeyType
, class KeyValueCompare
>
623 std::pair
<iterator
, bool> insert_unique_check
624 (const KeyType
&key
, KeyValueCompare key_value_comp
, insert_commit_data
&commit_data
)
626 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
627 comp(key_value_comp
, this);
628 std::pair
<node_ptr
, bool> ret
=
629 (node_algorithms::insert_unique_check
630 (node_ptr(&priv_header()), key
, comp
, commit_data
));
631 return std::pair
<iterator
, bool>(iterator(ret
.first
, this), ret
.second
);
634 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
635 //! the same strict weak ordering as value_compare. The difference is that
636 //! key_value_comp compares an arbitrary key with the contained values.
638 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
639 //! a user provided key instead of the value itself, using "hint"
640 //! as a hint to where it will be inserted.
642 //! <b>Returns</b>: If there is an equivalent value
643 //! returns a pair containing an iterator to the already present value
644 //! and false. If the value can be inserted returns true in the returned
645 //! pair boolean and fills "commit_data" that is meant to be used with
646 //! the "insert_commit" function.
648 //! <b>Complexity</b>: Logarithmic in general, but it's amortized
649 //! constant time if t is inserted immediately before hint.
651 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
653 //! <b>Notes</b>: This function is used to improve performance when constructing
654 //! a value_type is expensive: if there is an equivalent value
655 //! the constructed object must be discarded. Many times, the part of the
656 //! constructing that is used to impose the order is much cheaper to construct
657 //! than the value_type and this function offers the possibility to use that key
658 //! to check if the insertion will be successful.
660 //! If the check is successful, the user can construct the value_type and use
661 //! "insert_commit" to insert the object in constant-time. This can give a total
662 //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)).
664 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
665 //! objects are inserted or erased from the container.
666 template<class KeyType
, class KeyValueCompare
>
667 std::pair
<iterator
, bool> insert_unique_check
668 (const_iterator hint
, const KeyType
&key
669 ,KeyValueCompare key_value_comp
, insert_commit_data
&commit_data
)
671 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
672 comp(key_value_comp
, this);
673 std::pair
<node_ptr
, bool> ret
=
674 (node_algorithms::insert_unique_check
675 (node_ptr(&priv_header()), hint
.pointed_node(), key
, comp
, commit_data
));
676 return std::pair
<iterator
, bool>(iterator(ret
.first
, this), ret
.second
);
679 //! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
680 //! must have been obtained from a previous call to "insert_check".
681 //! No objects should have been inserted or erased from the container between
682 //! the "insert_check" that filled "commit_data" and the call to "insert_commit".
684 //! <b>Effects</b>: Inserts the value in the avl_set using the information obtained
685 //! from the "commit_data" that a previous "insert_check" filled.
687 //! <b>Returns</b>: An iterator to the newly inserted object.
689 //! <b>Complexity</b>: Constant time.
691 //! <b>Throws</b>: Nothing.
693 //! <b>Notes</b>: This function has only sense if a "insert_check" has been
694 //! previously executed to fill "commit_data". No value should be inserted or
695 //! erased between the "insert_check" and "insert_commit" calls.
696 iterator
insert_unique_commit(reference value
, const insert_commit_data
&commit_data
)
698 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
699 if(safemode_or_autounlink
)
700 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
701 this->priv_size_traits().increment();
702 node_algorithms::insert_unique_commit
703 (node_ptr(&priv_header()), to_insert
, commit_data
);
704 return iterator(to_insert
, this);
707 //! <b>Effects</b>: Erases the element pointed to by pos.
709 //! <b>Complexity</b>: Average complexity for erase element is constant time.
711 //! <b>Throws</b>: Nothing.
713 //! <b>Note</b>: Invalidates the iterators (but not the references)
714 //! to the erased elements. No destructors are called.
715 iterator
erase(const_iterator i
)
717 const_iterator
ret(i
);
719 node_ptr
to_erase(i
.pointed_node());
720 if(safemode_or_autounlink
)
721 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase
));
722 node_algorithms::erase(&priv_header(), to_erase
);
723 this->priv_size_traits().decrement();
724 if(safemode_or_autounlink
)
725 node_algorithms::init(to_erase
);
726 return ret
.unconst();
729 //! <b>Effects</b>: Erases the range pointed to by b end e.
731 //! <b>Complexity</b>: Average complexity for erase range is at most
732 //! O(log(size() + N)), where N is the number of elements in the range.
734 //! <b>Throws</b>: Nothing.
736 //! <b>Note</b>: Invalidates the iterators (but not the references)
737 //! to the erased elements. No destructors are called.
738 iterator
erase(const_iterator b
, const_iterator e
)
739 { size_type n
; return private_erase(b
, e
, n
); }
741 //! <b>Effects</b>: Erases all the elements with the given value.
743 //! <b>Returns</b>: The number of erased elements.
745 //! <b>Complexity</b>: O(log(size() + N).
747 //! <b>Throws</b>: Nothing.
749 //! <b>Note</b>: Invalidates the iterators (but not the references)
750 //! to the erased elements. No destructors are called.
751 size_type
erase(const_reference value
)
752 { return this->erase(value
, priv_comp()); }
754 //! <b>Effects</b>: Erases all the elements with the given key.
755 //! according to the comparison functor "comp".
757 //! <b>Returns</b>: The number of erased elements.
759 //! <b>Complexity</b>: O(log(size() + N).
761 //! <b>Throws</b>: Nothing.
763 //! <b>Note</b>: Invalidates the iterators (but not the references)
764 //! to the erased elements. No destructors are called.
765 template<class KeyType
, class KeyValueCompare
>
766 size_type
erase(const KeyType
& key
, KeyValueCompare comp
768 , typename
detail::enable_if_c
<!detail::is_convertible
<KeyValueCompare
, const_iterator
>::value
>::type
* = 0
772 std::pair
<iterator
,iterator
> p
= this->equal_range(key
, comp
);
774 private_erase(p
.first
, p
.second
, n
);
778 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
780 //! <b>Effects</b>: Erases the element pointed to by pos.
781 //! Disposer::operator()(pointer) is called for the removed element.
783 //! <b>Complexity</b>: Average complexity for erase element is constant time.
785 //! <b>Throws</b>: Nothing.
787 //! <b>Note</b>: Invalidates the iterators
788 //! to the erased elements.
789 template<class Disposer
>
790 iterator
erase_and_dispose(const_iterator i
, Disposer disposer
)
792 node_ptr
to_erase(i
.pointed_node());
793 iterator
ret(this->erase(i
));
794 disposer(get_real_value_traits().to_value_ptr(to_erase
));
798 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
799 template<class Disposer
>
800 iterator
erase_and_dispose(iterator i
, Disposer disposer
)
801 { return this->erase_and_dispose(const_iterator(i
), disposer
); }
804 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
806 //! <b>Effects</b>: Erases the range pointed to by b end e.
807 //! Disposer::operator()(pointer) is called for the removed elements.
809 //! <b>Complexity</b>: Average complexity for erase range is at most
810 //! O(log(size() + N)), where N is the number of elements in the range.
812 //! <b>Throws</b>: Nothing.
814 //! <b>Note</b>: Invalidates the iterators
815 //! to the erased elements.
816 template<class Disposer
>
817 iterator
erase_and_dispose(const_iterator b
, const_iterator e
, Disposer disposer
)
818 { size_type n
; return private_erase(b
, e
, n
, disposer
); }
820 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
822 //! <b>Effects</b>: Erases all the elements with the given value.
823 //! Disposer::operator()(pointer) is called for the removed elements.
825 //! <b>Returns</b>: The number of erased elements.
827 //! <b>Complexity</b>: O(log(size() + N).
829 //! <b>Throws</b>: Nothing.
831 //! <b>Note</b>: Invalidates the iterators (but not the references)
832 //! to the erased elements. No destructors are called.
833 template<class Disposer
>
834 size_type
erase_and_dispose(const_reference value
, Disposer disposer
)
836 std::pair
<iterator
,iterator
> p
= this->equal_range(value
);
838 private_erase(p
.first
, p
.second
, n
, disposer
);
842 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
844 //! <b>Effects</b>: Erases all the elements with the given key.
845 //! according to the comparison functor "comp".
846 //! Disposer::operator()(pointer) is called for the removed elements.
848 //! <b>Returns</b>: The number of erased elements.
850 //! <b>Complexity</b>: O(log(size() + N).
852 //! <b>Throws</b>: Nothing.
854 //! <b>Note</b>: Invalidates the iterators
855 //! to the erased elements.
856 template<class KeyType
, class KeyValueCompare
, class Disposer
>
857 size_type
erase_and_dispose(const KeyType
& key
, KeyValueCompare comp
, Disposer disposer
859 , typename
detail::enable_if_c
<!detail::is_convertible
<KeyValueCompare
, const_iterator
>::value
>::type
* = 0
863 std::pair
<iterator
,iterator
> p
= this->equal_range(key
, comp
);
865 private_erase(p
.first
, p
.second
, n
, disposer
);
869 //! <b>Effects</b>: Erases all of the elements.
871 //! <b>Complexity</b>: Linear to the number of elements on the container.
872 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
874 //! <b>Throws</b>: Nothing.
876 //! <b>Note</b>: Invalidates the iterators (but not the references)
877 //! to the erased elements. No destructors are called.
880 if(safemode_or_autounlink
){
881 this->clear_and_dispose(detail::null_disposer());
884 node_algorithms::init_header(&priv_header());
885 this->priv_size_traits().set_size(0);
889 //! <b>Effects</b>: Erases all of the elements calling disposer(p) for
890 //! each node to be erased.
891 //! <b>Complexity</b>: Average complexity for is at most O(log(size() + N)),
892 //! where N is the number of elements in the container.
894 //! <b>Throws</b>: Nothing.
896 //! <b>Note</b>: Invalidates the iterators (but not the references)
897 //! to the erased elements. Calls N times to disposer functor.
898 template<class Disposer
>
899 void clear_and_dispose(Disposer disposer
)
901 node_algorithms::clear_and_dispose(node_ptr(&priv_header())
902 , detail::node_disposer
<Disposer
, avltree_impl
>(disposer
, this));
903 node_algorithms::init_header(&priv_header());
904 this->priv_size_traits().set_size(0);
907 //! <b>Effects</b>: Returns the number of contained elements with the given value
909 //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal
910 //! to number of objects with the given value.
912 //! <b>Throws</b>: Nothing.
913 size_type
count(const_reference value
) const
914 { return this->count(value
, priv_comp()); }
916 //! <b>Effects</b>: Returns the number of contained elements with the given key
918 //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal
919 //! to number of objects with the given key.
921 //! <b>Throws</b>: Nothing.
922 template<class KeyType
, class KeyValueCompare
>
923 size_type
count(const KeyType
&key
, KeyValueCompare comp
) const
925 std::pair
<const_iterator
, const_iterator
> ret
= this->equal_range(key
, comp
);
926 return std::distance(ret
.first
, ret
.second
);
929 //! <b>Effects</b>: Returns an iterator to the first element whose
930 //! key is not less than k or end() if that element does not exist.
932 //! <b>Complexity</b>: Logarithmic.
934 //! <b>Throws</b>: Nothing.
935 iterator
lower_bound(const_reference value
)
936 { return this->lower_bound(value
, priv_comp()); }
938 //! <b>Effects</b>: Returns an iterator to the first element whose
939 //! key is not less than k or end() if that element does not exist.
941 //! <b>Complexity</b>: Logarithmic.
943 //! <b>Throws</b>: Nothing.
944 const_iterator
lower_bound(const_reference value
) const
945 { return this->lower_bound(value
, priv_comp()); }
947 //! <b>Effects</b>: Returns an iterator to the first element whose
948 //! key is not less than k or end() if that element does not exist.
950 //! <b>Complexity</b>: Logarithmic.
952 //! <b>Throws</b>: Nothing.
953 template<class KeyType
, class KeyValueCompare
>
954 iterator
lower_bound(const KeyType
&key
, KeyValueCompare comp
)
956 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
957 key_node_comp(comp
, this);
958 return iterator(node_algorithms::lower_bound
959 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
962 //! <b>Effects</b>: Returns a const iterator to the first element whose
963 //! key is not less than k or end() if that element does not exist.
965 //! <b>Complexity</b>: Logarithmic.
967 //! <b>Throws</b>: Nothing.
968 template<class KeyType
, class KeyValueCompare
>
969 const_iterator
lower_bound(const KeyType
&key
, KeyValueCompare comp
) const
971 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
972 key_node_comp(comp
, this);
973 return const_iterator(node_algorithms::lower_bound
974 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
977 //! <b>Effects</b>: Returns an iterator to the first element whose
978 //! key is greater than k or end() if that element does not exist.
980 //! <b>Complexity</b>: Logarithmic.
982 //! <b>Throws</b>: Nothing.
983 iterator
upper_bound(const_reference value
)
984 { return this->upper_bound(value
, priv_comp()); }
986 //! <b>Effects</b>: Returns an iterator to the first element whose
987 //! key is greater than k according to comp or end() if that element
990 //! <b>Complexity</b>: Logarithmic.
992 //! <b>Throws</b>: Nothing.
993 template<class KeyType
, class KeyValueCompare
>
994 iterator
upper_bound(const KeyType
&key
, KeyValueCompare comp
)
996 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
997 key_node_comp(comp
, this);
998 return iterator(node_algorithms::upper_bound
999 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1002 //! <b>Effects</b>: Returns an iterator to the first element whose
1003 //! key is greater than k or end() if that element does not exist.
1005 //! <b>Complexity</b>: Logarithmic.
1007 //! <b>Throws</b>: Nothing.
1008 const_iterator
upper_bound(const_reference value
) const
1009 { return this->upper_bound(value
, priv_comp()); }
1011 //! <b>Effects</b>: Returns an iterator to the first element whose
1012 //! key is greater than k according to comp or end() if that element
1015 //! <b>Complexity</b>: Logarithmic.
1017 //! <b>Throws</b>: Nothing.
1018 template<class KeyType
, class KeyValueCompare
>
1019 const_iterator
upper_bound(const KeyType
&key
, KeyValueCompare comp
) const
1021 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
1022 key_node_comp(comp
, this);
1023 return const_iterator(node_algorithms::upper_bound
1024 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1027 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1028 //! k or end() if that element does not exist.
1030 //! <b>Complexity</b>: Logarithmic.
1032 //! <b>Throws</b>: Nothing.
1033 iterator
find(const_reference value
)
1034 { return this->find(value
, priv_comp()); }
1036 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1037 //! k or end() if that element does not exist.
1039 //! <b>Complexity</b>: Logarithmic.
1041 //! <b>Throws</b>: Nothing.
1042 template<class KeyType
, class KeyValueCompare
>
1043 iterator
find(const KeyType
&key
, KeyValueCompare comp
)
1045 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
1046 key_node_comp(comp
, this);
1048 (node_algorithms::find(const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1051 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1052 //! k or end() if that element does not exist.
1054 //! <b>Complexity</b>: Logarithmic.
1056 //! <b>Throws</b>: Nothing.
1057 const_iterator
find(const_reference value
) const
1058 { return this->find(value
, priv_comp()); }
1060 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1061 //! k or end() if that element does not exist.
1063 //! <b>Complexity</b>: Logarithmic.
1065 //! <b>Throws</b>: Nothing.
1066 template<class KeyType
, class KeyValueCompare
>
1067 const_iterator
find(const KeyType
&key
, KeyValueCompare comp
) const
1069 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
1070 key_node_comp(comp
, this);
1071 return const_iterator
1072 (node_algorithms::find(const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1075 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1076 //! an empty range that indicates the position where those elements would be
1077 //! if they there is no elements with key k.
1079 //! <b>Complexity</b>: Logarithmic.
1081 //! <b>Throws</b>: Nothing.
1082 std::pair
<iterator
,iterator
> equal_range(const_reference value
)
1083 { return this->equal_range(value
, priv_comp()); }
1085 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1086 //! an empty range that indicates the position where those elements would be
1087 //! if they there is no elements with key k.
1089 //! <b>Complexity</b>: Logarithmic.
1091 //! <b>Throws</b>: Nothing.
1092 template<class KeyType
, class KeyValueCompare
>
1093 std::pair
<iterator
,iterator
> equal_range(const KeyType
&key
, KeyValueCompare comp
)
1095 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
1096 key_node_comp(comp
, this);
1097 std::pair
<node_ptr
, node_ptr
> ret
1098 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key
, key_node_comp
));
1099 return std::pair
<iterator
, iterator
>(iterator(ret
.first
, this), iterator(ret
.second
, this));
1102 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1103 //! an empty range that indicates the position where those elements would be
1104 //! if they there is no elements with key k.
1106 //! <b>Complexity</b>: Logarithmic.
1108 //! <b>Throws</b>: Nothing.
1109 std::pair
<const_iterator
, const_iterator
>
1110 equal_range(const_reference value
) const
1111 { return this->equal_range(value
, priv_comp()); }
1113 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1114 //! an empty range that indicates the position where those elements would be
1115 //! if they there is no elements with key k.
1117 //! <b>Complexity</b>: Logarithmic.
1119 //! <b>Throws</b>: Nothing.
1120 template<class KeyType
, class KeyValueCompare
>
1121 std::pair
<const_iterator
, const_iterator
>
1122 equal_range(const KeyType
&key
, KeyValueCompare comp
) const
1124 detail::key_nodeptr_comp
<KeyValueCompare
, avltree_impl
>
1125 key_node_comp(comp
, this);
1126 std::pair
<node_ptr
, node_ptr
> ret
1127 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key
, key_node_comp
));
1128 return std::pair
<const_iterator
, const_iterator
>(const_iterator(ret
.first
, this), const_iterator(ret
.second
, this));
1131 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1132 //! Cloner should yield to nodes equivalent to the original nodes.
1134 //! <b>Effects</b>: Erases all the elements from *this
1135 //! calling Disposer::operator()(pointer), clones all the
1136 //! elements from src calling Cloner::operator()(const_reference )
1137 //! and inserts them on *this. Copies the predicate from the source container.
1139 //! If cloner throws, all cloned elements are unlinked and disposed
1140 //! calling Disposer::operator()(pointer).
1142 //! <b>Complexity</b>: Linear to erased plus inserted elements.
1144 //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
1145 template <class Cloner
, class Disposer
>
1146 void clone_from(const avltree_impl
&src
, Cloner cloner
, Disposer disposer
)
1148 this->clear_and_dispose(disposer
);
1150 detail::exception_disposer
<avltree_impl
, Disposer
>
1151 rollback(*this, disposer
);
1152 node_algorithms::clone
1153 (const_node_ptr(&src
.priv_header())
1154 ,node_ptr(&this->priv_header())
1155 ,detail::node_cloner
<Cloner
, avltree_impl
>(cloner
, this)
1156 ,detail::node_disposer
<Disposer
, avltree_impl
>(disposer
, this));
1157 this->priv_size_traits().set_size(src
.priv_size_traits().get_size());
1158 this->priv_comp() = src
.priv_comp();
1163 //! <b>Effects</b>: Unlinks the leftmost node from the tree.
1165 //! <b>Complexity</b>: Average complexity is constant time.
1167 //! <b>Throws</b>: Nothing.
1169 //! <b>Notes</b>: This function breaks the tree and the tree can
1170 //! only be used for more unlink_leftmost_without_rebalance calls.
1171 //! This function is normally used to achieve a step by step
1172 //! controlled destruction of the tree.
1173 pointer
unlink_leftmost_without_rebalance()
1175 node_ptr
to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance
1176 (node_ptr(&priv_header())));
1179 this->priv_size_traits().decrement();
1180 if(safemode_or_autounlink
)//If this is commented does not work with normal_link
1181 node_algorithms::init(to_be_disposed
);
1182 return get_real_value_traits().to_value_ptr(to_be_disposed
);
1185 //! <b>Requires</b>: replace_this must be a valid iterator of *this
1186 //! and with_this must not be inserted in any tree.
1188 //! <b>Effects</b>: Replaces replace_this in its position in the
1189 //! tree with with_this. The tree does not need to be rebalanced.
1191 //! <b>Complexity</b>: Constant.
1193 //! <b>Throws</b>: Nothing.
1195 //! <b>Note</b>: This function will break container ordering invariants if
1196 //! with_this is not equivalent to *replace_this according to the
1197 //! ordering rules. This function is faster than erasing and inserting
1198 //! the node, since no rebalancing or comparison is needed.
1199 void replace_node(iterator replace_this
, reference with_this
)
1201 node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this
)
1202 , node_ptr(&priv_header())
1203 , get_real_value_traits().to_node_ptr(with_this
));
1206 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1207 //! appropriate type. Otherwise the behavior is undefined.
1209 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1210 //! that points to the value
1212 //! <b>Complexity</b>: Constant.
1214 //! <b>Throws</b>: Nothing.
1216 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1218 static iterator
s_iterator_to(reference value
)
1220 BOOST_STATIC_ASSERT((!stateful_value_traits
));
1221 return iterator (value_traits::to_node_ptr(value
), 0);
1224 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1225 //! appropriate type. Otherwise the behavior is undefined.
1227 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1228 //! set that points to the value
1230 //! <b>Complexity</b>: Constant.
1232 //! <b>Throws</b>: Nothing.
1234 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1236 static const_iterator
s_iterator_to(const_reference value
)
1238 BOOST_STATIC_ASSERT((!stateful_value_traits
));
1239 return const_iterator (value_traits::to_node_ptr(const_cast<reference
> (value
)), 0);
1242 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1243 //! appropriate type. Otherwise the behavior is undefined.
1245 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1246 //! that points to the value
1248 //! <b>Complexity</b>: Constant.
1250 //! <b>Throws</b>: Nothing.
1251 iterator
iterator_to(reference value
)
1252 { return iterator (value_traits::to_node_ptr(value
), this); }
1254 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1255 //! appropriate type. Otherwise the behavior is undefined.
1257 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1258 //! set that points to the value
1260 //! <b>Complexity</b>: Constant.
1262 //! <b>Throws</b>: Nothing.
1263 const_iterator
iterator_to(const_reference value
) const
1264 { return const_iterator (value_traits::to_node_ptr(const_cast<reference
> (value
)), this); }
1266 //! <b>Requires</b>: value shall not be in a tree.
1268 //! <b>Effects</b>: init_node puts the hook of a value in a well-known default
1271 //! <b>Throws</b>: Nothing.
1273 //! <b>Complexity</b>: Constant time.
1275 //! <b>Note</b>: This function puts the hook in the well-known default state
1276 //! used by auto_unlink and safe hooks.
1277 static void init_node(reference value
)
1278 { node_algorithms::init(value_traits::to_node_ptr(value
)); }
1281 //! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
1282 //! if x is not in such a tree.
1284 //! <b>Throws</b>: Nothing.
1286 //! <b>Complexity</b>: Constant time.
1288 //! <b>Note</b>: This static function is only usable with the "safe mode"
1289 //! hook and non-constant time size lists. Otherwise, the user must use
1290 //! the non-static "erase(reference )" member. If the user calls
1291 //! this function with a non "safe mode" or constant time size list
1292 //! a compilation error will be issued.
1294 static void remove_node(T& value)
1296 //This function is only usable for safe mode hooks and non-constant
1298 //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
1299 BOOST_STATIC_ASSERT((!constant_time_size));
1300 BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
1301 node_ptr to_remove(value_traits::to_node_ptr(value));
1302 node_algorithms::unlink_and_rebalance(to_remove);
1303 if(safemode_or_autounlink)
1304 node_algorithms::init(to_remove);
1311 template<class Disposer
>
1312 iterator
private_erase(const_iterator b
, const_iterator e
, size_type
&n
, Disposer disposer
)
1314 for(n
= 0; b
!= e
; ++n
)
1315 this->erase_and_dispose(b
++, disposer
);
1319 iterator
private_erase(const_iterator b
, const_iterator e
, size_type
&n
)
1321 for(n
= 0; b
!= e
; ++n
)
1328 static avltree_impl
&priv_container_from_end_iterator(const const_iterator
&end_iterator
)
1330 header_plus_size
*r
= detail::parent_from_member
<header_plus_size
, node
>
1331 ( detail::get_pointer(end_iterator
.pointed_node()), &header_plus_size::header_
);
1332 node_plus_pred_t
*n
= detail::parent_from_member
1333 <node_plus_pred_t
, header_plus_size
>(r
, &node_plus_pred_t::header_plus_size_
);
1334 data_t
*d
= detail::parent_from_member
<data_t
, node_plus_pred_t
>(n
, &data_t::node_plus_pred_
);
1335 avltree_impl
*avl
= detail::parent_from_member
<avltree_impl
, data_t
>(d
, &avltree_impl::data_
);
1339 static avltree_impl
&priv_container_from_iterator(const const_iterator
&it
)
1340 { return priv_container_from_end_iterator(it
.end_iterator_from_it()); }
1343 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1344 template<class T
, class ...Options
>
1346 template<class Config
>
1348 inline bool operator<
1349 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1350 (const avltree_impl
<T
, Options
...> &x
, const avltree_impl
<T
, Options
...> &y
)
1352 (const avltree_impl
<Config
> &x
, const avltree_impl
<Config
> &y
)
1354 { return std::lexicographical_compare(x
.begin(), x
.end(), y
.begin(), y
.end()); }
1356 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1357 template<class T
, class ...Options
>
1359 template<class Config
>
1362 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1363 (const avltree_impl
<T
, Options
...> &x
, const avltree_impl
<T
, Options
...> &y
)
1365 (const avltree_impl
<Config
> &x
, const avltree_impl
<Config
> &y
)
1368 typedef avltree_impl
<Config
> tree_type
;
1369 typedef typename
tree_type::const_iterator const_iterator
;
1371 if(tree_type::constant_time_size
&& x
.size() != y
.size()){
1374 const_iterator end1
= x
.end();
1375 const_iterator i1
= x
.begin();
1376 const_iterator i2
= y
.begin();
1377 if(tree_type::constant_time_size
){
1378 while (i1
!= end1
&& *i1
== *i2
) {
1385 const_iterator end2
= y
.end();
1386 while (i1
!= end1
&& i2
!= end2
&& *i1
== *i2
) {
1390 return i1
== end1
&& i2
== end2
;
1394 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1395 template<class T
, class ...Options
>
1397 template<class Config
>
1399 inline bool operator!=
1400 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1401 (const avltree_impl
<T
, Options
...> &x
, const avltree_impl
<T
, Options
...> &y
)
1403 (const avltree_impl
<Config
> &x
, const avltree_impl
<Config
> &y
)
1405 { return !(x
== y
); }
1407 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1408 template<class T
, class ...Options
>
1410 template<class Config
>
1412 inline bool operator>
1413 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1414 (const avltree_impl
<T
, Options
...> &x
, const avltree_impl
<T
, Options
...> &y
)
1416 (const avltree_impl
<Config
> &x
, const avltree_impl
<Config
> &y
)
1420 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1421 template<class T
, class ...Options
>
1423 template<class Config
>
1425 inline bool operator<=
1426 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1427 (const avltree_impl
<T
, Options
...> &x
, const avltree_impl
<T
, Options
...> &y
)
1429 (const avltree_impl
<Config
> &x
, const avltree_impl
<Config
> &y
)
1431 { return !(y
< x
); }
1433 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1434 template<class T
, class ...Options
>
1436 template<class Config
>
1438 inline bool operator>=
1439 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1440 (const avltree_impl
<T
, Options
...> &x
, const avltree_impl
<T
, Options
...> &y
)
1442 (const avltree_impl
<Config
> &x
, const avltree_impl
<Config
> &y
)
1444 { return !(x
< y
); }
1446 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1447 template<class T
, class ...Options
>
1449 template<class Config
>
1452 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1453 (avltree_impl
<T
, Options
...> &x
, avltree_impl
<T
, Options
...> &y
)
1455 (avltree_impl
<Config
> &x
, avltree_impl
<Config
> &y
)
1461 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1462 template<class T
, class O1
= none
, class O2
= none
1463 , class O3
= none
, class O4
= none
1466 template<class T
, class ...Options
>
1468 struct make_avltree_opt
1470 typedef typename pack_options
1471 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1472 < avl_set_defaults
<T
>, O1
, O2
, O3
, O4
>
1474 < avl_set_defaults
<T
>, Options
...>
1476 ::type packed_options
;
1478 typedef typename
detail::get_value_traits
1479 <T
, typename
packed_options::value_traits
>::type value_traits
;
1483 , typename
packed_options::compare
1484 , typename
packed_options::size_type
1485 , packed_options::constant_time_size
1490 //! Helper metafunction to define a \c avltree that yields to the same type when the
1491 //! same options (either explicitly or implicitly) are used.
1492 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1493 template<class T
, class ...Options
>
1495 template<class T
, class O1
= none
, class O2
= none
1496 , class O3
= none
, class O4
= none
>
1501 typedef avltree_impl
1502 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1503 < typename make_avltree_opt
<T
, O1
, O2
, O3
, O4
>::type
1505 < typename make_avltree_opt
<T
, Options
...>::type
1507 > implementation_defined
;
1509 typedef implementation_defined type
;
1512 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1514 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1515 template<class T
, class O1
, class O2
, class O3
, class O4
>
1517 template<class T
, class ...Options
>
1520 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1521 : public make_avltree
<T
, O1
, O2
, O3
, O4
>::type
1523 : public make_avltree
<T
, Options
...>::type
1526 typedef typename make_avltree
1527 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1535 typedef typename
Base::value_compare value_compare
;
1536 typedef typename
Base::value_traits value_traits
;
1537 typedef typename
Base::real_value_traits real_value_traits
;
1538 typedef typename
Base::iterator iterator
;
1539 typedef typename
Base::const_iterator const_iterator
;
1541 //Assert if passed value traits are compatible with the type
1542 BOOST_STATIC_ASSERT((detail::is_same
<typename
real_value_traits::value_type
, T
>::value
));
1544 avltree( const value_compare
&cmp
= value_compare()
1545 , const value_traits
&v_traits
= value_traits())
1546 : Base(cmp
, v_traits
)
1549 template<class Iterator
>
1550 avltree( bool unique
, Iterator b
, Iterator e
1551 , const value_compare
&cmp
= value_compare()
1552 , const value_traits
&v_traits
= value_traits())
1553 : Base(unique
, b
, e
, cmp
, v_traits
)
1556 static avltree
&container_from_end_iterator(iterator end_iterator
)
1557 { return static_cast<avltree
&>(Base::container_from_end_iterator(end_iterator
)); }
1559 static const avltree
&container_from_end_iterator(const_iterator end_iterator
)
1560 { return static_cast<const avltree
&>(Base::container_from_end_iterator(end_iterator
)); }
1562 static avltree
&container_from_iterator(iterator it
)
1563 { return static_cast<avltree
&>(Base::container_from_iterator(it
)); }
1565 static const avltree
&container_from_iterator(const_iterator it
)
1566 { return static_cast<const avltree
&>(Base::container_from_iterator(it
)); }
1572 } //namespace intrusive
1575 #include <boost/intrusive/detail/config_end.hpp>
1577 #endif //BOOST_INTRUSIVE_AVLTREE_HPP