fix doc example typo
[boost.git] / boost / intrusive / sgtree.hpp
blob0d19919ed710bc13aa13414a7abf54aae0c5ee1d
1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2007-2008
4 //
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)
8 //
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>
22 #include <algorithm>
23 #include <cstddef>
24 #include <functional>
25 #include <iterator>
26 #include <utility>
27 #include <cmath>
28 #include <cstddef>
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>
42 namespace boost {
43 namespace intrusive {
45 /// @cond
47 namespace detail{
49 //! Returns floor(log(n)/log(sqrt(2))) -> floor(2*log2(n))
50 //! Undefined if N is 0.
51 //!
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;
76 struct h_alpha_t
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_);
91 private:
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)
102 : alpha_(alpha)
105 float operator()(std::size_t max_tree_size) const
106 { return float(max_tree_size)*alpha_; }
108 private:
109 float alpha_;
110 float inv_minus_logalpha_;
113 template<bool Activate>
114 struct alpha_holder
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;
119 alpha_holder()
120 { set_alpha(0.7f); }
122 float get_alpha() const
123 { return alpha_; }
125 void set_alpha(float alpha)
127 alpha_ = 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_); }
137 private:
138 float alpha_;
139 float inv_minus_logalpha_;
142 template<>
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>
169 struct sg_setopt
171 typedef ValueTraits value_traits;
172 typedef Compare compare;
173 typedef SizeType size_type;
174 static const bool floating_point = FloatingPoint;
177 template <class T>
178 struct sg_set_defaults
179 : pack_options
180 < none
181 , base_hook<detail::default_bs_set_hook>
182 , floating_point<true>
183 , size_type<std::size_t>
184 , compare<std::less<T> >
185 >::type
188 /// @endcond
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
193 //! doesn't throw.
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
202 //! \c compare<>.
203 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
204 template<class T, class ...Options>
205 #else
206 template<class Config>
207 #endif
208 class sgtree_impl
209 : private detail::clear_on_destructor_base<sgtree_impl<Config> >
211 template<class C> friend class detail::clear_on_destructor_base;
212 public:
213 typedef typename Config::value_traits value_traits;
214 /// @cond
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;
222 /// @endcond
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;
249 /// @cond
250 private:
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;
256 //noncopyable
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 ||
268 // !floating_point
269 // ));
271 struct header_plus_alpha : public alpha_traits
272 { node header_; };
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)
288 , max_tree_size_(0)
290 node_plus_pred_t node_plus_pred_;
291 size_type max_tree_size_;
292 } data_;
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_; }
309 node &priv_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
328 { return data_; }
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>)
334 { return data_; }
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(); }
345 /// @endcond
347 public:
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.
358 //!
359 //! <b>Complexity</b>: Constant.
360 //!
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
376 //! [b, e).
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.
380 //!
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));
392 if(unique)
393 this->insert_unique(b, e);
394 else
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.
401 //!
402 //! <b>Complexity</b>: Linear to elements contained in *this.
403 //!
404 //! <b>Throws</b>: Nothing.
405 ~sgtree_impl()
408 //! <b>Effects</b>: Returns an iterator pointing to the beginning of the tree.
409 //!
410 //! <b>Complexity</b>: Constant.
411 //!
412 //! <b>Throws</b>: Nothing.
413 iterator begin()
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.
417 //!
418 //! <b>Complexity</b>: Constant.
419 //!
420 //! <b>Throws</b>: Nothing.
421 const_iterator begin() const
422 { return cbegin(); }
424 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
425 //!
426 //! <b>Complexity</b>: Constant.
427 //!
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.
433 //!
434 //! <b>Complexity</b>: Constant.
435 //!
436 //! <b>Throws</b>: Nothing.
437 iterator end()
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.
443 //!
444 //! <b>Throws</b>: Nothing.
445 const_iterator end() const
446 { return cend(); }
448 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
449 //!
450 //! <b>Complexity</b>: Constant.
451 //!
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
457 //! reversed tree.
458 //!
459 //! <b>Complexity</b>: Constant.
460 //!
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.
467 //!
468 //! <b>Complexity</b>: Constant.
469 //!
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.
476 //!
477 //! <b>Complexity</b>: Constant.
478 //!
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.
485 //!
486 //! <b>Complexity</b>: Constant.
487 //!
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.
494 //!
495 //! <b>Complexity</b>: Constant.
496 //!
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.
503 //!
504 //! <b>Complexity</b>: Constant.
505 //!
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
511 //! of sgtree.
512 //!
513 //! <b>Effects</b>: Returns a const reference to the sgtree associated to the end iterator
514 //!
515 //! <b>Throws</b>: Nothing.
516 //!
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
522 //! of sgtree.
523 //!
524 //! <b>Effects</b>: Returns a const reference to the sgtree associated to the end iterator
525 //!
526 //! <b>Throws</b>: Nothing.
527 //!
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
533 //! of rbtree.
534 //!
535 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
536 //!
537 //! <b>Throws</b>: Nothing.
538 //!
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
544 //! of rbtree.
545 //!
546 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
547 //!
548 //! <b>Throws</b>: Nothing.
549 //!
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.
555 //!
556 //! <b>Complexity</b>: Constant.
557 //!
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.
563 //!
564 //! <b>Complexity</b>: Constant.
565 //!
566 //! <b>Throws</b>: Nothing.
567 bool empty() const
568 { return node_algorithms::unique(const_node_ptr(&priv_header())); }
570 //! <b>Effects</b>: Returns the number of elements stored in the tree.
571 //!
572 //! <b>Complexity</b>: Linear to elements contained in *this
573 //! if constant-time size option is disabled. Constant time otherwise.
574 //!
575 //! <b>Throws</b>: Nothing.
576 size_type size() const
578 if(constant_time_size)
579 return this->priv_size_traits().get_size();
580 else{
581 return (size_type)node_algorithms::size(const_node_ptr(&priv_header()));
585 //! <b>Effects</b>: Swaps the contents of two sgtrees.
586 //!
587 //! <b>Complexity</b>: Constant.
588 //!
589 //! <b>Throws</b>: If the comparison functor's swap call throws.
590 void swap(sgtree_impl& other)
592 //This can throw
593 using std::swap;
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_);
597 //These can't throw
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
607 //!
608 //! <b>Effects</b>: Inserts value into the tree before the upper bound.
609 //!
610 //! <b>Complexity</b>: Average complexity for insert element is at
611 //! most logarithmic.
612 //!
613 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
614 //!
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.
635 //!
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)
639 //!
640 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
641 //! constant time if t is inserted immediately before hint.
642 //!
643 //! <b>Throws</b>: Nothing.
644 //!
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.
665 //!
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.
668 //!
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
671 //! by value_comp().
672 //!
673 //! <b>Throws</b>: Nothing.
674 //!
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());
681 for (; b != e; ++b)
682 this->insert_equal(end, *b);
685 //! <b>Requires</b>: value must be an lvalue
686 //!
687 //! <b>Effects</b>: Inserts value into the tree if the value
688 //! is not already present.
689 //!
690 //! <b>Complexity</b>: Average complexity for insert element is at
691 //! most logarithmic.
692 //!
693 //! <b>Throws</b>: Nothing.
694 //!
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);
701 if(!ret.second)
702 return ret;
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
707 //! a valid iterator
708 //!
709 //! <b>Effects</b>: Tries to insert x into the tree, using "hint" as a hint
710 //! to where it will be inserted.
711 //!
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.
715 //!
716 //! <b>Throws</b>: Nothing.
717 //!
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);
724 if(!ret.second)
725 return ret.first;
726 return insert_unique_commit(value, commit_data);
729 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
730 //! of type value_type.
731 //!
732 //! <b>Effects</b>: Tries to insert each element of a range into the tree.
733 //!
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
736 //! by value_comp().
737 //!
738 //! <b>Throws</b>: Nothing.
739 //!
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)
745 if(this->empty()){
746 iterator end(this->end());
747 for (; b != e; ++b)
748 this->insert_unique(end, *b);
750 else{
751 for (; b != e; ++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.
759 //!
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.
768 //!
769 //! <b>Complexity</b>: Average complexity is at most logarithmic.
771 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
772 //!
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.
801 //!
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.
811 //!
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.
816 //!
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)).
827 //!
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".
847 //!
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.
852 //!
853 //! <b>Complexity</b>: Constant time.
855 //! <b>Throws</b>: Nothing.
856 //!
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.
875 //!
876 //! <b>Complexity</b>: Average complexity for erase element is constant time.
877 //!
878 //! <b>Throws</b>: Nothing.
879 //!
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);
885 ++ret;
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.
901 //!
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.
904 //!
905 //! <b>Throws</b>: Nothing.
906 //!
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.
913 //!
914 //! <b>Returns</b>: The number of erased elements.
915 //!
916 //! <b>Complexity</b>: O(log(size() + N).
917 //!
918 //! <b>Throws</b>: Nothing.
919 //!
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.
929 //!
930 //! <b>Complexity</b>: O(log(size() + N).
931 //!
932 //! <b>Throws</b>: Nothing.
933 //!
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
938 /// @cond
939 , typename detail::enable_if_c<!detail::is_convertible<KeyValueCompare, const_iterator>::value >::type * = 0
940 /// @endcond
943 std::pair<iterator,iterator> p = this->equal_range(key, comp);
944 size_type n;
945 private_erase(p.first, p.second, n);
946 return 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.
953 //!
954 //! <b>Complexity</b>: Average complexity for erase element is constant time.
955 //!
956 //! <b>Throws</b>: Nothing.
957 //!
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));
966 return ret;
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); }
973 #endif
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.
979 //!
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.
982 //!
983 //! <b>Throws</b>: Nothing.
984 //!
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.
995 //!
996 //! <b>Returns</b>: The number of erased elements.
997 //!
998 //! <b>Complexity</b>: O(log(size() + N).
999 //!
1000 //! <b>Throws</b>: Nothing.
1001 //!
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);
1008 size_type n;
1009 private_erase(p.first, p.second, n, disposer);
1010 return n;
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.
1020 //!
1021 //! <b>Complexity</b>: O(log(size() + N).
1022 //!
1023 //! <b>Throws</b>: Nothing.
1024 //!
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
1029 /// @cond
1030 , typename detail::enable_if_c<!detail::is_convertible<KeyValueCompare, const_iterator>::value >::type * = 0
1031 /// @endcond
1034 std::pair<iterator,iterator> p = this->equal_range(key, comp);
1035 size_type n;
1036 private_erase(p.first, p.second, n, disposer);
1037 return n;
1040 //! <b>Effects</b>: Erases all of the elements.
1041 //!
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.
1044 //!
1045 //! <b>Throws</b>: Nothing.
1046 //!
1047 //! <b>Note</b>: Invalidates the iterators (but not the references)
1048 //! to the erased elements. No destructors are called.
1049 void clear()
1051 if(safemode_or_autounlink){
1052 this->clear_and_dispose(detail::null_disposer());
1054 else{
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.
1064 //!
1065 //! <b>Throws</b>: Nothing.
1066 //!
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
1079 //!
1080 //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal
1081 //! to number of objects with the given value.
1082 //!
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
1088 //!
1089 //! <b>Complexity</b>: Logarithmic to the number of elements contained plus lineal
1090 //! to number of objects with the given key.
1091 //!
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.
1102 //!
1103 //! <b>Complexity</b>: Logarithmic.
1104 //!
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.
1111 //!
1112 //! <b>Complexity</b>: Logarithmic.
1113 //!
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.
1120 //!
1121 //! <b>Complexity</b>: Logarithmic.
1122 //!
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.
1135 //!
1136 //! <b>Complexity</b>: Logarithmic.
1137 //!
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.
1150 //!
1151 //! <b>Complexity</b>: Logarithmic.
1152 //!
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
1159 //! does not exist.
1161 //! <b>Complexity</b>: Logarithmic.
1162 //!
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.
1175 //!
1176 //! <b>Complexity</b>: Logarithmic.
1177 //!
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
1184 //! does not exist.
1186 //! <b>Complexity</b>: Logarithmic.
1187 //!
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.
1202 //!
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.
1211 //!
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);
1218 return iterator
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.
1224 //!
1225 //! <b>Complexity</b>: Logarithmic.
1226 //!
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.
1233 //!
1234 //! <b>Complexity</b>: Logarithmic.
1235 //!
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.
1249 //!
1250 //! <b>Complexity</b>: Logarithmic.
1251 //!
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.
1259 //!
1260 //! <b>Complexity</b>: Logarithmic.
1261 //!
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.
1276 //!
1277 //! <b>Complexity</b>: Logarithmic.
1278 //!
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.
1287 //!
1288 //! <b>Complexity</b>: Logarithmic.
1289 //!
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).
1312 //!
1313 //! <b>Complexity</b>: Linear to erased plus inserted elements.
1314 //!
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);
1320 if(!src.empty()){
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();
1330 rollback.release();
1334 //! <b>Effects</b>: Unlinks the leftmost node from the tree.
1335 //!
1336 //! <b>Complexity</b>: Average complexity is constant time.
1337 //!
1338 //! <b>Throws</b>: Nothing.
1339 //!
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())));
1348 if(!to_be_disposed)
1349 return 0;
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.
1358 //!
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.
1361 //!
1362 //! <b>Complexity</b>: Constant.
1363 //!
1364 //! <b>Throws</b>: Nothing.
1365 //!
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.
1379 //!
1380 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1381 //! that points to the value
1382 //!
1383 //! <b>Complexity</b>: Constant.
1384 //!
1385 //! <b>Throws</b>: Nothing.
1386 //!
1387 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1388 //! is stateless.
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.
1397 //!
1398 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1399 //! set that points to the value
1400 //!
1401 //! <b>Complexity</b>: Constant.
1402 //!
1403 //! <b>Throws</b>: Nothing.
1404 //!
1405 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1406 //! is stateless.
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.
1415 //!
1416 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1417 //! that points to the value
1418 //!
1419 //! <b>Complexity</b>: Constant.
1420 //!
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.
1427 //!
1428 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1429 //! set that points to the value
1430 //!
1431 //! <b>Complexity</b>: Constant.
1432 //!
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.
1438 //!
1439 //! <b>Effects</b>: init_node puts the hook of a value in a well-known default
1440 //! state.
1441 //!
1442 //! <b>Throws</b>: Nothing.
1443 //!
1444 //! <b>Complexity</b>: Constant time.
1445 //!
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.
1452 //!
1453 //! <b>Throws</b>: Nothing.
1454 //!
1455 //! <b>Complexity</b>: Linear.
1456 void rebalance()
1457 { node_algorithms::rebalance(node_ptr(&priv_header())); }
1459 //! <b>Requires</b>: old_root is a node of a tree.
1460 //!
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.
1466 //!
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.
1474 //!
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
1480 //!
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.
1485 //!
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();
1500 this->rebalance();
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.
1506 //!
1507 //! <b>Throws</b>: Nothing.
1508 //!
1509 //! <b>Complexity</b>: Constant time.
1510 //!
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.
1516 template<class T>
1517 static void remove_node(T& value)
1519 //This function is only usable for safe mode hooks and non-constant
1520 //time lists.
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);
1531 /// @cond
1532 private:
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);
1538 return b.unconst();
1541 iterator private_erase(const_iterator b, const_iterator e, size_type &n)
1543 for(n = 0; b != e; ++n)
1544 this->erase(b++);
1545 return b.unconst();
1547 /// @endcond
1549 private:
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_);
1558 return *scapegoat;
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>
1567 #else
1568 template<class Config>
1569 #endif
1570 inline bool operator<
1571 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1572 (const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
1573 #else
1574 (const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
1575 #endif
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>
1580 #else
1581 template<class Config>
1582 #endif
1583 bool operator==
1584 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1585 (const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
1586 #else
1587 (const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
1588 #endif
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()){
1594 return false;
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) {
1601 ++i1;
1602 ++i2;
1604 return i1 == end1;
1606 else{
1607 const_iterator end2 = y.end();
1608 while (i1 != end1 && i2 != end2 && *i1 == *i2) {
1609 ++i1;
1610 ++i2;
1612 return i1 == end1 && i2 == end2;
1616 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1617 template<class T, class ...Options>
1618 #else
1619 template<class Config>
1620 #endif
1621 inline bool operator!=
1622 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1623 (const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
1624 #else
1625 (const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
1626 #endif
1627 { return !(x == y); }
1629 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1630 template<class T, class ...Options>
1631 #else
1632 template<class Config>
1633 #endif
1634 inline bool operator>
1635 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1636 (const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
1637 #else
1638 (const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
1639 #endif
1640 { return y < x; }
1642 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1643 template<class T, class ...Options>
1644 #else
1645 template<class Config>
1646 #endif
1647 inline bool operator<=
1648 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1649 (const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
1650 #else
1651 (const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
1652 #endif
1653 { return !(y < x); }
1655 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1656 template<class T, class ...Options>
1657 #else
1658 template<class Config>
1659 #endif
1660 inline bool operator>=
1661 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1662 (const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
1663 #else
1664 (const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
1665 #endif
1666 { return !(x < y); }
1668 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1669 template<class T, class ...Options>
1670 #else
1671 template<class Config>
1672 #endif
1673 inline void swap
1674 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1675 (sgtree_impl<T, Options...> &x, sgtree_impl<T, Options...> &y)
1676 #else
1677 (sgtree_impl<Config> &x, sgtree_impl<Config> &y)
1678 #endif
1679 { x.swap(y); }
1681 /// @cond
1682 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1683 template<class T, class O1 = none, class O2 = none
1684 , class O3 = none, class O4 = none>
1685 #else
1686 template<class T, class ...Options>
1687 #endif
1688 struct make_sgtree_opt
1690 typedef typename pack_options
1691 < sg_set_defaults<T>,
1692 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1693 O1, O2, O3, O4
1694 #else
1695 Options...
1696 #endif
1697 >::type packed_options;
1698 typedef typename detail::get_value_traits
1699 <T, typename packed_options::value_traits>::type value_traits;
1701 typedef sg_setopt
1702 < value_traits
1703 , typename packed_options::compare
1704 , typename packed_options::size_type
1705 , packed_options::floating_point
1706 > type;
1708 /// @endcond
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>
1714 #else
1715 template<class T, class O1 = none, class O2 = none
1716 , class O3 = none, class O4 = none>
1717 #endif
1718 struct make_sgtree
1720 /// @cond
1721 typedef sgtree_impl
1722 < typename make_sgtree_opt<T,
1723 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1724 O1, O2, O3, O4
1725 #else
1726 Options...
1727 #endif
1728 >::type
1729 > implementation_defined;
1730 /// @endcond
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>
1737 #else
1738 template<class T, class ...Options>
1739 #endif
1740 class sgtree
1741 : public make_sgtree<T,
1742 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1743 O1, O2, O3, O4
1744 #else
1745 Options...
1746 #endif
1747 >::type
1749 typedef typename make_sgtree
1750 <T,
1751 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1752 O1, O2, O3, O4
1753 #else
1754 Options...
1755 #endif
1756 >::type Base;
1758 public:
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)); }
1787 #endif
1790 } //namespace intrusive
1791 } //namespace boost
1793 #include <boost/intrusive/detail/config_end.hpp>
1795 #endif //BOOST_INTRUSIVE_SGTREE_HPP