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_SPLAYTREE_HPP
13 #define BOOST_INTRUSIVE_SPLAYTREE_HPP
15 #include <boost/intrusive/detail/config_begin.hpp>
21 #include <boost/intrusive/detail/assert.hpp>
22 #include <boost/static_assert.hpp>
23 #include <boost/intrusive/intrusive_fwd.hpp>
24 #include <boost/intrusive/detail/pointer_to_other.hpp>
25 #include <boost/intrusive/splay_set_hook.hpp>
26 #include <boost/intrusive/detail/tree_node.hpp>
27 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
28 #include <boost/intrusive/detail/clear_on_destructor_base.hpp>
29 #include <boost/intrusive/detail/mpl.hpp>
30 #include <boost/intrusive/options.hpp>
31 #include <boost/intrusive/splaytree_algorithms.hpp>
32 #include <boost/intrusive/link_mode.hpp>
40 template <class ValueTraits
, class Compare
, class SizeType
, bool ConstantTimeSize
>
43 typedef ValueTraits value_traits
;
44 typedef Compare compare
;
45 typedef SizeType size_type
;
46 static const bool constant_time_size
= ConstantTimeSize
;
50 struct splay_set_defaults
53 , base_hook
<detail::default_splay_set_hook
>
54 , constant_time_size
<true>
55 , size_type
<std::size_t>
56 , compare
<std::less
<T
> >
62 //! The class template splaytree is an intrusive splay tree container that
63 //! is used to construct intrusive splay_set and splay_multiset containers. The no-throw
64 //! guarantee holds only, if the value_compare object
67 //! The template parameter \c T is the type to be managed by the container.
68 //! The user can specify additional options and if no options are provided
69 //! default options are used.
71 //! The container supports the following options:
72 //! \c base_hook<>/member_hook<>/value_traits<>,
73 //! \c constant_time_size<>, \c size_type<> and
75 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
76 template<class T
, class ...Options
>
78 template<class Config
>
81 : private detail::clear_on_destructor_base
<splaytree_impl
<Config
> >
83 template<class C
> friend class detail::clear_on_destructor_base
;
85 typedef typename
Config::value_traits value_traits
;
87 static const bool external_value_traits
=
88 detail::external_value_traits_is_true
<value_traits
>::value
;
89 typedef typename
detail::eval_if_c
90 < external_value_traits
91 , detail::eval_value_traits
<value_traits
>
92 , detail::identity
<value_traits
>
93 >::type real_value_traits
;
95 typedef typename
real_value_traits::pointer pointer
;
96 typedef typename
real_value_traits::const_pointer const_pointer
;
97 typedef typename
std::iterator_traits
<pointer
>::value_type value_type
;
98 typedef value_type key_type
;
99 typedef typename
std::iterator_traits
<pointer
>::reference reference
;
100 typedef typename
std::iterator_traits
<const_pointer
>::reference const_reference
;
101 typedef typename
std::iterator_traits
<pointer
>::difference_type difference_type
;
102 typedef typename
Config::size_type size_type
;
103 typedef typename
Config::compare value_compare
;
104 typedef value_compare key_compare
;
105 typedef tree_iterator
<splaytree_impl
, false> iterator
;
106 typedef tree_iterator
<splaytree_impl
, true> const_iterator
;
107 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
108 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
109 typedef typename
real_value_traits::node_traits node_traits
;
110 typedef typename
node_traits::node node
;
111 typedef typename
boost::pointer_to_other
112 <pointer
, node
>::type node_ptr
;
113 typedef typename
boost::pointer_to_other
114 <node_ptr
, const node
>::type const_node_ptr
;
115 typedef splaytree_algorithms
<node_traits
> node_algorithms
;
117 static const bool constant_time_size
= Config::constant_time_size
;
118 static const bool stateful_value_traits
= detail::store_cont_ptr_on_it
<splaytree_impl
>::value
;
122 typedef detail::size_holder
<constant_time_size
, size_type
> size_traits
;
125 splaytree_impl (const splaytree_impl
&);
126 splaytree_impl
operator =(const splaytree_impl
&);
128 enum { safemode_or_autounlink
=
129 (int)real_value_traits::link_mode
== (int)auto_unlink
||
130 (int)real_value_traits::link_mode
== (int)safe_link
};
132 //Constant-time size is incompatible with auto-unlink hooks!
133 BOOST_STATIC_ASSERT(!(constant_time_size
&& ((int)real_value_traits::link_mode
== (int)auto_unlink
)));
135 struct header_plus_size
: public size_traits
138 struct node_plus_pred_t
: public detail::ebo_functor_holder
<value_compare
>
140 node_plus_pred_t(const value_compare
&comp
)
141 : detail::ebo_functor_holder
<value_compare
>(comp
)
143 header_plus_size header_plus_size_
;
146 struct data_t
: public splaytree_impl::value_traits
148 typedef typename
splaytree_impl::value_traits value_traits
;
149 data_t(const value_compare
& comp
, const value_traits
&val_traits
)
150 : value_traits(val_traits
), node_plus_pred_(comp
)
152 node_plus_pred_t node_plus_pred_
;
155 const value_compare
&priv_comp() const
156 { return data_
.node_plus_pred_
.get(); }
158 value_compare
&priv_comp()
159 { return data_
.node_plus_pred_
.get(); }
161 const node
&priv_header() const
162 { return data_
.node_plus_pred_
.header_plus_size_
.header_
; }
165 { return data_
.node_plus_pred_
.header_plus_size_
.header_
; }
167 static node_ptr
uncast(const_node_ptr ptr
)
169 return node_ptr(const_cast<node
*>(detail::get_pointer(ptr
)));
172 size_traits
&priv_size_traits()
173 { return data_
.node_plus_pred_
.header_plus_size_
; }
175 const size_traits
&priv_size_traits() const
176 { return data_
.node_plus_pred_
.header_plus_size_
; }
178 const real_value_traits
&get_real_value_traits(detail::bool_
<false>) const
181 const real_value_traits
&get_real_value_traits(detail::bool_
<true>) const
182 { return data_
.get_value_traits(*this); }
184 real_value_traits
&get_real_value_traits(detail::bool_
<false>)
187 real_value_traits
&get_real_value_traits(detail::bool_
<true>)
188 { return data_
.get_value_traits(*this); }
194 const real_value_traits
&get_real_value_traits() const
195 { return this->get_real_value_traits(detail::bool_
<external_value_traits
>()); }
197 real_value_traits
&get_real_value_traits()
198 { return this->get_real_value_traits(detail::bool_
<external_value_traits
>()); }
200 typedef typename
node_algorithms::insert_commit_data insert_commit_data
;
202 //! <b>Effects</b>: Constructs an empty tree.
204 //! <b>Complexity</b>: Constant.
206 //! <b>Throws</b>: If value_traits::node_traits::node
207 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
208 //! or the copy constructorof the value_compare object throws. Basic guarantee.
209 splaytree_impl( const value_compare
&cmp
= value_compare()
210 , const value_traits
&v_traits
= value_traits())
211 : data_(cmp
, v_traits
)
213 node_algorithms::init_header(&priv_header());
214 this->priv_size_traits().set_size(size_type(0));
217 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
218 //! cmp must be a comparison function that induces a strict weak ordering.
220 //! <b>Effects</b>: Constructs an empty tree and inserts elements from
223 //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using
224 //! comp and otherwise amortized N * log N, where N is the distance between first and last.
226 //! <b>Throws</b>: If value_traits::node_traits::node
227 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
228 //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee.
229 template<class Iterator
>
230 splaytree_impl ( bool unique
, Iterator b
, Iterator e
231 , const value_compare
&cmp
= value_compare()
232 , const value_traits
&v_traits
= value_traits())
233 : data_(cmp
, v_traits
)
235 node_algorithms::init_header(&priv_header());
236 this->priv_size_traits().set_size(size_type(0));
238 this->insert_unique(b
, e
);
240 this->insert_equal(b
, e
);
243 //! <b>Effects</b>: Detaches all elements from this. The objects in the set
244 //! are not deleted (i.e. no destructors are called), but the nodes according to
245 //! the value_traits template parameter are reinitialized and thus can be reused.
247 //! <b>Complexity</b>: Linear to the number of elements on the container.
248 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
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_algorithms::begin_node(&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_algorithms::begin_node(&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 splaytree associated to the end iterator
361 //! <b>Throws</b>: Nothing.
363 //! <b>Complexity</b>: Constant.
364 static splaytree_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 splaytree associated to the end iterator
372 //! <b>Throws</b>: Nothing.
374 //! <b>Complexity</b>: Constant.
375 static const splaytree_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 splaytree_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 splaytree_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 this->cbegin() == this->cend(); }
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();
428 return (size_type
)node_algorithms::size(const_node_ptr(&priv_header()));
432 //! <b>Effects</b>: Swaps the contents of two splaytrees.
434 //! <b>Complexity</b>: Constant.
436 //! <b>Throws</b>: If the comparison functor's swap call throws.
437 void swap(splaytree_impl
& other
)
441 swap(priv_comp(), priv_comp());
443 node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other
.priv_header()));
444 if(constant_time_size
){
445 size_type backup
= this->priv_size_traits().get_size();
446 this->priv_size_traits().set_size(other
.priv_size_traits().get_size());
447 other
.priv_size_traits().set_size(backup
);
451 //! <b>Requires</b>: value must be an lvalue
453 //! <b>Effects</b>: Inserts value into the tree before the lower bound.
455 //! <b>Complexity</b>: Average complexity for insert element is amortized
458 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
460 //! <b>Note</b>: Does not affect the validity of iterators and references.
461 //! No copy-constructors are called.
462 iterator
insert_equal(reference value
)
464 detail::key_nodeptr_comp
<value_compare
, splaytree_impl
>
465 key_node_comp(priv_comp(), this);
466 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
467 if(safemode_or_autounlink
)
468 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
469 this->priv_size_traits().increment();
470 return iterator(node_algorithms::insert_equal_lower_bound
471 (node_ptr(&priv_header()), to_insert
, key_node_comp
), this);
474 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
475 //! a valid iterator.
477 //! <b>Effects</b>: Inserts x into the tree, using "hint" as a hint to
478 //! where it will be inserted. If "hint" is the upper_bound
479 //! the insertion takes constant time (two comparisons in the worst case)
481 //! <b>Complexity</b>: Amortized logarithmic in general, but it is amortized
482 //! constant time if t is inserted immediately before hint.
484 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
486 //! <b>Note</b>: Does not affect the validity of iterators and references.
487 //! No copy-constructors are called.
488 iterator
insert_equal(const_iterator hint
, reference value
)
490 detail::key_nodeptr_comp
<value_compare
, splaytree_impl
>
491 key_node_comp(priv_comp(), this);
492 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
493 if(safemode_or_autounlink
)
494 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
495 this->priv_size_traits().increment();
496 return iterator(node_algorithms::insert_equal
497 (node_ptr(&priv_header()), hint
.pointed_node(), to_insert
, key_node_comp
), this);
500 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
501 //! of type value_type.
503 //! <b>Effects</b>: Inserts a each element of a range into the tree
504 //! before the upper bound of the key of each element.
506 //! <b>Complexity</b>: Insert range is in general amortized O(N * log(N)), where N is the
507 //! size of the range. However, it is linear in N if the range is already sorted
510 //! <b>Throws</b>: Nothing.
512 //! <b>Note</b>: Does not affect the validity of iterators and references.
513 //! No copy-constructors are called.
514 template<class Iterator
>
515 void insert_equal(Iterator b
, Iterator e
)
518 iterator
end(this->end());
520 this->insert_equal(end
, *b
);
524 //! <b>Requires</b>: value must be an lvalue
526 //! <b>Effects</b>: Inserts value into the tree if the value
527 //! is not already present.
529 //! <b>Complexity</b>: Amortized logarithmic.
531 //! <b>Throws</b>: Nothing.
533 //! <b>Note</b>: Does not affect the validity of iterators and references.
534 //! No copy-constructors are called.
535 std::pair
<iterator
, bool> insert_unique(reference value
)
537 insert_commit_data commit_data
;
538 std::pair
<iterator
, bool> ret
= insert_unique_check(value
, priv_comp(), commit_data
);
541 return std::pair
<iterator
, bool> (insert_unique_commit(value
, commit_data
), true);
544 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
547 //! <b>Effects</b>: Tries to insert x into the tree, using "hint" as a hint
548 //! to where it will be inserted.
550 //! <b>Complexity</b>: Amortized logarithmic in general, but it is amortized
551 //! constant time (two comparisons in the worst case)
552 //! if t is inserted immediately before hint.
554 //! <b>Throws</b>: Nothing.
556 //! <b>Note</b>: Does not affect the validity of iterators and references.
557 //! No copy-constructors are called.
558 iterator
insert_unique(const_iterator hint
, reference value
)
560 insert_commit_data commit_data
;
561 std::pair
<iterator
, bool> ret
= insert_unique_check(hint
, value
, priv_comp(), commit_data
);
564 return insert_unique_commit(value
, commit_data
);
567 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
568 //! of type value_type.
570 //! <b>Effects</b>: Tries to insert each element of a range into the tree.
572 //! <b>Complexity</b>: Insert range is in general amortized O(N * log(N)), where N is the
573 //! size of the range. However, it is linear in N if the range is already sorted
576 //! <b>Throws</b>: Nothing.
578 //! <b>Note</b>: Does not affect the validity of iterators and references.
579 //! No copy-constructors are called.
580 template<class Iterator
>
581 void insert_unique(Iterator b
, Iterator e
)
584 this->insert_unique(*b
);
587 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
588 //! the same strict weak ordering as value_compare. The difference is that
589 //! key_value_comp compares an arbitrary key with the contained values.
591 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
592 //! a user provided key instead of the value itself.
594 //! <b>Returns</b>: If there is an equivalent value
595 //! returns a pair containing an iterator to the already present value
596 //! and false. If the value can be inserted returns true in the returned
597 //! pair boolean and fills "commit_data" that is meant to be used with
598 //! the "insert_commit" function.
600 //! <b>Complexity</b>: Average complexity is at most logarithmic.
602 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
604 //! <b>Notes</b>: This function is used to improve performance when constructing
605 //! a value_type is expensive: if there is an equivalent value
606 //! the constructed object must be discarded. Many times, the part of the
607 //! node that is used to impose the order is much cheaper to construct
608 //! than the value_type and this function offers the possibility to use that
609 //! part to check if the insertion will be successful.
611 //! If the check is successful, the user can construct the value_type and use
612 //! "insert_commit" to insert the object in constant-time. This gives a total
613 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
615 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
616 //! objects are inserted or erased from the container.
617 template<class KeyType
, class KeyValueCompare
>
618 std::pair
<iterator
, bool> insert_unique_check
619 (const KeyType
&key
, KeyValueCompare key_value_comp
, insert_commit_data
&commit_data
)
621 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
622 comp(key_value_comp
, this);
623 std::pair
<node_ptr
, bool> ret
=
624 (node_algorithms::insert_unique_check
625 (node_ptr(&priv_header()), key
, comp
, commit_data
));
626 return std::pair
<iterator
, bool>(iterator(ret
.first
, this), ret
.second
);
629 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
630 //! the same strict weak ordering as value_compare. The difference is that
631 //! key_value_comp compares an arbitrary key with the contained values.
633 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
634 //! a user provided key instead of the value itself, using "hint"
635 //! as a hint to where it will be inserted.
637 //! <b>Returns</b>: If there is an equivalent value
638 //! returns a pair containing an iterator to the already present value
639 //! and false. If the value can be inserted returns true in the returned
640 //! pair boolean and fills "commit_data" that is meant to be used with
641 //! the "insert_commit" function.
643 //! <b>Complexity</b>: Logarithmic in general, but it's amortized
644 //! constant time if t is inserted immediately before hint.
646 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
648 //! <b>Notes</b>: This function is used to improve performance when constructing
649 //! a value_type is expensive: if there is an equivalent value
650 //! the constructed object must be discarded. Many times, the part of the
651 //! constructing that is used to impose the order is much cheaper to construct
652 //! than the value_type and this function offers the possibility to use that key
653 //! to check if the insertion will be successful.
655 //! If the check is successful, the user can construct the value_type and use
656 //! "insert_commit" to insert the object in constant-time. This can give a total
657 //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)).
659 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
660 //! objects are inserted or erased from the container.
661 template<class KeyType
, class KeyValueCompare
>
662 std::pair
<iterator
, bool> insert_unique_check
663 (const_iterator hint
, const KeyType
&key
664 ,KeyValueCompare key_value_comp
, insert_commit_data
&commit_data
)
666 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
667 comp(key_value_comp
, this);
668 std::pair
<node_ptr
, bool> ret
=
669 node_algorithms::insert_unique_check
670 (node_ptr(&priv_header()), hint
.pointed_node(), key
, comp
, commit_data
);
671 return std::pair
<iterator
, bool>(iterator(ret
.first
, this), ret
.second
);
674 //! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
675 //! must have been obtained from a previous call to "insert_check".
676 //! No objects should have been inserted or erased from the container between
677 //! the "insert_check" that filled "commit_data" and the call to "insert_commit".
679 //! <b>Effects</b>: Inserts the value in the avl_set using the information obtained
680 //! from the "commit_data" that a previous "insert_check" filled.
682 //! <b>Returns</b>: An iterator to the newly inserted object.
684 //! <b>Complexity</b>: Constant time.
686 //! <b>Throws</b>: Nothing.
688 //! <b>Notes</b>: This function has only sense if a "insert_check" has been
689 //! previously executed to fill "commit_data". No value should be inserted or
690 //! erased between the "insert_check" and "insert_commit" calls.
691 iterator
insert_unique_commit(reference value
, const insert_commit_data
&commit_data
)
693 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
694 if(safemode_or_autounlink
)
695 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
696 this->priv_size_traits().increment();
697 node_algorithms::insert_unique_commit
698 (node_ptr(&priv_header()), to_insert
, commit_data
);
699 return iterator(to_insert
, this);
702 //! <b>Effects</b>: Erases the element pointed to by pos.
704 //! <b>Complexity</b>: Average complexity for erase element is constant time.
706 //! <b>Throws</b>: Nothing.
708 //! <b>Note</b>: Invalidates the iterators (but not the references)
709 //! to the erased elements. No destructors are called.
710 iterator
erase(const_iterator i
)
712 const_iterator
ret(i
);
714 node_ptr
to_erase(i
.pointed_node());
715 if(safemode_or_autounlink
)
716 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase
));
717 node_algorithms::erase(&priv_header(), to_erase
);
718 this->priv_size_traits().decrement();
719 if(safemode_or_autounlink
)
720 node_algorithms::init(to_erase
);
721 return ret
.unconst();
724 //! <b>Effects</b>: Erases the range pointed to by b end e.
726 //! <b>Complexity</b>: Average complexity for erase range is amortized
727 //! O(log(size() + N)), where N is the number of elements in the range.
729 //! <b>Throws</b>: Nothing.
731 //! <b>Note</b>: Invalidates the iterators (but not the references)
732 //! to the erased elements. No destructors are called.
733 iterator
erase(const_iterator b
, const_iterator e
)
734 { size_type n
; return private_erase(b
, e
, n
); }
736 //! <b>Effects</b>: Erases all the elements with the given value.
738 //! <b>Returns</b>: The number of erased elements.
740 //! <b>Complexity</b>: Amortized O(log(size() + N).
742 //! <b>Throws</b>: Nothing.
744 //! <b>Note</b>: Invalidates the iterators (but not the references)
745 //! to the erased elements. No destructors are called.
746 size_type
erase(const_reference value
)
747 { return this->erase(value
, priv_comp()); }
749 //! <b>Effects</b>: Erases all the elements with the given key.
750 //! according to the comparison functor "comp".
752 //! <b>Returns</b>: The number of erased elements.
754 //! <b>Complexity</b>: Amortized O(log(size() + N).
756 //! <b>Throws</b>: Nothing.
758 //! <b>Note</b>: Invalidates the iterators (but not the references)
759 //! to the erased elements. No destructors are called.
760 template<class KeyType
, class KeyValueCompare
>
761 size_type
erase(const KeyType
& key
, KeyValueCompare comp
763 , typename
detail::enable_if_c
<!detail::is_convertible
<KeyValueCompare
, const_iterator
>::value
>::type
* = 0
767 std::pair
<iterator
,iterator
> p
= this->equal_range(key
, comp
);
769 private_erase(p
.first
, p
.second
, n
);
773 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
775 //! <b>Effects</b>: Erases the element pointed to by pos.
776 //! Disposer::operator()(pointer) is called for the removed element.
778 //! <b>Complexity</b>: Average complexity for erase element is constant time.
780 //! <b>Throws</b>: Nothing.
782 //! <b>Note</b>: Invalidates the iterators
783 //! to the erased elements.
784 template<class Disposer
>
785 iterator
erase_and_dispose(const_iterator i
, Disposer disposer
)
787 node_ptr
to_erase(i
.pointed_node());
788 iterator
ret(this->erase(i
));
789 disposer(get_real_value_traits().to_value_ptr(to_erase
));
793 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
794 template<class Disposer
>
795 iterator
erase_and_dispose(iterator i
, Disposer disposer
)
796 { return this->erase_and_dispose(const_iterator(i
), disposer
); }
799 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
801 //! <b>Effects</b>: Erases the range pointed to by b end e.
802 //! Disposer::operator()(pointer) is called for the removed elements.
804 //! <b>Complexity</b>: Average complexity for erase range is amortized
805 //! O(log(size() + N)), where N is the number of elements in the range.
807 //! <b>Throws</b>: Nothing.
809 //! <b>Note</b>: Invalidates the iterators
810 //! to the erased elements.
811 template<class Disposer
>
812 iterator
erase_and_dispose(const_iterator b
, const_iterator e
, Disposer disposer
)
813 { size_type n
; return private_erase(b
, e
, n
, disposer
); }
815 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
817 //! <b>Effects</b>: Erases all the elements with the given value.
818 //! Disposer::operator()(pointer) is called for the removed elements.
820 //! <b>Returns</b>: The number of erased elements.
822 //! <b>Complexity</b>: Amortized O(log(size() + N).
824 //! <b>Throws</b>: Nothing.
826 //! <b>Note</b>: Invalidates the iterators (but not the references)
827 //! to the erased elements. No destructors are called.
828 template<class Disposer
>
829 size_type
erase_and_dispose(const_reference value
, Disposer disposer
)
831 std::pair
<iterator
,iterator
> p
= this->equal_range(value
);
833 private_erase(p
.first
, p
.second
, n
, disposer
);
837 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
839 //! <b>Effects</b>: Erases all the elements with the given key.
840 //! according to the comparison functor "comp".
841 //! Disposer::operator()(pointer) is called for the removed elements.
843 //! <b>Returns</b>: The number of erased elements.
845 //! <b>Complexity</b>: Amortized O(log(size() + N).
847 //! <b>Throws</b>: Nothing.
849 //! <b>Note</b>: Invalidates the iterators
850 //! to the erased elements.
851 template<class KeyType
, class KeyValueCompare
, class Disposer
>
852 size_type
erase_and_dispose(const KeyType
& key
, KeyValueCompare comp
, Disposer disposer
854 , typename
detail::enable_if_c
<!detail::is_convertible
<KeyValueCompare
, const_iterator
>::value
>::type
* = 0
858 std::pair
<iterator
,iterator
> p
= this->equal_range(key
, comp
);
860 private_erase(p
.first
, p
.second
, n
, disposer
);
864 //! <b>Effects</b>: Erases all of the elements.
866 //! <b>Complexity</b>: Linear to the number of elements on the container.
867 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
869 //! <b>Throws</b>: Nothing.
871 //! <b>Note</b>: Invalidates the iterators (but not the references)
872 //! to the erased elements. No destructors are called.
875 if(safemode_or_autounlink
){
876 this->clear_and_dispose(detail::null_disposer());
879 node_algorithms::init_header(&priv_header());
880 this->priv_size_traits().set_size(0);
884 //! <b>Effects</b>: Erases all of the elements calling disposer(p) for
885 //! each node to be erased.
886 //! <b>Complexity</b>: Amortized O(log(size() + N)),
887 //! where N is the number of elements in the container.
889 //! <b>Throws</b>: Nothing.
891 //! <b>Note</b>: Invalidates the iterators (but not the references)
892 //! to the erased elements. Calls N times to disposer functor.
893 template<class Disposer
>
894 void clear_and_dispose(Disposer disposer
)
896 node_algorithms::clear_and_dispose(node_ptr(&priv_header())
897 , detail::node_disposer
<Disposer
, splaytree_impl
>(disposer
, this));
898 node_algorithms::init_header(&priv_header());
899 this->priv_size_traits().set_size(0);
902 //! <b>Effects</b>: Returns the number of contained elements with the given value
904 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
905 //! to number of objects with the given value.
907 //! <b>Throws</b>: Nothing.
908 size_type
count(const_reference value
)
909 { return this->count(value
, priv_comp()); }
911 //! <b>Effects</b>: Returns the number of contained elements with the given key
913 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
914 //! to number of objects with the given key.
916 //! <b>Throws</b>: Nothing.
917 template<class KeyType
, class KeyValueCompare
>
918 size_type
count(const KeyType
&key
, KeyValueCompare comp
)
920 std::pair
<const_iterator
, const_iterator
> ret
= this->equal_range(key
, comp
);
921 return std::distance(ret
.first
, ret
.second
);
924 //! <b>Effects</b>: Returns the number of contained elements with the given value
926 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
927 //! to number of objects with the given value.
929 //! <b>Throws</b>: Nothing.
930 size_type
count_dont_splay(const_reference value
) const
931 { return this->count_dont_splay(value
, priv_comp()); }
933 //! <b>Effects</b>: Returns the number of contained elements with the given key
935 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
936 //! to number of objects with the given key.
938 //! <b>Throws</b>: Nothing.
939 template<class KeyType
, class KeyValueCompare
>
940 size_type
count_dont_splay(const KeyType
&key
, KeyValueCompare comp
) const
942 std::pair
<const_iterator
, const_iterator
> ret
= this->equal_range_dont_splay(key
, comp
);
943 return std::distance(ret
.first
, ret
.second
);
946 //! <b>Effects</b>: Returns an iterator to the first element whose
947 //! key is not less than k or end() if that element does not exist.
949 //! <b>Complexity</b>: Amortized logarithmic.
951 //! <b>Throws</b>: Nothing.
952 iterator
lower_bound(const_reference value
)
953 { return this->lower_bound(value
, priv_comp()); }
955 //! <b>Effects</b>: Returns an iterator to the first element whose
956 //! key is not less than k or end() if that element does not exist.
958 //! <b>Complexity</b>: Logarithmic.
960 //! <b>Throws</b>: Nothing.
961 const_iterator
lower_bound_dont_splay(const_reference value
) const
962 { return this->lower_bound_dont_splay(value
, priv_comp()); }
964 //! <b>Effects</b>: Returns an iterator to the first element whose
965 //! key is not less than k or end() if that element does not exist.
967 //! <b>Complexity</b>: Logarithmic.
969 //! <b>Throws</b>: Nothing.
970 template<class KeyType
, class KeyValueCompare
>
971 iterator
lower_bound(const KeyType
&key
, KeyValueCompare comp
)
973 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
974 key_node_comp(comp
, this);
975 return iterator(node_algorithms::lower_bound
976 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
979 //! <b>Effects</b>: Returns a const iterator to the first element whose
980 //! key is not less than k or end() if that element does not exist.
982 //! <b>Complexity</b>: Logarithmic.
984 //! <b>Throws</b>: Nothing.
985 template<class KeyType
, class KeyValueCompare
>
986 const_iterator
lower_bound_dont_splay(const KeyType
&key
, KeyValueCompare comp
) const
988 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
989 key_node_comp(comp
, this);
990 return const_iterator(node_algorithms::lower_bound
991 (const_node_ptr(&priv_header()), key
, key_node_comp
, false), this);
994 //! <b>Effects</b>: Returns an iterator to the first element whose
995 //! key is greater than k or end() if that element does not exist.
997 //! <b>Complexity</b>: Amortized logarithmic.
999 //! <b>Throws</b>: Nothing.
1000 iterator
upper_bound(const_reference value
)
1001 { return this->upper_bound(value
, priv_comp()); }
1003 //! <b>Effects</b>: Returns an iterator to the first element whose
1004 //! key is greater than k according to comp or end() if that element
1007 //! <b>Complexity</b>: Amortized logarithmic.
1009 //! <b>Throws</b>: Nothing.
1010 template<class KeyType
, class KeyValueCompare
>
1011 iterator
upper_bound(const KeyType
&key
, KeyValueCompare comp
)
1013 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1014 key_node_comp(comp
, this);
1015 return iterator(node_algorithms::upper_bound
1016 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1019 //! <b>Effects</b>: Returns an iterator to the first element whose
1020 //! key is greater than k or end() if that element does not exist.
1022 //! <b>Complexity</b>: Logarithmic.
1024 //! <b>Throws</b>: Nothing.
1025 const_iterator
upper_bound_dont_splay(const_reference value
) const
1026 { return this->upper_bound_dont_splay(value
, priv_comp()); }
1028 //! <b>Effects</b>: Returns an iterator to the first element whose
1029 //! key is greater than k according to comp or end() if that element
1032 //! <b>Complexity</b>: Logarithmic.
1034 //! <b>Throws</b>: Nothing.
1035 template<class KeyType
, class KeyValueCompare
>
1036 const_iterator
upper_bound_dont_splay(const KeyType
&key
, KeyValueCompare comp
) const
1038 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1039 key_node_comp(comp
, this);
1040 return const_iterator(node_algorithms::upper_bound_dont_splay
1041 (const_node_ptr(&priv_header()), key
, key_node_comp
, false), this);
1044 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1045 //! k or end() if that element does not exist.
1047 //! <b>Complexity</b>: Amortized logarithmic.
1049 //! <b>Throws</b>: Nothing.
1050 iterator
find(const_reference value
)
1051 { return this->find(value
, priv_comp()); }
1053 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1054 //! k or end() if that element does not exist.
1056 //! <b>Complexity</b>: Amortized logarithmic.
1058 //! <b>Throws</b>: Nothing.
1059 template<class KeyType
, class KeyValueCompare
>
1060 iterator
find(const KeyType
&key
, KeyValueCompare comp
)
1062 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1063 key_node_comp(comp
, this);
1065 (node_algorithms::find(const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1068 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1069 //! k or end() if that element does not exist.
1071 //! <b>Complexity</b>: Logarithmic.
1073 //! <b>Throws</b>: Nothing.
1074 const_iterator
find_dont_splay(const_reference value
) const
1075 { return this->find_dont_splay(value
, priv_comp()); }
1077 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1078 //! k or end() if that element does not exist.
1080 //! <b>Complexity</b>: Logarithmic.
1082 //! <b>Throws</b>: Nothing.
1083 template<class KeyType
, class KeyValueCompare
>
1084 const_iterator
find_dont_splay(const KeyType
&key
, KeyValueCompare comp
) const
1086 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1087 key_node_comp(comp
, this);
1088 return const_iterator
1089 (node_algorithms::find(const_node_ptr(&priv_header()), key
, key_node_comp
, false), this);
1092 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1093 //! an empty range that indicates the position where those elements would be
1094 //! if they there is no elements with key k.
1096 //! <b>Complexity</b>: Amortized logarithmic.
1098 //! <b>Throws</b>: Nothing.
1099 std::pair
<iterator
,iterator
> equal_range(const_reference value
)
1100 { return this->equal_range(value
, priv_comp()); }
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>: Amortized logarithmic.
1108 //! <b>Throws</b>: Nothing.
1109 template<class KeyType
, class KeyValueCompare
>
1110 std::pair
<iterator
,iterator
> equal_range(const KeyType
&key
, KeyValueCompare comp
)
1112 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1113 key_node_comp(comp
, this);
1114 std::pair
<node_ptr
, node_ptr
> ret
1115 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key
, key_node_comp
));
1116 return std::pair
<iterator
, iterator
>(iterator(ret
.first
, this), iterator(ret
.second
, this));
1119 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1120 //! an empty range that indicates the position where those elements would be
1121 //! if they there is no elements with key k.
1123 //! <b>Complexity</b>: Logarithmic.
1125 //! <b>Throws</b>: Nothing.
1126 std::pair
<const_iterator
, const_iterator
>
1127 equal_range_dont_splay(const_reference value
) const
1128 { return this->equal_range_dont_splay(value
, priv_comp()); }
1130 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1131 //! an empty range that indicates the position where those elements would be
1132 //! if they there is no elements with key k.
1134 //! <b>Complexity</b>: Logarithmic.
1136 //! <b>Throws</b>: Nothing.
1137 template<class KeyType
, class KeyValueCompare
>
1138 std::pair
<const_iterator
, const_iterator
>
1139 equal_range_dont_splay(const KeyType
&key
, KeyValueCompare comp
) const
1141 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1142 key_node_comp(comp
, this);
1143 std::pair
<node_ptr
, node_ptr
> ret
1144 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key
, key_node_comp
, false));
1145 return std::pair
<const_iterator
, const_iterator
>(const_iterator(ret
.first
, this), const_iterator(ret
.second
, this));
1148 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1149 //! Cloner should yield to nodes equivalent to the original nodes.
1151 //! <b>Effects</b>: Erases all the elements from *this
1152 //! calling Disposer::operator()(pointer), clones all the
1153 //! elements from src calling Cloner::operator()(const_reference )
1154 //! and inserts them on *this. Copies the predicate from the source container.
1156 //! If cloner throws, all cloned elements are unlinked and disposed
1157 //! calling Disposer::operator()(pointer).
1159 //! <b>Complexity</b>: Linear to erased plus inserted elements.
1161 //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
1162 template <class Cloner
, class Disposer
>
1163 void clone_from(const splaytree_impl
&src
, Cloner cloner
, Disposer disposer
)
1165 this->clear_and_dispose(disposer
);
1167 detail::exception_disposer
<splaytree_impl
, Disposer
>
1168 rollback(*this, disposer
);
1169 node_algorithms::clone
1170 (const_node_ptr(&src
.priv_header())
1171 ,node_ptr(&this->priv_header())
1172 ,detail::node_cloner
<Cloner
, splaytree_impl
>(cloner
, this)
1173 ,detail::node_disposer
<Disposer
, splaytree_impl
>(disposer
, this));
1174 this->priv_size_traits().set_size(src
.priv_size_traits().get_size());
1175 this->priv_comp() = src
.priv_comp();
1180 //! <b>Effects</b>: Unlinks the leftmost node from the tree.
1182 //! <b>Complexity</b>: Average complexity is constant time.
1184 //! <b>Throws</b>: Nothing.
1186 //! <b>Notes</b>: This function breaks the tree and the tree can
1187 //! only be used for more unlink_leftmost_without_rebalance calls.
1188 //! This function is normally used to achieve a step by step
1189 //! controlled destruction of the tree.
1190 pointer
unlink_leftmost_without_rebalance()
1192 node_ptr
to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance
1193 (node_ptr(&priv_header())));
1196 this->priv_size_traits().decrement();
1197 if(safemode_or_autounlink
)//If this is commented does not work with normal_link
1198 node_algorithms::init(to_be_disposed
);
1199 return get_real_value_traits().to_value_ptr(to_be_disposed
);
1202 //! <b>Requires</b>: i must be a valid iterator of *this.
1204 //! <b>Effects</b>: Rearranges the splay set so that the element pointed by i
1205 //! is placed as the root of the tree, improving future searches of this value.
1207 //! <b>Complexity</b>: Amortized logarithmic.
1209 //! <b>Throws</b>: Nothing.
1210 void splay_up(iterator i
)
1211 { return node_algorithms::splay_up(i
.pointed_node(), &priv_header()); }
1213 //! <b>Effects</b>: Rearranges the splay set so that if *this stores an element
1214 //! with a key equivalent to value the element is placed as the root of the
1215 //! tree. If the element is not present returns the last node compared with the key.
1216 //! If the tree is empty, end() is returned.
1218 //! <b>Complexity</b>: Amortized logarithmic.
1220 //! <b>Returns</b>: An iterator to the new root of the tree, end() if the tree is empty.
1222 //! <b>Throws</b>: If the comparison functor throws.
1223 template<class KeyType
, class KeyValueCompare
>
1224 iterator
splay_down(const KeyType
&key
, KeyValueCompare comp
)
1226 detail::key_nodeptr_comp
<KeyValueCompare
, splaytree_impl
>
1227 key_node_comp(comp
, this);
1228 node_ptr r
= node_algorithms::splay_down(&priv_header(), key
, key_node_comp
);
1229 return iterator(r
, this);
1232 //! <b>Effects</b>: Rearranges the splay set so that if *this stores an element
1233 //! with a key equivalent to value the element is placed as the root of the
1236 //! <b>Complexity</b>: Amortized logarithmic.
1238 //! <b>Returns</b>: An iterator to the new root of the tree, end() if the tree is empty.
1240 //! <b>Throws</b>: If the predicate throws.
1241 iterator
splay_down(const value_type
&value
)
1242 { return this->splay_down(value
, priv_comp()); }
1244 //! <b>Requires</b>: replace_this must be a valid iterator of *this
1245 //! and with_this must not be inserted in any tree.
1247 //! <b>Effects</b>: Replaces replace_this in its position in the
1248 //! tree with with_this. The tree does not need to be rebalanced.
1250 //! <b>Complexity</b>: Constant.
1252 //! <b>Throws</b>: Nothing.
1254 //! <b>Note</b>: This function will break container ordering invariants if
1255 //! with_this is not equivalent to *replace_this according to the
1256 //! ordering rules. This function is faster than erasing and inserting
1257 //! the node, since no rebalancing or comparison is needed.
1258 void replace_node(iterator replace_this
, reference with_this
)
1260 node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this
)
1261 , node_ptr(&priv_header())
1262 , get_real_value_traits().to_node_ptr(with_this
));
1265 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1266 //! appropriate type. Otherwise the behavior is undefined.
1268 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1269 //! that points to the value
1271 //! <b>Complexity</b>: Constant.
1273 //! <b>Throws</b>: Nothing.
1275 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1277 static iterator
s_iterator_to(reference value
)
1279 BOOST_STATIC_ASSERT((!stateful_value_traits
));
1280 return iterator (value_traits::to_node_ptr(value
), 0);
1283 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1284 //! appropriate type. Otherwise the behavior is undefined.
1286 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1287 //! set that points to the value
1289 //! <b>Complexity</b>: Constant.
1291 //! <b>Throws</b>: Nothing.
1293 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1295 static const_iterator
s_iterator_to(const_reference value
)
1297 BOOST_STATIC_ASSERT((!stateful_value_traits
));
1298 return const_iterator (value_traits::to_node_ptr(const_cast<reference
> (value
)), 0);
1301 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1302 //! appropriate type. Otherwise the behavior is undefined.
1304 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1305 //! that points to the value
1307 //! <b>Complexity</b>: Constant.
1309 //! <b>Throws</b>: Nothing.
1310 iterator
iterator_to(reference value
)
1311 { return iterator (value_traits::to_node_ptr(value
), this); }
1313 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1314 //! appropriate type. Otherwise the behavior is undefined.
1316 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1317 //! set that points to the value
1319 //! <b>Complexity</b>: Constant.
1321 //! <b>Throws</b>: Nothing.
1322 const_iterator
iterator_to(const_reference value
) const
1323 { return const_iterator (value_traits::to_node_ptr(const_cast<reference
> (value
)), this); }
1325 //! <b>Requires</b>: value shall not be in a tree.
1327 //! <b>Effects</b>: init_node puts the hook of a value in a well-known default
1330 //! <b>Throws</b>: Nothing.
1332 //! <b>Complexity</b>: Constant time.
1334 //! <b>Note</b>: This function puts the hook in the well-known default state
1335 //! used by auto_unlink and safe hooks.
1336 static void init_node(reference value
)
1337 { node_algorithms::init(value_traits::to_node_ptr(value
)); }
1339 //! <b>Effects</b>: Rebalances the tree.
1341 //! <b>Throws</b>: Nothing.
1343 //! <b>Complexity</b>: Linear.
1345 { node_algorithms::rebalance(node_ptr(&priv_header())); }
1347 //! <b>Requires</b>: old_root is a node of a tree.
1349 //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
1351 //! <b>Returns</b>: The new root of the subtree.
1353 //! <b>Throws</b>: Nothing.
1355 //! <b>Complexity</b>: Linear to the elements in the subtree.
1356 iterator
rebalance_subtree(iterator root
)
1357 { return iterator(node_algorithms::rebalance_subtree(root
.pointed_node()), this); }
1360 //! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
1361 //! if x is not in such a tree.
1363 //! <b>Throws</b>: Nothing.
1365 //! <b>Complexity</b>: Constant time.
1367 //! <b>Note</b>: This static function is only usable with the "safe mode"
1368 //! hook and non-constant time size lists. Otherwise, the user must use
1369 //! the non-static "erase(reference )" member. If the user calls
1370 //! this function with a non "safe mode" or constant time size list
1371 //! a compilation error will be issued.
1373 static void remove_node(T& value)
1375 //This function is only usable for safe mode hooks and non-constant
1377 //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
1378 BOOST_STATIC_ASSERT((!constant_time_size));
1379 BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
1380 node_ptr to_remove(value_traits::to_node_ptr(value));
1381 node_algorithms::unlink_and_rebalance(to_remove);
1382 if(safemode_or_autounlink)
1383 node_algorithms::init(to_remove);
1389 template<class Disposer
>
1390 iterator
private_erase(const_iterator b
, const_iterator e
, size_type
&n
, Disposer disposer
)
1392 for(n
= 0; b
!= e
; ++n
)
1393 this->erase_and_dispose(b
++, disposer
);
1397 iterator
private_erase(const_iterator b
, const_iterator e
, size_type
&n
)
1399 for(n
= 0; b
!= e
; ++n
)
1406 static splaytree_impl
&priv_container_from_end_iterator(const const_iterator
&end_iterator
)
1408 header_plus_size
*r
= detail::parent_from_member
<header_plus_size
, node
>
1409 ( detail::get_pointer(end_iterator
.pointed_node()), &header_plus_size::header_
);
1410 node_plus_pred_t
*n
= detail::parent_from_member
1411 <node_plus_pred_t
, header_plus_size
>(r
, &node_plus_pred_t::header_plus_size_
);
1412 data_t
*d
= detail::parent_from_member
<data_t
, node_plus_pred_t
>(n
, &data_t::node_plus_pred_
);
1413 splaytree_impl
*rb
= detail::parent_from_member
<splaytree_impl
, data_t
>(d
, &splaytree_impl::data_
);
1417 static splaytree_impl
&priv_container_from_iterator(const const_iterator
&it
)
1418 { return priv_container_from_end_iterator(it
.end_iterator_from_it()); }
1421 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1422 template<class T
, class ...Options
>
1424 template<class Config
>
1426 inline bool operator<
1427 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1428 (const splaytree_impl
<T
, Options
...> &x
, const splaytree_impl
<T
, Options
...> &y
)
1430 (const splaytree_impl
<Config
> &x
, const splaytree_impl
<Config
> &y
)
1432 { return std::lexicographical_compare(x
.begin(), x
.end(), y
.begin(), y
.end()); }
1434 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1435 template<class T
, class ...Options
>
1437 template<class Config
>
1440 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1441 (const splaytree_impl
<T
, Options
...> &x
, const splaytree_impl
<T
, Options
...> &y
)
1443 (const splaytree_impl
<Config
> &x
, const splaytree_impl
<Config
> &y
)
1446 typedef splaytree_impl
<Config
> tree_type
;
1447 typedef typename
tree_type::const_iterator const_iterator
;
1449 if(tree_type::constant_time_size
&& x
.size() != y
.size()){
1452 const_iterator end1
= x
.end();
1453 const_iterator i1
= x
.begin();
1454 const_iterator i2
= y
.begin();
1455 if(tree_type::constant_time_size
){
1456 while (i1
!= end1
&& *i1
== *i2
) {
1463 const_iterator end2
= y
.end();
1464 while (i1
!= end1
&& i2
!= end2
&& *i1
== *i2
) {
1468 return i1
== end1
&& i2
== end2
;
1472 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1473 template<class T
, class ...Options
>
1475 template<class Config
>
1477 inline bool operator!=
1478 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1479 (const splaytree_impl
<T
, Options
...> &x
, const splaytree_impl
<T
, Options
...> &y
)
1481 (const splaytree_impl
<Config
> &x
, const splaytree_impl
<Config
> &y
)
1483 { return !(x
== y
); }
1485 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1486 template<class T
, class ...Options
>
1488 template<class Config
>
1490 inline bool operator>
1491 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1492 (const splaytree_impl
<T
, Options
...> &x
, const splaytree_impl
<T
, Options
...> &y
)
1494 (const splaytree_impl
<Config
> &x
, const splaytree_impl
<Config
> &y
)
1498 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1499 template<class T
, class ...Options
>
1501 template<class Config
>
1503 inline bool operator<=
1504 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1505 (const splaytree_impl
<T
, Options
...> &x
, const splaytree_impl
<T
, Options
...> &y
)
1507 (const splaytree_impl
<Config
> &x
, const splaytree_impl
<Config
> &y
)
1509 { return !(y
< x
); }
1511 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1512 template<class T
, class ...Options
>
1514 template<class Config
>
1516 inline bool operator>=
1517 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1518 (const splaytree_impl
<T
, Options
...> &x
, const splaytree_impl
<T
, Options
...> &y
)
1520 (const splaytree_impl
<Config
> &x
, const splaytree_impl
<Config
> &y
)
1522 { return !(x
< y
); }
1524 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1525 template<class T
, class ...Options
>
1527 template<class Config
>
1530 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1531 (splaytree_impl
<T
, Options
...> &x
, splaytree_impl
<T
, Options
...> &y
)
1533 (splaytree_impl
<Config
> &x
, splaytree_impl
<Config
> &y
)
1539 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1540 template<class T
, class O1
= none
, class O2
= none
1541 , class O3
= none
, class O4
= none
>
1543 template<class T
, class ...Options
>
1545 struct make_splaytree_opt
1547 typedef typename pack_options
1548 < splay_set_defaults
<T
>,
1549 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1554 >::type packed_options
;
1555 typedef typename
detail::get_value_traits
1556 <T
, typename
packed_options::value_traits
>::type value_traits
;
1560 , typename
packed_options::compare
1561 , typename
packed_options::size_type
1562 , packed_options::constant_time_size
1567 //! Helper metafunction to define a \c splaytree that yields to the same type when the
1568 //! same options (either explicitly or implicitly) are used.
1569 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1570 template<class T
, class ...Options
>
1572 template<class T
, class O1
= none
, class O2
= none
1573 , class O3
= none
, class O4
= none
>
1575 struct make_splaytree
1578 typedef splaytree_impl
1579 < typename make_splaytree_opt
<T
,
1580 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1586 > implementation_defined
;
1588 typedef implementation_defined type
;
1591 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1592 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1593 template<class T
, class O1
, class O2
, class O3
, class O4
>
1595 template<class T
, class ...Options
>
1598 : public make_splaytree
<T
,
1599 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1606 typedef typename make_splaytree
1608 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1616 typedef typename
Base::value_compare value_compare
;
1617 typedef typename
Base::value_traits value_traits
;
1618 typedef typename
Base::real_value_traits real_value_traits
;
1619 typedef typename
Base::iterator iterator
;
1620 typedef typename
Base::const_iterator const_iterator
;
1622 //Assert if passed value traits are compatible with the type
1623 BOOST_STATIC_ASSERT((detail::is_same
<typename
real_value_traits::value_type
, T
>::value
));
1625 splaytree( const value_compare
&cmp
= value_compare()
1626 , const value_traits
&v_traits
= value_traits())
1627 : Base(cmp
, v_traits
)
1630 template<class Iterator
>
1631 splaytree( bool unique
, Iterator b
, Iterator e
1632 , const value_compare
&cmp
= value_compare()
1633 , const value_traits
&v_traits
= value_traits())
1634 : Base(unique
, b
, e
, cmp
, v_traits
)
1637 static splaytree
&container_from_end_iterator(iterator end_iterator
)
1638 { return static_cast<splaytree
&>(Base::container_from_end_iterator(end_iterator
)); }
1640 static const splaytree
&container_from_end_iterator(const_iterator end_iterator
)
1641 { return static_cast<const splaytree
&>(Base::container_from_end_iterator(end_iterator
)); }
1647 } //namespace intrusive
1650 #include <boost/intrusive/detail/config_end.hpp>
1652 #endif //BOOST_INTRUSIVE_SPLAYTREE_HPP