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 /////////////////////////////////////////////////////////////////////////////
13 // The option that yields to non-floating point 1/sqrt(2) alpha is taken
14 // from the scapegoat tree implementation of the PSPP library.
16 /////////////////////////////////////////////////////////////////////////////
18 #ifndef BOOST_INTRUSIVE_SGTREE_HPP
19 #define BOOST_INTRUSIVE_SGTREE_HPP
21 #include <boost/intrusive/detail/config_begin.hpp>
29 #include <boost/intrusive/detail/assert.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/intrusive/intrusive_fwd.hpp>
32 #include <boost/intrusive/bs_set_hook.hpp>
33 #include <boost/intrusive/detail/tree_node.hpp>
34 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
35 #include <boost/intrusive/detail/pointer_to_other.hpp>
36 #include <boost/intrusive/detail/clear_on_destructor_base.hpp>
37 #include <boost/intrusive/detail/mpl.hpp>
38 #include <boost/intrusive/options.hpp>
39 #include <boost/intrusive/sgtree_algorithms.hpp>
40 #include <boost/intrusive/link_mode.hpp>
49 //! Returns floor(log(n)/log(sqrt(2))) -> floor(2*log2(n))
50 //! Undefined if N is 0.
52 //! This function does not use float point operations.
53 inline std::size_t calculate_h_sqrt2 (std::size_t n
)
55 std::size_t f_log2
= detail::floor_log2(n
);
56 return (2*f_log2
) + (n
>= detail::sqrt2_pow_2xplus1 (f_log2
));
59 struct h_alpha_sqrt2_t
61 h_alpha_sqrt2_t(void){}
62 std::size_t operator()(std::size_t n
) const
63 { return calculate_h_sqrt2(n
); }
66 struct alpha_0_75_by_max_size_t
68 alpha_0_75_by_max_size_t(void){}
69 std::size_t operator()(std::size_t max_tree_size
) const
71 const std::size_t max_tree_size_limit
= ((~std::size_t(0))/std::size_t(3));
72 return max_tree_size
> max_tree_size_limit
? max_tree_size
/4*3 : max_tree_size
*3/4;
78 h_alpha_t(float inv_minus_logalpha
)
79 : inv_minus_logalpha_(inv_minus_logalpha
)
82 std::size_t operator()(std::size_t n
) const
84 //Returns floor(log1/alpha(n)) ->
85 // floor(log(n)/log(1/alpha)) ->
86 // floor(log(n)/(-log(alpha)))
87 //return static_cast<std::size_t>(std::log(float(n))*inv_minus_logalpha_);
88 return static_cast<std::size_t>(detail::fast_log2(float(n
))*inv_minus_logalpha_
);
92 //Since the function will be repeatedly called
93 //precalculate constant data to avoid repeated
94 //calls to log and division.
95 //This will store 1/(-std::log(alpha_))
96 float inv_minus_logalpha_
;
99 struct alpha_by_max_size_t
101 alpha_by_max_size_t(float alpha
)
105 float operator()(std::size_t max_tree_size
) const
106 { return float(max_tree_size
)*alpha_
; }
110 float inv_minus_logalpha_
;
113 template<bool Activate
>
116 typedef boost::intrusive::detail::h_alpha_t h_alpha_t
;
117 typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t
;
122 float get_alpha() const
125 void set_alpha(float alpha
)
128 inv_minus_logalpha_
= 1/(-detail::fast_log2(alpha
));
131 h_alpha_t
get_h_alpha_t() const
132 { return h_alpha_t(inv_minus_logalpha_
); }
134 multiply_by_alpha_t
get_multiply_by_alpha_t() const
135 { return multiply_by_alpha_t(alpha_
); }
139 float inv_minus_logalpha_
;
143 struct alpha_holder
<false>
145 //This specialization uses alpha = 1/sqrt(2)
146 //without using floating point operations
147 //Downside: alpha CAN't be changed.
148 typedef boost::intrusive::detail::h_alpha_sqrt2_t h_alpha_t
;
149 typedef boost::intrusive::detail::alpha_0_75_by_max_size_t multiply_by_alpha_t
;
151 float get_alpha() const
152 { return 0.70710677f
; }
154 void set_alpha(float)
155 { //alpha CAN't be changed.
156 BOOST_INTRUSIVE_INVARIANT_ASSERT(0);
159 h_alpha_t
get_h_alpha_t() const
160 { return h_alpha_t(); }
162 multiply_by_alpha_t
get_multiply_by_alpha_t() const
163 { return multiply_by_alpha_t(); }
166 } //namespace detail{
168 template <class ValueTraits
, class Compare
, class SizeType
, bool FloatingPoint
>
171 typedef ValueTraits value_traits
;
172 typedef Compare compare
;
173 typedef SizeType size_type
;
174 static const bool floating_point
= FloatingPoint
;
178 struct sg_set_defaults
181 , base_hook
<detail::default_bs_set_hook
>
182 , floating_point
<true>
183 , size_type
<std::size_t>
184 , compare
<std::less
<T
> >
190 //! The class template sgtree is an intrusive scapegoat tree container, that
191 //! is used to construct intrusive sg_set and sg_multiset containers.
192 //! The no-throw guarantee holds only, if the value_compare object
195 //! The template parameter \c T is the type to be managed by the container.
196 //! The user can specify additional options and if no options are provided
197 //! default options are used.
199 //! The container supports the following options:
200 //! \c base_hook<>/member_hook<>/value_traits<>,
201 //! \c floating_point<>, \c size_type<> and
203 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
204 template<class T
, class ...Options
>
206 template<class Config
>
209 : private detail::clear_on_destructor_base
<sgtree_impl
<Config
> >
211 template<class C
> friend class detail::clear_on_destructor_base
;
213 typedef typename
Config::value_traits value_traits
;
215 static const bool external_value_traits
=
216 detail::external_value_traits_is_true
<value_traits
>::value
;
217 typedef typename
detail::eval_if_c
218 < external_value_traits
219 , detail::eval_value_traits
<value_traits
>
220 , detail::identity
<value_traits
>
221 >::type real_value_traits
;
223 typedef typename
real_value_traits::pointer pointer
;
224 typedef typename
real_value_traits::const_pointer const_pointer
;
225 typedef typename
std::iterator_traits
<pointer
>::value_type value_type
;
226 typedef value_type key_type
;
227 typedef typename
std::iterator_traits
<pointer
>::reference reference
;
228 typedef typename
std::iterator_traits
<const_pointer
>::reference const_reference
;
229 typedef typename
std::iterator_traits
<pointer
>::difference_type difference_type
;
230 typedef typename
Config::size_type size_type
;
231 typedef typename
Config::compare value_compare
;
232 typedef value_compare key_compare
;
233 typedef tree_iterator
<sgtree_impl
, false> iterator
;
234 typedef tree_iterator
<sgtree_impl
, true> const_iterator
;
235 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
236 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
237 typedef typename
real_value_traits::node_traits node_traits
;
238 typedef typename
node_traits::node node
;
239 typedef typename
boost::pointer_to_other
240 <pointer
, node
>::type node_ptr
;
241 typedef typename
boost::pointer_to_other
242 <node_ptr
, const node
>::type const_node_ptr
;
243 typedef sgtree_algorithms
<node_traits
> node_algorithms
;
245 static const bool floating_point
= Config::floating_point
;
246 static const bool constant_time_size
= true;
247 static const bool stateful_value_traits
= detail::store_cont_ptr_on_it
<sgtree_impl
>::value
;
251 typedef detail::size_holder
<true, size_type
> size_traits
;
252 typedef detail::alpha_holder
<floating_point
> alpha_traits
;
253 typedef typename
alpha_traits::h_alpha_t h_alpha_t
;
254 typedef typename
alpha_traits::multiply_by_alpha_t multiply_by_alpha_t
;
257 sgtree_impl (const sgtree_impl
&);
258 sgtree_impl
operator =(const sgtree_impl
&);
260 enum { safemode_or_autounlink
=
261 (int)real_value_traits::link_mode
== (int)auto_unlink
||
262 (int)real_value_traits::link_mode
== (int)safe_link
};
264 BOOST_STATIC_ASSERT(((int)real_value_traits::link_mode
!= (int)auto_unlink
));
266 //BOOST_STATIC_ASSERT((
267 // (int)real_value_traits::link_mode != (int)auto_unlink ||
271 struct header_plus_alpha
: public alpha_traits
274 struct node_plus_pred_t
: public detail::ebo_functor_holder
<value_compare
>
276 node_plus_pred_t(const value_compare
&comp
)
277 : detail::ebo_functor_holder
<value_compare
>(comp
)
279 header_plus_alpha header_plus_alpha_
;
280 size_traits size_traits_
;
283 struct data_t
: public sgtree_impl::value_traits
285 typedef typename
sgtree_impl::value_traits value_traits
;
286 data_t(const value_compare
& comp
, const value_traits
&val_traits
)
287 : value_traits(val_traits
), node_plus_pred_(comp
)
290 node_plus_pred_t node_plus_pred_
;
291 size_type max_tree_size_
;
294 float priv_alpha() const
295 { return this->priv_alpha_traits().get_alpha(); }
297 void priv_alpha(float alpha
)
298 { return this->priv_alpha_traits().set_alpha(alpha
); }
300 const value_compare
&priv_comp() const
301 { return data_
.node_plus_pred_
.get(); }
303 value_compare
&priv_comp()
304 { return data_
.node_plus_pred_
.get(); }
306 const node
&priv_header() const
307 { return data_
.node_plus_pred_
.header_plus_alpha_
.header_
; }
310 { return data_
.node_plus_pred_
.header_plus_alpha_
.header_
; }
312 static node_ptr
uncast(const_node_ptr ptr
)
313 { return node_ptr(const_cast<node
*>(detail::get_pointer(ptr
))); }
315 size_traits
&priv_size_traits()
316 { return data_
.node_plus_pred_
.size_traits_
; }
318 const size_traits
&priv_size_traits() const
319 { return data_
.node_plus_pred_
.size_traits_
; }
321 alpha_traits
&priv_alpha_traits()
322 { return data_
.node_plus_pred_
.header_plus_alpha_
; }
324 const alpha_traits
&priv_alpha_traits() const
325 { return data_
.node_plus_pred_
.header_plus_alpha_
; }
327 const real_value_traits
&get_real_value_traits(detail::bool_
<false>) const
330 const real_value_traits
&get_real_value_traits(detail::bool_
<true>) const
331 { return data_
.get_value_traits(*this); }
333 real_value_traits
&get_real_value_traits(detail::bool_
<false>)
336 real_value_traits
&get_real_value_traits(detail::bool_
<true>)
337 { return data_
.get_value_traits(*this); }
339 h_alpha_t
get_h_alpha_func() const
340 { return priv_alpha_traits().get_h_alpha_t(); }
342 multiply_by_alpha_t
get_alpha_by_max_size_func() const
343 { return priv_alpha_traits().get_multiply_by_alpha_t(); }
349 const real_value_traits
&get_real_value_traits() const
350 { return this->get_real_value_traits(detail::bool_
<external_value_traits
>()); }
352 real_value_traits
&get_real_value_traits()
353 { return this->get_real_value_traits(detail::bool_
<external_value_traits
>()); }
355 typedef typename
node_algorithms::insert_commit_data insert_commit_data
;
357 //! <b>Effects</b>: Constructs an empty tree.
359 //! <b>Complexity</b>: Constant.
361 //! <b>Throws</b>: If value_traits::node_traits::node
362 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
363 //! or the copy constructorof the value_compare object throws. Basic guarantee.
364 sgtree_impl( const value_compare
&cmp
= value_compare()
365 , const value_traits
&v_traits
= value_traits())
366 : data_(cmp
, v_traits
)
368 node_algorithms::init_header(&priv_header());
369 this->priv_size_traits().set_size(size_type(0));
372 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
373 //! cmp must be a comparison function that induces a strict weak ordering.
375 //! <b>Effects</b>: Constructs an empty tree and inserts elements from
378 //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using
379 //! comp and otherwise N * log N, where N is the distance between first and last.
381 //! <b>Throws</b>: If value_traits::node_traits::node
382 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
383 //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee.
384 template<class Iterator
>
385 sgtree_impl( bool unique
, Iterator b
, Iterator e
386 , const value_compare
&cmp
= value_compare()
387 , const value_traits
&v_traits
= value_traits())
388 : data_(cmp
, v_traits
)
390 node_algorithms::init_header(&priv_header());
391 this->priv_size_traits().set_size(size_type(0));
393 this->insert_unique(b
, e
);
395 this->insert_equal(b
, e
);
398 //! <b>Effects</b>: Detaches all elements from this. The objects in the set
399 //! are not deleted (i.e. no destructors are called), but the nodes according to
400 //! the value_traits template parameter are reinitialized and thus can be reused.
402 //! <b>Complexity</b>: Linear to elements contained in *this.
404 //! <b>Throws</b>: Nothing.
408 //! <b>Effects</b>: Returns an iterator pointing to the beginning of the tree.
410 //! <b>Complexity</b>: Constant.
412 //! <b>Throws</b>: Nothing.
414 { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); }
416 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
418 //! <b>Complexity</b>: Constant.
420 //! <b>Throws</b>: Nothing.
421 const_iterator
begin() const
424 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
426 //! <b>Complexity</b>: Constant.
428 //! <b>Throws</b>: Nothing.
429 const_iterator
cbegin() const
430 { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); }
432 //! <b>Effects</b>: Returns an iterator pointing to the end of the tree.
434 //! <b>Complexity</b>: Constant.
436 //! <b>Throws</b>: Nothing.
438 { return iterator (node_ptr(&priv_header()), this); }
440 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
442 //! <b>Complexity</b>: Constant.
444 //! <b>Throws</b>: Nothing.
445 const_iterator
end() const
448 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
450 //! <b>Complexity</b>: Constant.
452 //! <b>Throws</b>: Nothing.
453 const_iterator
cend() const
454 { return const_iterator (uncast(const_node_ptr(&priv_header())), this); }
456 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning of the
459 //! <b>Complexity</b>: Constant.
461 //! <b>Throws</b>: Nothing.
462 reverse_iterator
rbegin()
463 { return reverse_iterator(end()); }
465 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
466 //! of the reversed tree.
468 //! <b>Complexity</b>: Constant.
470 //! <b>Throws</b>: Nothing.
471 const_reverse_iterator
rbegin() const
472 { return const_reverse_iterator(end()); }
474 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
475 //! of the reversed tree.
477 //! <b>Complexity</b>: Constant.
479 //! <b>Throws</b>: Nothing.
480 const_reverse_iterator
crbegin() const
481 { return const_reverse_iterator(end()); }
483 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
484 //! of the reversed tree.
486 //! <b>Complexity</b>: Constant.
488 //! <b>Throws</b>: Nothing.
489 reverse_iterator
rend()
490 { return reverse_iterator(begin()); }
492 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
493 //! of the reversed tree.
495 //! <b>Complexity</b>: Constant.
497 //! <b>Throws</b>: Nothing.
498 const_reverse_iterator
rend() const
499 { return const_reverse_iterator(begin()); }
501 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
502 //! of the reversed tree.
504 //! <b>Complexity</b>: Constant.
506 //! <b>Throws</b>: Nothing.
507 const_reverse_iterator
crend() const
508 { return const_reverse_iterator(begin()); }
510 //! <b>Precondition</b>: end_iterator must be a valid end iterator
513 //! <b>Effects</b>: Returns a const reference to the sgtree associated to the end iterator
515 //! <b>Throws</b>: Nothing.
517 //! <b>Complexity</b>: Constant.
518 static sgtree_impl
&container_from_end_iterator(iterator end_iterator
)
519 { return priv_container_from_end_iterator(end_iterator
); }
521 //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
524 //! <b>Effects</b>: Returns a const reference to the sgtree associated to the end iterator
526 //! <b>Throws</b>: Nothing.
528 //! <b>Complexity</b>: Constant.
529 static const sgtree_impl
&container_from_end_iterator(const_iterator end_iterator
)
530 { return priv_container_from_end_iterator(end_iterator
); }
532 //! <b>Precondition</b>: it must be a valid iterator
535 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
537 //! <b>Throws</b>: Nothing.
539 //! <b>Complexity</b>: Logarithmic.
540 static sgtree_impl
&container_from_iterator(iterator it
)
541 { return priv_container_from_iterator(it
); }
543 //! <b>Precondition</b>: it must be a valid end const_iterator
546 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
548 //! <b>Throws</b>: Nothing.
550 //! <b>Complexity</b>: Logarithmic.
551 static const sgtree_impl
&container_from_iterator(const_iterator it
)
552 { return priv_container_from_iterator(it
); }
554 //! <b>Effects</b>: Returns the value_compare object used by the tree.
556 //! <b>Complexity</b>: Constant.
558 //! <b>Throws</b>: If value_compare copy-constructor throws.
559 value_compare
value_comp() const
560 { return priv_comp(); }
562 //! <b>Effects</b>: Returns true if the container is empty.
564 //! <b>Complexity</b>: Constant.
566 //! <b>Throws</b>: Nothing.
568 { return node_algorithms::unique(const_node_ptr(&priv_header())); }
570 //! <b>Effects</b>: Returns the number of elements stored in the tree.
572 //! <b>Complexity</b>: Linear to elements contained in *this
573 //! if constant-time size option is disabled. Constant time otherwise.
575 //! <b>Throws</b>: Nothing.
576 size_type
size() const
578 if(constant_time_size
)
579 return this->priv_size_traits().get_size();
581 return (size_type
)node_algorithms::size(const_node_ptr(&priv_header()));
585 //! <b>Effects</b>: Swaps the contents of two sgtrees.
587 //! <b>Complexity</b>: Constant.
589 //! <b>Throws</b>: If the comparison functor's swap call throws.
590 void swap(sgtree_impl
& other
)
594 swap(priv_comp(), priv_comp());
595 swap(priv_alpha_traits(), priv_alpha_traits());
596 swap(data_
.max_tree_size_
, other
.data_
.max_tree_size_
);
598 node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other
.priv_header()));
599 if(constant_time_size
){
600 size_type backup
= this->priv_size_traits().get_size();
601 this->priv_size_traits().set_size(other
.priv_size_traits().get_size());
602 other
.priv_size_traits().set_size(backup
);
606 //! <b>Requires</b>: value must be an lvalue
608 //! <b>Effects</b>: Inserts value into the tree before the upper bound.
610 //! <b>Complexity</b>: Average complexity for insert element is at
611 //! most logarithmic.
613 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
615 //! <b>Note</b>: Does not affect the validity of iterators and references.
616 //! No copy-constructors are called.
617 iterator
insert_equal(reference value
)
619 detail::key_nodeptr_comp
<value_compare
, sgtree_impl
>
620 key_node_comp(priv_comp(), this);
621 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
622 if(safemode_or_autounlink
)
623 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
624 this->priv_size_traits().increment();
625 std::size_t max_tree_size
= (std::size_t)data_
.max_tree_size_
;
626 node_ptr p
= node_algorithms::insert_equal_upper_bound
627 (node_ptr(&priv_header()), to_insert
, key_node_comp
628 , (size_type
)this->size(), this->get_h_alpha_func(), max_tree_size
);
629 data_
.max_tree_size_
= (size_type
)max_tree_size
;
630 return iterator(p
, this);
633 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
634 //! a valid iterator.
636 //! <b>Effects</b>: Inserts x into the tree, using "hint" as a hint to
637 //! where it will be inserted. If "hint" is the upper_bound
638 //! the insertion takes constant time (two comparisons in the worst case)
640 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
641 //! constant time if t is inserted immediately before hint.
643 //! <b>Throws</b>: Nothing.
645 //! <b>Note</b>: Does not affect the validity of iterators and references.
646 //! No copy-constructors are called.
647 iterator
insert_equal(const_iterator hint
, reference value
)
649 detail::key_nodeptr_comp
<value_compare
, sgtree_impl
>
650 key_node_comp(priv_comp(), this);
651 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
652 if(safemode_or_autounlink
)
653 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
654 this->priv_size_traits().increment();
655 std::size_t max_tree_size
= (std::size_t)data_
.max_tree_size_
;
656 node_ptr p
= node_algorithms::insert_equal
657 (node_ptr(&priv_header()), hint
.pointed_node(), to_insert
, key_node_comp
658 , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size
);
659 data_
.max_tree_size_
= (size_type
)max_tree_size
;
660 return iterator(p
, this);
663 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
664 //! of type value_type.
666 //! <b>Effects</b>: Inserts a each element of a range into the tree
667 //! before the upper bound of the key of each element.
669 //! <b>Complexity</b>: Insert range is in general O(N * log(N)), where N is the
670 //! size of the range. However, it is linear in N if the range is already sorted
673 //! <b>Throws</b>: Nothing.
675 //! <b>Note</b>: Does not affect the validity of iterators and references.
676 //! No copy-constructors are called.
677 template<class Iterator
>
678 void insert_equal(Iterator b
, Iterator e
)
680 iterator
end(this->end());
682 this->insert_equal(end
, *b
);
685 //! <b>Requires</b>: value must be an lvalue
687 //! <b>Effects</b>: Inserts value into the tree if the value
688 //! is not already present.
690 //! <b>Complexity</b>: Average complexity for insert element is at
691 //! most logarithmic.
693 //! <b>Throws</b>: Nothing.
695 //! <b>Note</b>: Does not affect the validity of iterators and references.
696 //! No copy-constructors are called.
697 std::pair
<iterator
, bool> insert_unique(reference value
)
699 insert_commit_data commit_data
;
700 std::pair
<iterator
, bool> ret
= insert_unique_check(value
, priv_comp(), commit_data
);
703 return std::pair
<iterator
, bool> (insert_unique_commit(value
, commit_data
), true);
706 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
709 //! <b>Effects</b>: Tries to insert x into the tree, using "hint" as a hint
710 //! to where it will be inserted.
712 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
713 //! constant time (two comparisons in the worst case)
714 //! if t is inserted immediately before hint.
716 //! <b>Throws</b>: Nothing.
718 //! <b>Note</b>: Does not affect the validity of iterators and references.
719 //! No copy-constructors are called.
720 iterator
insert_unique(const_iterator hint
, reference value
)
722 insert_commit_data commit_data
;
723 std::pair
<iterator
, bool> ret
= insert_unique_check(hint
, value
, priv_comp(), commit_data
);
726 return insert_unique_commit(value
, commit_data
);
729 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
730 //! of type value_type.
732 //! <b>Effects</b>: Tries to insert each element of a range into the tree.
734 //! <b>Complexity</b>: Insert range is in general O(N * log(N)), where N is the
735 //! size of the range. However, it is linear in N if the range is already sorted
738 //! <b>Throws</b>: Nothing.
740 //! <b>Note</b>: Does not affect the validity of iterators and references.
741 //! No copy-constructors are called.
742 template<class Iterator
>
743 void insert_unique(Iterator b
, Iterator e
)
746 iterator
end(this->end());
748 this->insert_unique(end
, *b
);
752 this->insert_unique(*b
);
756 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
757 //! the same strict weak ordering as value_compare. The difference is that
758 //! key_value_comp compares an arbitrary key with the contained values.
760 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
761 //! a user provided key instead of the value itself.
763 //! <b>Returns</b>: If there is an equivalent value
764 //! returns a pair containing an iterator to the already present value
765 //! and false. If the value can be inserted returns true in the returned
766 //! pair boolean and fills "commit_data" that is meant to be used with
767 //! the "insert_commit" function.
769 //! <b>Complexity</b>: Average complexity is at most logarithmic.
771 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
773 //! <b>Notes</b>: This function is used to improve performance when constructing
774 //! a value_type is expensive: if there is an equivalent value
775 //! the constructed object must be discarded. Many times, the part of the
776 //! node that is used to impose the order is much cheaper to construct
777 //! than the value_type and this function offers the possibility to use that
778 //! part to check if the insertion will be successful.
780 //! If the check is successful, the user can construct the value_type and use
781 //! "insert_commit" to insert the object in constant-time. This gives a total
782 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
784 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
785 //! objects are inserted or erased from the container.
786 template<class KeyType
, class KeyValueCompare
>
787 std::pair
<iterator
, bool> insert_unique_check
788 (const KeyType
&key
, KeyValueCompare key_value_comp
, insert_commit_data
&commit_data
)
790 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
791 comp(key_value_comp
, this);
792 std::pair
<node_ptr
, bool> ret
=
793 (node_algorithms::insert_unique_check
794 (node_ptr(&priv_header()), key
, comp
, commit_data
));
795 return std::pair
<iterator
, bool>(iterator(ret
.first
, this), ret
.second
);
798 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
799 //! the same strict weak ordering as value_compare. The difference is that
800 //! key_value_comp compares an arbitrary key with the contained values.
802 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
803 //! a user provided key instead of the value itself, using "hint"
804 //! as a hint to where it will be inserted.
806 //! <b>Returns</b>: If there is an equivalent value
807 //! returns a pair containing an iterator to the already present value
808 //! and false. If the value can be inserted returns true in the returned
809 //! pair boolean and fills "commit_data" that is meant to be used with
810 //! the "insert_commit" function.
812 //! <b>Complexity</b>: Logarithmic in general, but it's amortized
813 //! constant time if t is inserted immediately before hint.
815 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
817 //! <b>Notes</b>: This function is used to improve performance when constructing
818 //! a value_type is expensive: if there is an equivalent value
819 //! the constructed object must be discarded. Many times, the part of the
820 //! constructing that is used to impose the order is much cheaper to construct
821 //! than the value_type and this function offers the possibility to use that key
822 //! to check if the insertion will be successful.
824 //! If the check is successful, the user can construct the value_type and use
825 //! "insert_commit" to insert the object in constant-time. This can give a total
826 //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)).
828 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
829 //! objects are inserted or erased from the container.
830 template<class KeyType
, class KeyValueCompare
>
831 std::pair
<iterator
, bool> insert_unique_check
832 (const_iterator hint
, const KeyType
&key
833 ,KeyValueCompare key_value_comp
, insert_commit_data
&commit_data
)
835 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
836 comp(key_value_comp
, this);
837 std::pair
<node_ptr
, bool> ret
=
838 (node_algorithms::insert_unique_check
839 (node_ptr(&priv_header()), hint
.pointed_node(), key
, comp
, commit_data
));
840 return std::pair
<iterator
, bool>(iterator(ret
.first
, this), ret
.second
);
843 //! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
844 //! must have been obtained from a previous call to "insert_check".
845 //! No objects should have been inserted or erased from the container between
846 //! the "insert_check" that filled "commit_data" and the call to "insert_commit".
848 //! <b>Effects</b>: Inserts the value in the avl_set using the information obtained
849 //! from the "commit_data" that a previous "insert_check" filled.
851 //! <b>Returns</b>: An iterator to the newly inserted object.
853 //! <b>Complexity</b>: Constant time.
855 //! <b>Throws</b>: Nothing.
857 //! <b>Notes</b>: This function has only sense if a "insert_check" has been
858 //! previously executed to fill "commit_data". No value should be inserted or
859 //! erased between the "insert_check" and "insert_commit" calls.
860 iterator
insert_unique_commit(reference value
, const insert_commit_data
&commit_data
)
862 node_ptr
to_insert(get_real_value_traits().to_node_ptr(value
));
863 if(safemode_or_autounlink
)
864 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert
));
865 this->priv_size_traits().increment();
866 std::size_t max_tree_size
= (std::size_t)data_
.max_tree_size_
;
867 node_algorithms::insert_unique_commit
868 ( node_ptr(&priv_header()), to_insert
, commit_data
869 , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size
);
870 data_
.max_tree_size_
= (size_type
)max_tree_size
;
871 return iterator(to_insert
, this);
874 //! <b>Effects</b>: Erases the element pointed to by pos.
876 //! <b>Complexity</b>: Average complexity for erase element is constant time.
878 //! <b>Throws</b>: Nothing.
880 //! <b>Note</b>: Invalidates the iterators (but not the references)
881 //! to the erased elements. No destructors are called.
882 iterator
erase(const_iterator i
)
884 const_iterator
ret(i
);
886 node_ptr
to_erase(i
.pointed_node());
887 if(safemode_or_autounlink
)
888 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase
));
889 std::size_t max_tree_size
= data_
.max_tree_size_
;
890 node_algorithms::erase
891 ( &priv_header(), to_erase
, (std::size_t)this->size()
892 , max_tree_size
, this->get_alpha_by_max_size_func());
893 data_
.max_tree_size_
= (size_type
)max_tree_size
;
894 this->priv_size_traits().decrement();
895 if(safemode_or_autounlink
)
896 node_algorithms::init(to_erase
);
897 return ret
.unconst();
900 //! <b>Effects</b>: Erases the range pointed to by b end e.
902 //! <b>Complexity</b>: Average complexity for erase range is at most
903 //! O(log(size() + N)), where N is the number of elements in the range.
905 //! <b>Throws</b>: Nothing.
907 //! <b>Note</b>: Invalidates the iterators (but not the references)
908 //! to the erased elements. No destructors are called.
909 iterator
erase(const_iterator b
, const_iterator e
)
910 { size_type n
; return private_erase(b
, e
, n
); }
912 //! <b>Effects</b>: Erases all the elements with the given value.
914 //! <b>Returns</b>: The number of erased elements.
916 //! <b>Complexity</b>: O(log(size() + N).
918 //! <b>Throws</b>: Nothing.
920 //! <b>Note</b>: Invalidates the iterators (but not the references)
921 //! to the erased elements. No destructors are called.
922 size_type
erase(const_reference value
)
923 { return this->erase(value
, priv_comp()); }
925 //! <b>Effects</b>: Erases all the elements with the given key.
926 //! according to the comparison functor "comp".
928 //! <b>Returns</b>: The number of erased elements.
930 //! <b>Complexity</b>: O(log(size() + N).
932 //! <b>Throws</b>: Nothing.
934 //! <b>Note</b>: Invalidates the iterators (but not the references)
935 //! to the erased elements. No destructors are called.
936 template<class KeyType
, class KeyValueCompare
>
937 size_type
erase(const KeyType
& key
, KeyValueCompare comp
939 , typename
detail::enable_if_c
<!detail::is_convertible
<KeyValueCompare
, const_iterator
>::value
>::type
* = 0
943 std::pair
<iterator
,iterator
> p
= this->equal_range(key
, comp
);
945 private_erase(p
.first
, p
.second
, n
);
949 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
951 //! <b>Effects</b>: Erases the element pointed to by pos.
952 //! Disposer::operator()(pointer) is called for the removed element.
954 //! <b>Complexity</b>: Average complexity for erase element is constant time.
956 //! <b>Throws</b>: Nothing.
958 //! <b>Note</b>: Invalidates the iterators
959 //! to the erased elements.
960 template<class Disposer
>
961 iterator
erase_and_dispose(const_iterator i
, Disposer disposer
)
963 node_ptr
to_erase(i
.pointed_node());
964 iterator
ret(this->erase(i
));
965 disposer(get_real_value_traits().to_value_ptr(to_erase
));
969 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
970 template<class Disposer
>
971 iterator
erase_and_dispose(iterator i
, Disposer disposer
)
972 { return this->erase_and_dispose(const_iterator(i
), disposer
); }
975 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
977 //! <b>Effects</b>: Erases the range pointed to by b end e.
978 //! Disposer::operator()(pointer) is called for the removed elements.
980 //! <b>Complexity</b>: Average complexity for erase range is at most
981 //! O(log(size() + N)), where N is the number of elements in the range.
983 //! <b>Throws</b>: Nothing.
985 //! <b>Note</b>: Invalidates the iterators
986 //! to the erased elements.
987 template<class Disposer
>
988 iterator
erase_and_dispose(const_iterator b
, const_iterator e
, Disposer disposer
)
989 { size_type n
; return private_erase(b
, e
, n
, disposer
); }
991 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
993 //! <b>Effects</b>: Erases all the elements with the given value.
994 //! Disposer::operator()(pointer) is called for the removed elements.
996 //! <b>Returns</b>: The number of erased elements.
998 //! <b>Complexity</b>: O(log(size() + N).
1000 //! <b>Throws</b>: Nothing.
1002 //! <b>Note</b>: Invalidates the iterators (but not the references)
1003 //! to the erased elements. No destructors are called.
1004 template<class Disposer
>
1005 size_type
erase_and_dispose(const_reference value
, Disposer disposer
)
1007 std::pair
<iterator
,iterator
> p
= this->equal_range(value
);
1009 private_erase(p
.first
, p
.second
, n
, disposer
);
1013 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1015 //! <b>Effects</b>: Erases all the elements with the given key.
1016 //! according to the comparison functor "comp".
1017 //! Disposer::operator()(pointer) is called for the removed elements.
1019 //! <b>Returns</b>: The number of erased elements.
1021 //! <b>Complexity</b>: O(log(size() + N).
1023 //! <b>Throws</b>: Nothing.
1025 //! <b>Note</b>: Invalidates the iterators
1026 //! to the erased elements.
1027 template<class KeyType
, class KeyValueCompare
, class Disposer
>
1028 size_type
erase_and_dispose(const KeyType
& key
, KeyValueCompare comp
, Disposer disposer
1030 , typename
detail::enable_if_c
<!detail::is_convertible
<KeyValueCompare
, const_iterator
>::value
>::type
* = 0
1034 std::pair
<iterator
,iterator
> p
= this->equal_range(key
, comp
);
1036 private_erase(p
.first
, p
.second
, n
, disposer
);
1040 //! <b>Effects</b>: Erases all of the elements.
1042 //! <b>Complexity</b>: Linear to the number of elements on the container.
1043 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
1045 //! <b>Throws</b>: Nothing.
1047 //! <b>Note</b>: Invalidates the iterators (but not the references)
1048 //! to the erased elements. No destructors are called.
1051 if(safemode_or_autounlink
){
1052 this->clear_and_dispose(detail::null_disposer());
1055 node_algorithms::init_header(&priv_header());
1056 this->priv_size_traits().set_size(0);
1060 //! <b>Effects</b>: Erases all of the elements calling disposer(p) for
1061 //! each node to be erased.
1062 //! <b>Complexity</b>: Average complexity for is at most O(log(size() + N)),
1063 //! where N is the number of elements in the container.
1065 //! <b>Throws</b>: Nothing.
1067 //! <b>Note</b>: Invalidates the iterators (but not the references)
1068 //! to the erased elements. Calls N times to disposer functor.
1069 template<class Disposer
>
1070 void clear_and_dispose(Disposer disposer
)
1072 node_algorithms::clear_and_dispose(node_ptr(&priv_header())
1073 , detail::node_disposer
<Disposer
, sgtree_impl
>(disposer
, this));
1074 node_algorithms::init_header(&priv_header());
1075 this->priv_size_traits().set_size(0);
1078 //! <b>Effects</b>: Returns the number of contained elements with the given value
1080 //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal
1081 //! to number of objects with the given value.
1083 //! <b>Throws</b>: Nothing.
1084 size_type
count(const_reference value
) const
1085 { return this->count(value
, priv_comp()); }
1087 //! <b>Effects</b>: Returns the number of contained elements with the given key
1089 //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal
1090 //! to number of objects with the given key.
1092 //! <b>Throws</b>: Nothing.
1093 template<class KeyType
, class KeyValueCompare
>
1094 size_type
count(const KeyType
&key
, KeyValueCompare comp
) const
1096 std::pair
<const_iterator
, const_iterator
> ret
= this->equal_range(key
, comp
);
1097 return std::distance(ret
.first
, ret
.second
);
1100 //! <b>Effects</b>: Returns an iterator to the first element whose
1101 //! key is not less than k or end() if that element does not exist.
1103 //! <b>Complexity</b>: Logarithmic.
1105 //! <b>Throws</b>: Nothing.
1106 iterator
lower_bound(const_reference value
)
1107 { return this->lower_bound(value
, priv_comp()); }
1109 //! <b>Effects</b>: Returns an iterator to the first element whose
1110 //! key is not less than k or end() if that element does not exist.
1112 //! <b>Complexity</b>: Logarithmic.
1114 //! <b>Throws</b>: Nothing.
1115 const_iterator
lower_bound(const_reference value
) const
1116 { return this->lower_bound(value
, priv_comp()); }
1118 //! <b>Effects</b>: Returns an iterator to the first element whose
1119 //! key is not less than k or end() if that element does not exist.
1121 //! <b>Complexity</b>: Logarithmic.
1123 //! <b>Throws</b>: Nothing.
1124 template<class KeyType
, class KeyValueCompare
>
1125 iterator
lower_bound(const KeyType
&key
, KeyValueCompare comp
)
1127 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1128 key_node_comp(comp
, this);
1129 return iterator(node_algorithms::lower_bound
1130 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1133 //! <b>Effects</b>: Returns a const iterator to the first element whose
1134 //! key is not less than k or end() if that element does not exist.
1136 //! <b>Complexity</b>: Logarithmic.
1138 //! <b>Throws</b>: Nothing.
1139 template<class KeyType
, class KeyValueCompare
>
1140 const_iterator
lower_bound(const KeyType
&key
, KeyValueCompare comp
) const
1142 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1143 key_node_comp(comp
, this);
1144 return const_iterator(node_algorithms::lower_bound
1145 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1148 //! <b>Effects</b>: Returns an iterator to the first element whose
1149 //! key is greater than k or end() if that element does not exist.
1151 //! <b>Complexity</b>: Logarithmic.
1153 //! <b>Throws</b>: Nothing.
1154 iterator
upper_bound(const_reference value
)
1155 { return this->upper_bound(value
, priv_comp()); }
1157 //! <b>Effects</b>: Returns an iterator to the first element whose
1158 //! key is greater than k according to comp or end() if that element
1161 //! <b>Complexity</b>: Logarithmic.
1163 //! <b>Throws</b>: Nothing.
1164 template<class KeyType
, class KeyValueCompare
>
1165 iterator
upper_bound(const KeyType
&key
, KeyValueCompare comp
)
1167 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1168 key_node_comp(comp
, this);
1169 return iterator(node_algorithms::upper_bound
1170 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1173 //! <b>Effects</b>: Returns an iterator to the first element whose
1174 //! key is greater than k or end() if that element does not exist.
1176 //! <b>Complexity</b>: Logarithmic.
1178 //! <b>Throws</b>: Nothing.
1179 const_iterator
upper_bound(const_reference value
) const
1180 { return this->upper_bound(value
, priv_comp()); }
1182 //! <b>Effects</b>: Returns an iterator to the first element whose
1183 //! key is greater than k according to comp or end() if that element
1186 //! <b>Complexity</b>: Logarithmic.
1188 //! <b>Throws</b>: Nothing.
1189 template<class KeyType
, class KeyValueCompare
>
1190 const_iterator
upper_bound(const KeyType
&key
, KeyValueCompare comp
) const
1192 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1193 key_node_comp(comp
, this);
1194 return const_iterator(node_algorithms::upper_bound
1195 (const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1198 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1199 //! k or end() if that element does not exist.
1201 //! <b>Complexity</b>: Logarithmic.
1203 //! <b>Throws</b>: Nothing.
1204 iterator
find(const_reference value
)
1205 { return this->find(value
, priv_comp()); }
1207 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1208 //! k or end() if that element does not exist.
1210 //! <b>Complexity</b>: Logarithmic.
1212 //! <b>Throws</b>: Nothing.
1213 template<class KeyType
, class KeyValueCompare
>
1214 iterator
find(const KeyType
&key
, KeyValueCompare comp
)
1216 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1217 key_node_comp(comp
, this);
1219 (node_algorithms::find(const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1222 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1223 //! k or end() if that element does not exist.
1225 //! <b>Complexity</b>: Logarithmic.
1227 //! <b>Throws</b>: Nothing.
1228 const_iterator
find(const_reference value
) const
1229 { return this->find(value
, priv_comp()); }
1231 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1232 //! k or end() if that element does not exist.
1234 //! <b>Complexity</b>: Logarithmic.
1236 //! <b>Throws</b>: Nothing.
1237 template<class KeyType
, class KeyValueCompare
>
1238 const_iterator
find(const KeyType
&key
, KeyValueCompare comp
) const
1240 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1241 key_node_comp(comp
, this);
1242 return const_iterator
1243 (node_algorithms::find(const_node_ptr(&priv_header()), key
, key_node_comp
), this);
1246 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1247 //! an empty range that indicates the position where those elements would be
1248 //! if they there is no elements with key k.
1250 //! <b>Complexity</b>: Logarithmic.
1252 //! <b>Throws</b>: Nothing.
1253 std::pair
<iterator
,iterator
> equal_range(const_reference value
)
1254 { return this->equal_range(value
, priv_comp()); }
1256 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1257 //! an empty range that indicates the position where those elements would be
1258 //! if they there is no elements with key k.
1260 //! <b>Complexity</b>: Logarithmic.
1262 //! <b>Throws</b>: Nothing.
1263 template<class KeyType
, class KeyValueCompare
>
1264 std::pair
<iterator
,iterator
> equal_range(const KeyType
&key
, KeyValueCompare comp
)
1266 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1267 key_node_comp(comp
, this);
1268 std::pair
<node_ptr
, node_ptr
> ret
1269 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key
, key_node_comp
));
1270 return std::pair
<iterator
, iterator
>(iterator(ret
.first
, this), iterator(ret
.second
, this));
1273 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1274 //! an empty range that indicates the position where those elements would be
1275 //! if they there is no elements with key k.
1277 //! <b>Complexity</b>: Logarithmic.
1279 //! <b>Throws</b>: Nothing.
1280 std::pair
<const_iterator
, const_iterator
>
1281 equal_range(const_reference value
) const
1282 { return this->equal_range(value
, priv_comp()); }
1284 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1285 //! an empty range that indicates the position where those elements would be
1286 //! if they there is no elements with key k.
1288 //! <b>Complexity</b>: Logarithmic.
1290 //! <b>Throws</b>: Nothing.
1291 template<class KeyType
, class KeyValueCompare
>
1292 std::pair
<const_iterator
, const_iterator
>
1293 equal_range(const KeyType
&key
, KeyValueCompare comp
) const
1295 detail::key_nodeptr_comp
<KeyValueCompare
, sgtree_impl
>
1296 key_node_comp(comp
, this);
1297 std::pair
<node_ptr
, node_ptr
> ret
1298 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key
, key_node_comp
));
1299 return std::pair
<const_iterator
, const_iterator
>(const_iterator(ret
.first
, this), const_iterator(ret
.second
, this));
1302 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1303 //! Cloner should yield to nodes equivalent to the original nodes.
1305 //! <b>Effects</b>: Erases all the elements from *this
1306 //! calling Disposer::operator()(pointer), clones all the
1307 //! elements from src calling Cloner::operator()(const_reference )
1308 //! and inserts them on *this. Copies the predicate from the source container.
1310 //! If cloner throws, all cloned elements are unlinked and disposed
1311 //! calling Disposer::operator()(pointer).
1313 //! <b>Complexity</b>: Linear to erased plus inserted elements.
1315 //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
1316 template <class Cloner
, class Disposer
>
1317 void clone_from(const sgtree_impl
&src
, Cloner cloner
, Disposer disposer
)
1319 this->clear_and_dispose(disposer
);
1321 detail::exception_disposer
<sgtree_impl
, Disposer
>
1322 rollback(*this, disposer
);
1323 node_algorithms::clone
1324 (const_node_ptr(&src
.priv_header())
1325 ,node_ptr(&this->priv_header())
1326 ,detail::node_cloner
<Cloner
, sgtree_impl
>(cloner
, this)
1327 ,detail::node_disposer
<Disposer
, sgtree_impl
>(disposer
, this));
1328 this->priv_size_traits().set_size(src
.priv_size_traits().get_size());
1329 this->priv_comp() = src
.priv_comp();
1334 //! <b>Effects</b>: Unlinks the leftmost node from the tree.
1336 //! <b>Complexity</b>: Average complexity is constant time.
1338 //! <b>Throws</b>: Nothing.
1340 //! <b>Notes</b>: This function breaks the tree and the tree can
1341 //! only be used for more unlink_leftmost_without_rebalance calls.
1342 //! This function is normally used to achieve a step by step
1343 //! controlled destruction of the tree.
1344 pointer
unlink_leftmost_without_rebalance()
1346 node_ptr
to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance
1347 (node_ptr(&priv_header())));
1350 this->priv_size_traits().decrement();
1351 if(safemode_or_autounlink
)//If this is commented does not work with normal_link
1352 node_algorithms::init(to_be_disposed
);
1353 return get_real_value_traits().to_value_ptr(to_be_disposed
);
1356 //! <b>Requires</b>: replace_this must be a valid iterator of *this
1357 //! and with_this must not be inserted in any tree.
1359 //! <b>Effects</b>: Replaces replace_this in its position in the
1360 //! tree with with_this. The tree does not need to be rebalanced.
1362 //! <b>Complexity</b>: Constant.
1364 //! <b>Throws</b>: Nothing.
1366 //! <b>Note</b>: This function will break container ordering invariants if
1367 //! with_this is not equivalent to *replace_this according to the
1368 //! ordering rules. This function is faster than erasing and inserting
1369 //! the node, since no rebalancing or comparison is needed.
1370 void replace_node(iterator replace_this
, reference with_this
)
1372 node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this
)
1373 , node_ptr(&priv_header())
1374 , get_real_value_traits().to_node_ptr(with_this
));
1377 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1378 //! appropriate type. Otherwise the behavior is undefined.
1380 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1381 //! that points to the value
1383 //! <b>Complexity</b>: Constant.
1385 //! <b>Throws</b>: Nothing.
1387 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1389 static iterator
s_iterator_to(reference value
)
1391 BOOST_STATIC_ASSERT((!stateful_value_traits
));
1392 return iterator (value_traits::to_node_ptr(value
), 0);
1395 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1396 //! appropriate type. Otherwise the behavior is undefined.
1398 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1399 //! set that points to the value
1401 //! <b>Complexity</b>: Constant.
1403 //! <b>Throws</b>: Nothing.
1405 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1407 static const_iterator
s_iterator_to(const_reference value
)
1409 BOOST_STATIC_ASSERT((!stateful_value_traits
));
1410 return const_iterator (value_traits::to_node_ptr(const_cast<reference
> (value
)), 0);
1413 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1414 //! appropriate type. Otherwise the behavior is undefined.
1416 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1417 //! that points to the value
1419 //! <b>Complexity</b>: Constant.
1421 //! <b>Throws</b>: Nothing.
1422 iterator
iterator_to(reference value
)
1423 { return iterator (value_traits::to_node_ptr(value
), this); }
1425 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1426 //! appropriate type. Otherwise the behavior is undefined.
1428 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1429 //! set that points to the value
1431 //! <b>Complexity</b>: Constant.
1433 //! <b>Throws</b>: Nothing.
1434 const_iterator
iterator_to(const_reference value
) const
1435 { return const_iterator (value_traits::to_node_ptr(const_cast<reference
> (value
)), this); }
1437 //! <b>Requires</b>: value shall not be in a tree.
1439 //! <b>Effects</b>: init_node puts the hook of a value in a well-known default
1442 //! <b>Throws</b>: Nothing.
1444 //! <b>Complexity</b>: Constant time.
1446 //! <b>Note</b>: This function puts the hook in the well-known default state
1447 //! used by auto_unlink and safe hooks.
1448 static void init_node(reference value
)
1449 { node_algorithms::init(value_traits::to_node_ptr(value
)); }
1451 //! <b>Effects</b>: Rebalances the tree.
1453 //! <b>Throws</b>: Nothing.
1455 //! <b>Complexity</b>: Linear.
1457 { node_algorithms::rebalance(node_ptr(&priv_header())); }
1459 //! <b>Requires</b>: old_root is a node of a tree.
1461 //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
1463 //! <b>Returns</b>: The new root of the subtree.
1465 //! <b>Throws</b>: Nothing.
1467 //! <b>Complexity</b>: Linear to the elements in the subtree.
1468 iterator
rebalance_subtree(iterator root
)
1469 { return iterator(node_algorithms::rebalance_subtree(root
.pointed_node()), this); }
1471 //! <b>Returns</b>: The balance factor (alpha) used in this tree
1473 //! <b>Throws</b>: Nothing.
1475 //! <b>Complexity</b>: Constant.
1476 float balance_factor() const
1477 { return this->priv_alpha(); }
1479 //! <b>Requires</b>: new_alpha must be a value between 0.5 and 1.0
1481 //! <b>Effects</b>: Establishes a new balance factor (alpha) and rebalances
1482 //! the tree if the new balance factor is stricter (less) than the old factor.
1484 //! <b>Throws</b>: Nothing.
1486 //! <b>Complexity</b>: Linear to the elements in the subtree.
1487 void balance_factor(float new_alpha
)
1489 BOOST_INTRUSIVE_INVARIANT_ASSERT((new_alpha
> 0.5f
&& new_alpha
< 1.0f
));
1490 if(new_alpha
< 0.5f
&& new_alpha
>= 1.0f
) return;
1492 //The alpha factor CAN't be changed if the fixed, floating operation-less
1493 //1/sqrt(2) alpha factor option is activated
1494 BOOST_STATIC_ASSERT((floating_point
));
1495 float old_alpha
= this->priv_alpha();
1496 this->priv_alpha(new_alpha
);
1498 if(new_alpha
< old_alpha
){
1499 data_
.max_tree_size_
= this->size();
1504 //! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
1505 //! if x is not in such a tree.
1507 //! <b>Throws</b>: Nothing.
1509 //! <b>Complexity</b>: Constant time.
1511 //! <b>Note</b>: This static function is only usable with the "safe mode"
1512 //! hook and non-constant time size lists. Otherwise, the user must use
1513 //! the non-static "erase(reference )" member. If the user calls
1514 //! this function with a non "safe mode" or constant time size list
1515 //! a compilation error will be issued.
1517 static void remove_node(T& value)
1519 //This function is only usable for safe mode hooks and non-constant
1521 //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
1522 BOOST_STATIC_ASSERT((!constant_time_size));
1523 BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
1524 node_ptr to_remove(value_traits::to_node_ptr(value));
1525 node_algorithms::unlink_and_rebalance(to_remove);
1526 if(safemode_or_autounlink)
1527 node_algorithms::init(to_remove);
1533 template<class Disposer
>
1534 iterator
private_erase(const_iterator b
, const_iterator e
, size_type
&n
, Disposer disposer
)
1536 for(n
= 0; b
!= e
; ++n
)
1537 this->erase_and_dispose(b
++, disposer
);
1541 iterator
private_erase(const_iterator b
, const_iterator e
, size_type
&n
)
1543 for(n
= 0; b
!= e
; ++n
)
1550 static sgtree_impl
&priv_container_from_end_iterator(const const_iterator
&end_iterator
)
1552 header_plus_alpha
*r
= detail::parent_from_member
<header_plus_alpha
, node
>
1553 ( detail::get_pointer(end_iterator
.pointed_node()), &header_plus_alpha::header_
);
1554 node_plus_pred_t
*n
= detail::parent_from_member
1555 <node_plus_pred_t
, header_plus_alpha
>(r
, &node_plus_pred_t::header_plus_alpha_
);
1556 data_t
*d
= detail::parent_from_member
<data_t
, node_plus_pred_t
>(n
, &data_t::node_plus_pred_
);
1557 sgtree_impl
*scapegoat
= detail::parent_from_member
<sgtree_impl
, data_t
>(d
, &sgtree_impl::data_
);
1561 static sgtree_impl
&priv_container_from_iterator(const const_iterator
&it
)
1562 { return priv_container_from_end_iterator(it
.end_iterator_from_it()); }
1565 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1566 template<class T
, class ...Options
>
1568 template<class Config
>
1570 inline bool operator<
1571 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1572 (const sgtree_impl
<T
, Options
...> &x
, const sgtree_impl
<T
, Options
...> &y
)
1574 (const sgtree_impl
<Config
> &x
, const sgtree_impl
<Config
> &y
)
1576 { return std::lexicographical_compare(x
.begin(), x
.end(), y
.begin(), y
.end()); }
1578 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1579 template<class T
, class ...Options
>
1581 template<class Config
>
1584 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1585 (const sgtree_impl
<T
, Options
...> &x
, const sgtree_impl
<T
, Options
...> &y
)
1587 (const sgtree_impl
<Config
> &x
, const sgtree_impl
<Config
> &y
)
1590 typedef sgtree_impl
<Config
> tree_type
;
1591 typedef typename
tree_type::const_iterator const_iterator
;
1593 if(tree_type::constant_time_size
&& x
.size() != y
.size()){
1596 const_iterator end1
= x
.end();
1597 const_iterator i1
= x
.begin();
1598 const_iterator i2
= y
.begin();
1599 if(tree_type::constant_time_size
){
1600 while (i1
!= end1
&& *i1
== *i2
) {
1607 const_iterator end2
= y
.end();
1608 while (i1
!= end1
&& i2
!= end2
&& *i1
== *i2
) {
1612 return i1
== end1
&& i2
== end2
;
1616 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1617 template<class T
, class ...Options
>
1619 template<class Config
>
1621 inline bool operator!=
1622 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1623 (const sgtree_impl
<T
, Options
...> &x
, const sgtree_impl
<T
, Options
...> &y
)
1625 (const sgtree_impl
<Config
> &x
, const sgtree_impl
<Config
> &y
)
1627 { return !(x
== y
); }
1629 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1630 template<class T
, class ...Options
>
1632 template<class Config
>
1634 inline bool operator>
1635 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1636 (const sgtree_impl
<T
, Options
...> &x
, const sgtree_impl
<T
, Options
...> &y
)
1638 (const sgtree_impl
<Config
> &x
, const sgtree_impl
<Config
> &y
)
1642 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1643 template<class T
, class ...Options
>
1645 template<class Config
>
1647 inline bool operator<=
1648 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1649 (const sgtree_impl
<T
, Options
...> &x
, const sgtree_impl
<T
, Options
...> &y
)
1651 (const sgtree_impl
<Config
> &x
, const sgtree_impl
<Config
> &y
)
1653 { return !(y
< x
); }
1655 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1656 template<class T
, class ...Options
>
1658 template<class Config
>
1660 inline bool operator>=
1661 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1662 (const sgtree_impl
<T
, Options
...> &x
, const sgtree_impl
<T
, Options
...> &y
)
1664 (const sgtree_impl
<Config
> &x
, const sgtree_impl
<Config
> &y
)
1666 { return !(x
< y
); }
1668 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1669 template<class T
, class ...Options
>
1671 template<class Config
>
1674 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1675 (sgtree_impl
<T
, Options
...> &x
, sgtree_impl
<T
, Options
...> &y
)
1677 (sgtree_impl
<Config
> &x
, sgtree_impl
<Config
> &y
)
1682 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1683 template<class T
, class O1
= none
, class O2
= none
1684 , class O3
= none
, class O4
= none
>
1686 template<class T
, class ...Options
>
1688 struct make_sgtree_opt
1690 typedef typename pack_options
1691 < sg_set_defaults
<T
>,
1692 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1697 >::type packed_options
;
1698 typedef typename
detail::get_value_traits
1699 <T
, typename
packed_options::value_traits
>::type value_traits
;
1703 , typename
packed_options::compare
1704 , typename
packed_options::size_type
1705 , packed_options::floating_point
1710 //! Helper metafunction to define a \c sgtree that yields to the same type when the
1711 //! same options (either explicitly or implicitly) are used.
1712 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1713 template<class T
, class ...Options
>
1715 template<class T
, class O1
= none
, class O2
= none
1716 , class O3
= none
, class O4
= none
>
1722 < typename make_sgtree_opt
<T
,
1723 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1729 > implementation_defined
;
1731 typedef implementation_defined type
;
1734 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1735 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1736 template<class T
, class O1
, class O2
, class O3
, class O4
>
1738 template<class T
, class ...Options
>
1741 : public make_sgtree
<T
,
1742 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1749 typedef typename make_sgtree
1751 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1759 typedef typename
Base::value_compare value_compare
;
1760 typedef typename
Base::value_traits value_traits
;
1761 typedef typename
Base::real_value_traits real_value_traits
;
1762 typedef typename
Base::iterator iterator
;
1763 typedef typename
Base::const_iterator const_iterator
;
1765 //Assert if passed value traits are compatible with the type
1766 BOOST_STATIC_ASSERT((detail::is_same
<typename
real_value_traits::value_type
, T
>::value
));
1768 sgtree( const value_compare
&cmp
= value_compare()
1769 , const value_traits
&v_traits
= value_traits())
1770 : Base(cmp
, v_traits
)
1773 template<class Iterator
>
1774 sgtree( bool unique
, Iterator b
, Iterator e
1775 , const value_compare
&cmp
= value_compare()
1776 , const value_traits
&v_traits
= value_traits())
1777 : Base(unique
, b
, e
, cmp
, v_traits
)
1780 static sgtree
&container_from_end_iterator(iterator end_iterator
)
1781 { return static_cast<sgtree
&>(Base::container_from_end_iterator(end_iterator
)); }
1783 static const sgtree
&container_from_end_iterator(const_iterator end_iterator
)
1784 { return static_cast<const sgtree
&>(Base::container_from_end_iterator(end_iterator
)); }
1790 } //namespace intrusive
1793 #include <boost/intrusive/detail/config_end.hpp>
1795 #endif //BOOST_INTRUSIVE_SGTREE_HPP