fix doc example typo
[boost.git] / boost / intrusive / splaytree.hpp
blob971f8461faa0a3a8c36c7b84a558dfedcc059607
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 /////////////////////////////////////////////////////////////////////////////
12 #ifndef BOOST_INTRUSIVE_SPLAYTREE_HPP
13 #define BOOST_INTRUSIVE_SPLAYTREE_HPP
15 #include <boost/intrusive/detail/config_begin.hpp>
16 #include <functional>
17 #include <iterator>
18 #include <utility>
19 #include <cstddef>
20 #include <algorithm>
21 #include <boost/intrusive/detail/assert.hpp>
22 #include <boost/static_assert.hpp>
23 #include <boost/intrusive/intrusive_fwd.hpp>
24 #include <boost/intrusive/detail/pointer_to_other.hpp>
25 #include <boost/intrusive/splay_set_hook.hpp>
26 #include <boost/intrusive/detail/tree_node.hpp>
27 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
28 #include <boost/intrusive/detail/clear_on_destructor_base.hpp>
29 #include <boost/intrusive/detail/mpl.hpp>
30 #include <boost/intrusive/options.hpp>
31 #include <boost/intrusive/splaytree_algorithms.hpp>
32 #include <boost/intrusive/link_mode.hpp>
35 namespace boost {
36 namespace intrusive {
38 /// @cond
40 template <class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize>
41 struct splaysetopt
43 typedef ValueTraits value_traits;
44 typedef Compare compare;
45 typedef SizeType size_type;
46 static const bool constant_time_size = ConstantTimeSize;
49 template <class T>
50 struct splay_set_defaults
51 : pack_options
52 < none
53 , base_hook<detail::default_splay_set_hook>
54 , constant_time_size<true>
55 , size_type<std::size_t>
56 , compare<std::less<T> >
57 >::type
58 {};
60 /// @endcond
62 //! The class template splaytree is an intrusive splay tree container that
63 //! is used to construct intrusive splay_set and splay_multiset containers. The no-throw
64 //! guarantee holds only, if the value_compare object
65 //! doesn't throw.
66 //!
67 //! The template parameter \c T is the type to be managed by the container.
68 //! The user can specify additional options and if no options are provided
69 //! default options are used.
70 //!
71 //! The container supports the following options:
72 //! \c base_hook<>/member_hook<>/value_traits<>,
73 //! \c constant_time_size<>, \c size_type<> and
74 //! \c compare<>.
75 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
76 template<class T, class ...Options>
77 #else
78 template<class Config>
79 #endif
80 class splaytree_impl
81 : private detail::clear_on_destructor_base<splaytree_impl<Config> >
83 template<class C> friend class detail::clear_on_destructor_base;
84 public:
85 typedef typename Config::value_traits value_traits;
86 /// @cond
87 static const bool external_value_traits =
88 detail::external_value_traits_is_true<value_traits>::value;
89 typedef typename detail::eval_if_c
90 < external_value_traits
91 , detail::eval_value_traits<value_traits>
92 , detail::identity<value_traits>
93 >::type real_value_traits;
94 /// @endcond
95 typedef typename real_value_traits::pointer pointer;
96 typedef typename real_value_traits::const_pointer const_pointer;
97 typedef typename std::iterator_traits<pointer>::value_type value_type;
98 typedef value_type key_type;
99 typedef typename std::iterator_traits<pointer>::reference reference;
100 typedef typename std::iterator_traits<const_pointer>::reference const_reference;
101 typedef typename std::iterator_traits<pointer>::difference_type difference_type;
102 typedef typename Config::size_type size_type;
103 typedef typename Config::compare value_compare;
104 typedef value_compare key_compare;
105 typedef tree_iterator<splaytree_impl, false> iterator;
106 typedef tree_iterator<splaytree_impl, true> const_iterator;
107 typedef std::reverse_iterator<iterator> reverse_iterator;
108 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
109 typedef typename real_value_traits::node_traits node_traits;
110 typedef typename node_traits::node node;
111 typedef typename boost::pointer_to_other
112 <pointer, node>::type node_ptr;
113 typedef typename boost::pointer_to_other
114 <node_ptr, const node>::type const_node_ptr;
115 typedef splaytree_algorithms<node_traits> node_algorithms;
117 static const bool constant_time_size = Config::constant_time_size;
118 static const bool stateful_value_traits = detail::store_cont_ptr_on_it<splaytree_impl>::value;
120 /// @cond
121 private:
122 typedef detail::size_holder<constant_time_size, size_type> size_traits;
124 //noncopyable
125 splaytree_impl (const splaytree_impl&);
126 splaytree_impl operator =(const splaytree_impl&);
128 enum { safemode_or_autounlink =
129 (int)real_value_traits::link_mode == (int)auto_unlink ||
130 (int)real_value_traits::link_mode == (int)safe_link };
132 //Constant-time size is incompatible with auto-unlink hooks!
133 BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink)));
135 struct header_plus_size : public size_traits
136 { node header_; };
138 struct node_plus_pred_t : public detail::ebo_functor_holder<value_compare>
140 node_plus_pred_t(const value_compare &comp)
141 : detail::ebo_functor_holder<value_compare>(comp)
143 header_plus_size header_plus_size_;
146 struct data_t : public splaytree_impl::value_traits
148 typedef typename splaytree_impl::value_traits value_traits;
149 data_t(const value_compare & comp, const value_traits &val_traits)
150 : value_traits(val_traits), node_plus_pred_(comp)
152 node_plus_pred_t node_plus_pred_;
153 } data_;
155 const value_compare &priv_comp() const
156 { return data_.node_plus_pred_.get(); }
158 value_compare &priv_comp()
159 { return data_.node_plus_pred_.get(); }
161 const node &priv_header() const
162 { return data_.node_plus_pred_.header_plus_size_.header_; }
164 node &priv_header()
165 { return data_.node_plus_pred_.header_plus_size_.header_; }
167 static node_ptr uncast(const_node_ptr ptr)
169 return node_ptr(const_cast<node*>(detail::get_pointer(ptr)));
172 size_traits &priv_size_traits()
173 { return data_.node_plus_pred_.header_plus_size_; }
175 const size_traits &priv_size_traits() const
176 { return data_.node_plus_pred_.header_plus_size_; }
178 const real_value_traits &get_real_value_traits(detail::bool_<false>) const
179 { return data_; }
181 const real_value_traits &get_real_value_traits(detail::bool_<true>) const
182 { return data_.get_value_traits(*this); }
184 real_value_traits &get_real_value_traits(detail::bool_<false>)
185 { return data_; }
187 real_value_traits &get_real_value_traits(detail::bool_<true>)
188 { return data_.get_value_traits(*this); }
190 /// @endcond
192 public:
194 const real_value_traits &get_real_value_traits() const
195 { return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
197 real_value_traits &get_real_value_traits()
198 { return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
200 typedef typename node_algorithms::insert_commit_data insert_commit_data;
202 //! <b>Effects</b>: Constructs an empty tree.
203 //!
204 //! <b>Complexity</b>: Constant.
205 //!
206 //! <b>Throws</b>: If value_traits::node_traits::node
207 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
208 //! or the copy constructorof the value_compare object throws. Basic guarantee.
209 splaytree_impl( const value_compare &cmp = value_compare()
210 , const value_traits &v_traits = value_traits())
211 : data_(cmp, v_traits)
213 node_algorithms::init_header(&priv_header());
214 this->priv_size_traits().set_size(size_type(0));
217 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
218 //! cmp must be a comparison function that induces a strict weak ordering.
220 //! <b>Effects</b>: Constructs an empty tree and inserts elements from
221 //! [b, e).
223 //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using
224 //! comp and otherwise amortized N * log N, where N is the distance between first and last.
225 //!
226 //! <b>Throws</b>: If value_traits::node_traits::node
227 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
228 //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee.
229 template<class Iterator>
230 splaytree_impl ( bool unique, Iterator b, Iterator e
231 , const value_compare &cmp = value_compare()
232 , const value_traits &v_traits = value_traits())
233 : data_(cmp, v_traits)
235 node_algorithms::init_header(&priv_header());
236 this->priv_size_traits().set_size(size_type(0));
237 if(unique)
238 this->insert_unique(b, e);
239 else
240 this->insert_equal(b, e);
243 //! <b>Effects</b>: Detaches all elements from this. The objects in the set
244 //! are not deleted (i.e. no destructors are called), but the nodes according to
245 //! the value_traits template parameter are reinitialized and thus can be reused.
246 //!
247 //! <b>Complexity</b>: Linear to the number of elements on the container.
248 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
249 //!
250 //! <b>Throws</b>: Nothing.
251 ~splaytree_impl()
254 //! <b>Effects</b>: Returns an iterator pointing to the beginning of the tree.
255 //!
256 //! <b>Complexity</b>: Constant.
257 //!
258 //! <b>Throws</b>: Nothing.
259 iterator begin()
260 { return iterator(node_algorithms::begin_node(&priv_header()), this); }
262 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
263 //!
264 //! <b>Complexity</b>: Constant.
265 //!
266 //! <b>Throws</b>: Nothing.
267 const_iterator begin() const
268 { return cbegin(); }
270 //! <b>Effects</b>: Returns a const_iterator pointing to the beginning of the tree.
271 //!
272 //! <b>Complexity</b>: Constant.
273 //!
274 //! <b>Throws</b>: Nothing.
275 const_iterator cbegin() const
276 { return const_iterator(node_algorithms::begin_node(&priv_header()), this); }
278 //! <b>Effects</b>: Returns an iterator pointing to the end of the tree.
279 //!
280 //! <b>Complexity</b>: Constant.
281 //!
282 //! <b>Throws</b>: Nothing.
283 iterator end()
284 { return iterator (node_ptr(&priv_header()), this); }
286 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
288 //! <b>Complexity</b>: Constant.
289 //!
290 //! <b>Throws</b>: Nothing.
291 const_iterator end() const
292 { return cend(); }
294 //! <b>Effects</b>: Returns a const_iterator pointing to the end of the tree.
295 //!
296 //! <b>Complexity</b>: Constant.
297 //!
298 //! <b>Throws</b>: Nothing.
299 const_iterator cend() const
300 { return const_iterator (uncast(const_node_ptr(&priv_header())), this); }
302 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning of the
303 //! reversed tree.
304 //!
305 //! <b>Complexity</b>: Constant.
306 //!
307 //! <b>Throws</b>: Nothing.
308 reverse_iterator rbegin()
309 { return reverse_iterator(end()); }
311 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
312 //! of the reversed tree.
313 //!
314 //! <b>Complexity</b>: Constant.
315 //!
316 //! <b>Throws</b>: Nothing.
317 const_reverse_iterator rbegin() const
318 { return const_reverse_iterator(end()); }
320 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
321 //! of the reversed tree.
322 //!
323 //! <b>Complexity</b>: Constant.
324 //!
325 //! <b>Throws</b>: Nothing.
326 const_reverse_iterator crbegin() const
327 { return const_reverse_iterator(end()); }
329 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
330 //! of the reversed tree.
331 //!
332 //! <b>Complexity</b>: Constant.
333 //!
334 //! <b>Throws</b>: Nothing.
335 reverse_iterator rend()
336 { return reverse_iterator(begin()); }
338 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
339 //! of the reversed tree.
340 //!
341 //! <b>Complexity</b>: Constant.
342 //!
343 //! <b>Throws</b>: Nothing.
344 const_reverse_iterator rend() const
345 { return const_reverse_iterator(begin()); }
347 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
348 //! of the reversed tree.
349 //!
350 //! <b>Complexity</b>: Constant.
351 //!
352 //! <b>Throws</b>: Nothing.
353 const_reverse_iterator crend() const
354 { return const_reverse_iterator(begin()); }
356 //! <b>Precondition</b>: end_iterator must be a valid end iterator
357 //! of splaytree.
358 //!
359 //! <b>Effects</b>: Returns a const reference to the splaytree associated to the end iterator
360 //!
361 //! <b>Throws</b>: Nothing.
362 //!
363 //! <b>Complexity</b>: Constant.
364 static splaytree_impl &container_from_end_iterator(iterator end_iterator)
365 { return priv_container_from_end_iterator(end_iterator); }
367 //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
368 //! of splaytree.
369 //!
370 //! <b>Effects</b>: Returns a const reference to the splaytree associated to the end iterator
371 //!
372 //! <b>Throws</b>: Nothing.
373 //!
374 //! <b>Complexity</b>: Constant.
375 static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator)
376 { return priv_container_from_end_iterator(end_iterator); }
378 //! <b>Precondition</b>: it must be a valid iterator
379 //! of rbtree.
380 //!
381 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
382 //!
383 //! <b>Throws</b>: Nothing.
384 //!
385 //! <b>Complexity</b>: Logarithmic.
386 static splaytree_impl &container_from_iterator(iterator it)
387 { return priv_container_from_iterator(it); }
389 //! <b>Precondition</b>: it must be a valid end const_iterator
390 //! of rbtree.
391 //!
392 //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
393 //!
394 //! <b>Throws</b>: Nothing.
395 //!
396 //! <b>Complexity</b>: Logarithmic.
397 static const splaytree_impl &container_from_iterator(const_iterator it)
398 { return priv_container_from_iterator(it); }
400 //! <b>Effects</b>: Returns the value_compare object used by the tree.
401 //!
402 //! <b>Complexity</b>: Constant.
403 //!
404 //! <b>Throws</b>: If value_compare copy-constructor throws.
405 value_compare value_comp() const
406 { return priv_comp(); }
408 //! <b>Effects</b>: Returns true if the container is empty.
409 //!
410 //! <b>Complexity</b>: Constant.
411 //!
412 //! <b>Throws</b>: Nothing.
413 bool empty() const
414 { return this->cbegin() == this->cend(); }
416 //! <b>Effects</b>: Returns the number of elements stored in the tree.
417 //!
418 //! <b>Complexity</b>: Linear to elements contained in *this
419 //! if constant-time size option is disabled. Constant time otherwise.
420 //!
421 //! <b>Throws</b>: Nothing.
422 size_type size() const
424 if(constant_time_size){
425 return this->priv_size_traits().get_size();
427 else{
428 return (size_type)node_algorithms::size(const_node_ptr(&priv_header()));
432 //! <b>Effects</b>: Swaps the contents of two splaytrees.
433 //!
434 //! <b>Complexity</b>: Constant.
435 //!
436 //! <b>Throws</b>: If the comparison functor's swap call throws.
437 void swap(splaytree_impl& other)
439 //This can throw
440 using std::swap;
441 swap(priv_comp(), priv_comp());
442 //These can't throw
443 node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other.priv_header()));
444 if(constant_time_size){
445 size_type backup = this->priv_size_traits().get_size();
446 this->priv_size_traits().set_size(other.priv_size_traits().get_size());
447 other.priv_size_traits().set_size(backup);
451 //! <b>Requires</b>: value must be an lvalue
452 //!
453 //! <b>Effects</b>: Inserts value into the tree before the lower bound.
454 //!
455 //! <b>Complexity</b>: Average complexity for insert element is amortized
456 //! logarithmic.
457 //!
458 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
459 //!
460 //! <b>Note</b>: Does not affect the validity of iterators and references.
461 //! No copy-constructors are called.
462 iterator insert_equal(reference value)
464 detail::key_nodeptr_comp<value_compare, splaytree_impl>
465 key_node_comp(priv_comp(), this);
466 node_ptr to_insert(get_real_value_traits().to_node_ptr(value));
467 if(safemode_or_autounlink)
468 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
469 this->priv_size_traits().increment();
470 return iterator(node_algorithms::insert_equal_lower_bound
471 (node_ptr(&priv_header()), to_insert, key_node_comp), this);
474 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
475 //! a valid iterator.
476 //!
477 //! <b>Effects</b>: Inserts x into the tree, using "hint" as a hint to
478 //! where it will be inserted. If "hint" is the upper_bound
479 //! the insertion takes constant time (two comparisons in the worst case)
480 //!
481 //! <b>Complexity</b>: Amortized logarithmic in general, but it is amortized
482 //! constant time if t is inserted immediately before hint.
483 //!
484 //! <b>Throws</b>: If the internal value_compare ordering function throws. Strong guarantee.
485 //!
486 //! <b>Note</b>: Does not affect the validity of iterators and references.
487 //! No copy-constructors are called.
488 iterator insert_equal(const_iterator hint, reference value)
490 detail::key_nodeptr_comp<value_compare, splaytree_impl>
491 key_node_comp(priv_comp(), this);
492 node_ptr to_insert(get_real_value_traits().to_node_ptr(value));
493 if(safemode_or_autounlink)
494 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
495 this->priv_size_traits().increment();
496 return iterator(node_algorithms::insert_equal
497 (node_ptr(&priv_header()), hint.pointed_node(), to_insert, key_node_comp), this);
500 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
501 //! of type value_type.
502 //!
503 //! <b>Effects</b>: Inserts a each element of a range into the tree
504 //! before the upper bound of the key of each element.
505 //!
506 //! <b>Complexity</b>: Insert range is in general amortized O(N * log(N)), where N is the
507 //! size of the range. However, it is linear in N if the range is already sorted
508 //! by value_comp().
509 //!
510 //! <b>Throws</b>: Nothing.
511 //!
512 //! <b>Note</b>: Does not affect the validity of iterators and references.
513 //! No copy-constructors are called.
514 template<class Iterator>
515 void insert_equal(Iterator b, Iterator e)
517 if(this->empty()){
518 iterator end(this->end());
519 for (; b != e; ++b)
520 this->insert_equal(end, *b);
524 //! <b>Requires</b>: value must be an lvalue
525 //!
526 //! <b>Effects</b>: Inserts value into the tree if the value
527 //! is not already present.
528 //!
529 //! <b>Complexity</b>: Amortized logarithmic.
530 //!
531 //! <b>Throws</b>: Nothing.
532 //!
533 //! <b>Note</b>: Does not affect the validity of iterators and references.
534 //! No copy-constructors are called.
535 std::pair<iterator, bool> insert_unique(reference value)
537 insert_commit_data commit_data;
538 std::pair<iterator, bool> ret = insert_unique_check(value, priv_comp(), commit_data);
539 if(!ret.second)
540 return ret;
541 return std::pair<iterator, bool> (insert_unique_commit(value, commit_data), true);
544 //! <b>Requires</b>: value must be an lvalue, and "hint" must be
545 //! a valid iterator
546 //!
547 //! <b>Effects</b>: Tries to insert x into the tree, using "hint" as a hint
548 //! to where it will be inserted.
549 //!
550 //! <b>Complexity</b>: Amortized logarithmic in general, but it is amortized
551 //! constant time (two comparisons in the worst case)
552 //! if t is inserted immediately before hint.
553 //!
554 //! <b>Throws</b>: Nothing.
555 //!
556 //! <b>Note</b>: Does not affect the validity of iterators and references.
557 //! No copy-constructors are called.
558 iterator insert_unique(const_iterator hint, reference value)
560 insert_commit_data commit_data;
561 std::pair<iterator, bool> ret = insert_unique_check(hint, value, priv_comp(), commit_data);
562 if(!ret.second)
563 return ret.first;
564 return insert_unique_commit(value, commit_data);
567 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
568 //! of type value_type.
569 //!
570 //! <b>Effects</b>: Tries to insert each element of a range into the tree.
571 //!
572 //! <b>Complexity</b>: Insert range is in general amortized O(N * log(N)), where N is the
573 //! size of the range. However, it is linear in N if the range is already sorted
574 //! by value_comp().
575 //!
576 //! <b>Throws</b>: Nothing.
577 //!
578 //! <b>Note</b>: Does not affect the validity of iterators and references.
579 //! No copy-constructors are called.
580 template<class Iterator>
581 void insert_unique(Iterator b, Iterator e)
583 for (; b != e; ++b)
584 this->insert_unique(*b);
587 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
588 //! the same strict weak ordering as value_compare. The difference is that
589 //! key_value_comp compares an arbitrary key with the contained values.
590 //!
591 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
592 //! a user provided key instead of the value itself.
594 //! <b>Returns</b>: If there is an equivalent value
595 //! returns a pair containing an iterator to the already present value
596 //! and false. If the value can be inserted returns true in the returned
597 //! pair boolean and fills "commit_data" that is meant to be used with
598 //! the "insert_commit" function.
599 //!
600 //! <b>Complexity</b>: Average complexity is at most logarithmic.
602 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
603 //!
604 //! <b>Notes</b>: This function is used to improve performance when constructing
605 //! a value_type is expensive: if there is an equivalent value
606 //! the constructed object must be discarded. Many times, the part of the
607 //! node that is used to impose the order is much cheaper to construct
608 //! than the value_type and this function offers the possibility to use that
609 //! part to check if the insertion will be successful.
611 //! If the check is successful, the user can construct the value_type and use
612 //! "insert_commit" to insert the object in constant-time. This gives a total
613 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
615 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
616 //! objects are inserted or erased from the container.
617 template<class KeyType, class KeyValueCompare>
618 std::pair<iterator, bool> insert_unique_check
619 (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data)
621 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
622 comp(key_value_comp, this);
623 std::pair<node_ptr, bool> ret =
624 (node_algorithms::insert_unique_check
625 (node_ptr(&priv_header()), key, comp, commit_data));
626 return std::pair<iterator, bool>(iterator(ret.first, this), ret.second);
629 //! <b>Requires</b>: key_value_comp must be a comparison function that induces
630 //! the same strict weak ordering as value_compare. The difference is that
631 //! key_value_comp compares an arbitrary key with the contained values.
632 //!
633 //! <b>Effects</b>: Checks if a value can be inserted in the container, using
634 //! a user provided key instead of the value itself, using "hint"
635 //! as a hint to where it will be inserted.
637 //! <b>Returns</b>: If there is an equivalent value
638 //! returns a pair containing an iterator to the already present value
639 //! and false. If the value can be inserted returns true in the returned
640 //! pair boolean and fills "commit_data" that is meant to be used with
641 //! the "insert_commit" function.
642 //!
643 //! <b>Complexity</b>: Logarithmic in general, but it's amortized
644 //! constant time if t is inserted immediately before hint.
646 //! <b>Throws</b>: If the key_value_comp ordering function throws. Strong guarantee.
647 //!
648 //! <b>Notes</b>: This function is used to improve performance when constructing
649 //! a value_type is expensive: if there is an equivalent value
650 //! the constructed object must be discarded. Many times, the part of the
651 //! constructing that is used to impose the order is much cheaper to construct
652 //! than the value_type and this function offers the possibility to use that key
653 //! to check if the insertion will be successful.
655 //! If the check is successful, the user can construct the value_type and use
656 //! "insert_commit" to insert the object in constant-time. This can give a total
657 //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)).
658 //!
659 //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
660 //! objects are inserted or erased from the container.
661 template<class KeyType, class KeyValueCompare>
662 std::pair<iterator, bool> insert_unique_check
663 (const_iterator hint, const KeyType &key
664 ,KeyValueCompare key_value_comp, insert_commit_data &commit_data)
666 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
667 comp(key_value_comp, this);
668 std::pair<node_ptr, bool> ret =
669 node_algorithms::insert_unique_check
670 (node_ptr(&priv_header()), hint.pointed_node(), key, comp, commit_data);
671 return std::pair<iterator, bool>(iterator(ret.first, this), ret.second);
674 //! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
675 //! must have been obtained from a previous call to "insert_check".
676 //! No objects should have been inserted or erased from the container between
677 //! the "insert_check" that filled "commit_data" and the call to "insert_commit".
678 //!
679 //! <b>Effects</b>: Inserts the value in the avl_set using the information obtained
680 //! from the "commit_data" that a previous "insert_check" filled.
682 //! <b>Returns</b>: An iterator to the newly inserted object.
683 //!
684 //! <b>Complexity</b>: Constant time.
686 //! <b>Throws</b>: Nothing.
687 //!
688 //! <b>Notes</b>: This function has only sense if a "insert_check" has been
689 //! previously executed to fill "commit_data". No value should be inserted or
690 //! erased between the "insert_check" and "insert_commit" calls.
691 iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
693 node_ptr to_insert(get_real_value_traits().to_node_ptr(value));
694 if(safemode_or_autounlink)
695 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
696 this->priv_size_traits().increment();
697 node_algorithms::insert_unique_commit
698 (node_ptr(&priv_header()), to_insert, commit_data);
699 return iterator(to_insert, this);
702 //! <b>Effects</b>: Erases the element pointed to by pos.
703 //!
704 //! <b>Complexity</b>: Average complexity for erase element is constant time.
705 //!
706 //! <b>Throws</b>: Nothing.
707 //!
708 //! <b>Note</b>: Invalidates the iterators (but not the references)
709 //! to the erased elements. No destructors are called.
710 iterator erase(const_iterator i)
712 const_iterator ret(i);
713 ++ret;
714 node_ptr to_erase(i.pointed_node());
715 if(safemode_or_autounlink)
716 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase));
717 node_algorithms::erase(&priv_header(), to_erase);
718 this->priv_size_traits().decrement();
719 if(safemode_or_autounlink)
720 node_algorithms::init(to_erase);
721 return ret.unconst();
724 //! <b>Effects</b>: Erases the range pointed to by b end e.
725 //!
726 //! <b>Complexity</b>: Average complexity for erase range is amortized
727 //! O(log(size() + N)), where N is the number of elements in the range.
728 //!
729 //! <b>Throws</b>: Nothing.
730 //!
731 //! <b>Note</b>: Invalidates the iterators (but not the references)
732 //! to the erased elements. No destructors are called.
733 iterator erase(const_iterator b, const_iterator e)
734 { size_type n; return private_erase(b, e, n); }
736 //! <b>Effects</b>: Erases all the elements with the given value.
737 //!
738 //! <b>Returns</b>: The number of erased elements.
739 //!
740 //! <b>Complexity</b>: Amortized O(log(size() + N).
741 //!
742 //! <b>Throws</b>: Nothing.
743 //!
744 //! <b>Note</b>: Invalidates the iterators (but not the references)
745 //! to the erased elements. No destructors are called.
746 size_type erase(const_reference value)
747 { return this->erase(value, priv_comp()); }
749 //! <b>Effects</b>: Erases all the elements with the given key.
750 //! according to the comparison functor "comp".
752 //! <b>Returns</b>: The number of erased elements.
753 //!
754 //! <b>Complexity</b>: Amortized O(log(size() + N).
755 //!
756 //! <b>Throws</b>: Nothing.
757 //!
758 //! <b>Note</b>: Invalidates the iterators (but not the references)
759 //! to the erased elements. No destructors are called.
760 template<class KeyType, class KeyValueCompare>
761 size_type erase(const KeyType& key, KeyValueCompare comp
762 /// @cond
763 , typename detail::enable_if_c<!detail::is_convertible<KeyValueCompare, const_iterator>::value >::type * = 0
764 /// @endcond
767 std::pair<iterator,iterator> p = this->equal_range(key, comp);
768 size_type n;
769 private_erase(p.first, p.second, n);
770 return n;
773 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
775 //! <b>Effects</b>: Erases the element pointed to by pos.
776 //! Disposer::operator()(pointer) is called for the removed element.
777 //!
778 //! <b>Complexity</b>: Average complexity for erase element is constant time.
779 //!
780 //! <b>Throws</b>: Nothing.
781 //!
782 //! <b>Note</b>: Invalidates the iterators
783 //! to the erased elements.
784 template<class Disposer>
785 iterator erase_and_dispose(const_iterator i, Disposer disposer)
787 node_ptr to_erase(i.pointed_node());
788 iterator ret(this->erase(i));
789 disposer(get_real_value_traits().to_value_ptr(to_erase));
790 return ret;
793 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
794 template<class Disposer>
795 iterator erase_and_dispose(iterator i, Disposer disposer)
796 { return this->erase_and_dispose(const_iterator(i), disposer); }
797 #endif
799 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
801 //! <b>Effects</b>: Erases the range pointed to by b end e.
802 //! Disposer::operator()(pointer) is called for the removed elements.
803 //!
804 //! <b>Complexity</b>: Average complexity for erase range is amortized
805 //! O(log(size() + N)), where N is the number of elements in the range.
806 //!
807 //! <b>Throws</b>: Nothing.
808 //!
809 //! <b>Note</b>: Invalidates the iterators
810 //! to the erased elements.
811 template<class Disposer>
812 iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer)
813 { size_type n; return private_erase(b, e, n, disposer); }
815 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
817 //! <b>Effects</b>: Erases all the elements with the given value.
818 //! Disposer::operator()(pointer) is called for the removed elements.
819 //!
820 //! <b>Returns</b>: The number of erased elements.
821 //!
822 //! <b>Complexity</b>: Amortized O(log(size() + N).
823 //!
824 //! <b>Throws</b>: Nothing.
825 //!
826 //! <b>Note</b>: Invalidates the iterators (but not the references)
827 //! to the erased elements. No destructors are called.
828 template<class Disposer>
829 size_type erase_and_dispose(const_reference value, Disposer disposer)
831 std::pair<iterator,iterator> p = this->equal_range(value);
832 size_type n;
833 private_erase(p.first, p.second, n, disposer);
834 return n;
837 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
839 //! <b>Effects</b>: Erases all the elements with the given key.
840 //! according to the comparison functor "comp".
841 //! Disposer::operator()(pointer) is called for the removed elements.
843 //! <b>Returns</b>: The number of erased elements.
844 //!
845 //! <b>Complexity</b>: Amortized O(log(size() + N).
846 //!
847 //! <b>Throws</b>: Nothing.
848 //!
849 //! <b>Note</b>: Invalidates the iterators
850 //! to the erased elements.
851 template<class KeyType, class KeyValueCompare, class Disposer>
852 size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer
853 /// @cond
854 , typename detail::enable_if_c<!detail::is_convertible<KeyValueCompare, const_iterator>::value >::type * = 0
855 /// @endcond
858 std::pair<iterator,iterator> p = this->equal_range(key, comp);
859 size_type n;
860 private_erase(p.first, p.second, n, disposer);
861 return n;
864 //! <b>Effects</b>: Erases all of the elements.
865 //!
866 //! <b>Complexity</b>: Linear to the number of elements on the container.
867 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
868 //!
869 //! <b>Throws</b>: Nothing.
870 //!
871 //! <b>Note</b>: Invalidates the iterators (but not the references)
872 //! to the erased elements. No destructors are called.
873 void clear()
875 if(safemode_or_autounlink){
876 this->clear_and_dispose(detail::null_disposer());
878 else{
879 node_algorithms::init_header(&priv_header());
880 this->priv_size_traits().set_size(0);
884 //! <b>Effects</b>: Erases all of the elements calling disposer(p) for
885 //! each node to be erased.
886 //! <b>Complexity</b>: Amortized O(log(size() + N)),
887 //! where N is the number of elements in the container.
888 //!
889 //! <b>Throws</b>: Nothing.
890 //!
891 //! <b>Note</b>: Invalidates the iterators (but not the references)
892 //! to the erased elements. Calls N times to disposer functor.
893 template<class Disposer>
894 void clear_and_dispose(Disposer disposer)
896 node_algorithms::clear_and_dispose(node_ptr(&priv_header())
897 , detail::node_disposer<Disposer, splaytree_impl>(disposer, this));
898 node_algorithms::init_header(&priv_header());
899 this->priv_size_traits().set_size(0);
902 //! <b>Effects</b>: Returns the number of contained elements with the given value
903 //!
904 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
905 //! to number of objects with the given value.
906 //!
907 //! <b>Throws</b>: Nothing.
908 size_type count(const_reference value)
909 { return this->count(value, priv_comp()); }
911 //! <b>Effects</b>: Returns the number of contained elements with the given key
912 //!
913 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
914 //! to number of objects with the given key.
915 //!
916 //! <b>Throws</b>: Nothing.
917 template<class KeyType, class KeyValueCompare>
918 size_type count(const KeyType &key, KeyValueCompare comp)
920 std::pair<const_iterator, const_iterator> ret = this->equal_range(key, comp);
921 return std::distance(ret.first, ret.second);
924 //! <b>Effects</b>: Returns the number of contained elements with the given value
925 //!
926 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
927 //! to number of objects with the given value.
928 //!
929 //! <b>Throws</b>: Nothing.
930 size_type count_dont_splay(const_reference value) const
931 { return this->count_dont_splay(value, priv_comp()); }
933 //! <b>Effects</b>: Returns the number of contained elements with the given key
934 //!
935 //! <b>Complexity</b>: Amortized logarithmic to the number of elements contained plus lineal
936 //! to number of objects with the given key.
937 //!
938 //! <b>Throws</b>: Nothing.
939 template<class KeyType, class KeyValueCompare>
940 size_type count_dont_splay(const KeyType &key, KeyValueCompare comp) const
942 std::pair<const_iterator, const_iterator> ret = this->equal_range_dont_splay(key, comp);
943 return std::distance(ret.first, ret.second);
946 //! <b>Effects</b>: Returns an iterator to the first element whose
947 //! key is not less than k or end() if that element does not exist.
948 //!
949 //! <b>Complexity</b>: Amortized logarithmic.
950 //!
951 //! <b>Throws</b>: Nothing.
952 iterator lower_bound(const_reference value)
953 { return this->lower_bound(value, priv_comp()); }
955 //! <b>Effects</b>: Returns an iterator to the first element whose
956 //! key is not less than k or end() if that element does not exist.
957 //!
958 //! <b>Complexity</b>: Logarithmic.
959 //!
960 //! <b>Throws</b>: Nothing.
961 const_iterator lower_bound_dont_splay(const_reference value) const
962 { return this->lower_bound_dont_splay(value, priv_comp()); }
964 //! <b>Effects</b>: Returns an iterator to the first element whose
965 //! key is not less than k or end() if that element does not exist.
966 //!
967 //! <b>Complexity</b>: Logarithmic.
968 //!
969 //! <b>Throws</b>: Nothing.
970 template<class KeyType, class KeyValueCompare>
971 iterator lower_bound(const KeyType &key, KeyValueCompare comp)
973 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
974 key_node_comp(comp, this);
975 return iterator(node_algorithms::lower_bound
976 (const_node_ptr(&priv_header()), key, key_node_comp), this);
979 //! <b>Effects</b>: Returns a const iterator to the first element whose
980 //! key is not less than k or end() if that element does not exist.
981 //!
982 //! <b>Complexity</b>: Logarithmic.
983 //!
984 //! <b>Throws</b>: Nothing.
985 template<class KeyType, class KeyValueCompare>
986 const_iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const
988 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
989 key_node_comp(comp, this);
990 return const_iterator(node_algorithms::lower_bound
991 (const_node_ptr(&priv_header()), key, key_node_comp, false), this);
994 //! <b>Effects</b>: Returns an iterator to the first element whose
995 //! key is greater than k or end() if that element does not exist.
996 //!
997 //! <b>Complexity</b>: Amortized logarithmic.
998 //!
999 //! <b>Throws</b>: Nothing.
1000 iterator upper_bound(const_reference value)
1001 { return this->upper_bound(value, priv_comp()); }
1003 //! <b>Effects</b>: Returns an iterator to the first element whose
1004 //! key is greater than k according to comp or end() if that element
1005 //! does not exist.
1007 //! <b>Complexity</b>: Amortized logarithmic.
1008 //!
1009 //! <b>Throws</b>: Nothing.
1010 template<class KeyType, class KeyValueCompare>
1011 iterator upper_bound(const KeyType &key, KeyValueCompare comp)
1013 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1014 key_node_comp(comp, this);
1015 return iterator(node_algorithms::upper_bound
1016 (const_node_ptr(&priv_header()), key, key_node_comp), this);
1019 //! <b>Effects</b>: Returns an iterator to the first element whose
1020 //! key is greater than k or end() if that element does not exist.
1021 //!
1022 //! <b>Complexity</b>: Logarithmic.
1023 //!
1024 //! <b>Throws</b>: Nothing.
1025 const_iterator upper_bound_dont_splay(const_reference value) const
1026 { return this->upper_bound_dont_splay(value, priv_comp()); }
1028 //! <b>Effects</b>: Returns an iterator to the first element whose
1029 //! key is greater than k according to comp or end() if that element
1030 //! does not exist.
1032 //! <b>Complexity</b>: Logarithmic.
1033 //!
1034 //! <b>Throws</b>: Nothing.
1035 template<class KeyType, class KeyValueCompare>
1036 const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const
1038 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1039 key_node_comp(comp, this);
1040 return const_iterator(node_algorithms::upper_bound_dont_splay
1041 (const_node_ptr(&priv_header()), key, key_node_comp, false), this);
1044 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1045 //! k or end() if that element does not exist.
1047 //! <b>Complexity</b>: Amortized logarithmic.
1048 //!
1049 //! <b>Throws</b>: Nothing.
1050 iterator find(const_reference value)
1051 { return this->find(value, priv_comp()); }
1053 //! <b>Effects</b>: Finds an iterator to the first element whose key is
1054 //! k or end() if that element does not exist.
1056 //! <b>Complexity</b>: Amortized logarithmic.
1057 //!
1058 //! <b>Throws</b>: Nothing.
1059 template<class KeyType, class KeyValueCompare>
1060 iterator find(const KeyType &key, KeyValueCompare comp)
1062 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1063 key_node_comp(comp, this);
1064 return iterator
1065 (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this);
1068 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1069 //! k or end() if that element does not exist.
1070 //!
1071 //! <b>Complexity</b>: Logarithmic.
1072 //!
1073 //! <b>Throws</b>: Nothing.
1074 const_iterator find_dont_splay(const_reference value) const
1075 { return this->find_dont_splay(value, priv_comp()); }
1077 //! <b>Effects</b>: Finds a const_iterator to the first element whose key is
1078 //! k or end() if that element does not exist.
1079 //!
1080 //! <b>Complexity</b>: Logarithmic.
1081 //!
1082 //! <b>Throws</b>: Nothing.
1083 template<class KeyType, class KeyValueCompare>
1084 const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const
1086 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1087 key_node_comp(comp, this);
1088 return const_iterator
1089 (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp, false), this);
1092 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1093 //! an empty range that indicates the position where those elements would be
1094 //! if they there is no elements with key k.
1095 //!
1096 //! <b>Complexity</b>: Amortized logarithmic.
1097 //!
1098 //! <b>Throws</b>: Nothing.
1099 std::pair<iterator,iterator> equal_range(const_reference value)
1100 { return this->equal_range(value, priv_comp()); }
1102 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1103 //! an empty range that indicates the position where those elements would be
1104 //! if they there is no elements with key k.
1105 //!
1106 //! <b>Complexity</b>: Amortized logarithmic.
1107 //!
1108 //! <b>Throws</b>: Nothing.
1109 template<class KeyType, class KeyValueCompare>
1110 std::pair<iterator,iterator> equal_range(const KeyType &key, KeyValueCompare comp)
1112 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1113 key_node_comp(comp, this);
1114 std::pair<node_ptr, node_ptr> ret
1115 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp));
1116 return std::pair<iterator, iterator>(iterator(ret.first, this), iterator(ret.second, this));
1119 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1120 //! an empty range that indicates the position where those elements would be
1121 //! if they there is no elements with key k.
1122 //!
1123 //! <b>Complexity</b>: Logarithmic.
1124 //!
1125 //! <b>Throws</b>: Nothing.
1126 std::pair<const_iterator, const_iterator>
1127 equal_range_dont_splay(const_reference value) const
1128 { return this->equal_range_dont_splay(value, priv_comp()); }
1130 //! <b>Effects</b>: Finds a range containing all elements whose key is k or
1131 //! an empty range that indicates the position where those elements would be
1132 //! if they there is no elements with key k.
1133 //!
1134 //! <b>Complexity</b>: Logarithmic.
1135 //!
1136 //! <b>Throws</b>: Nothing.
1137 template<class KeyType, class KeyValueCompare>
1138 std::pair<const_iterator, const_iterator>
1139 equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const
1141 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1142 key_node_comp(comp, this);
1143 std::pair<node_ptr, node_ptr> ret
1144 (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp, false));
1145 return std::pair<const_iterator, const_iterator>(const_iterator(ret.first, this), const_iterator(ret.second, this));
1148 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1149 //! Cloner should yield to nodes equivalent to the original nodes.
1151 //! <b>Effects</b>: Erases all the elements from *this
1152 //! calling Disposer::operator()(pointer), clones all the
1153 //! elements from src calling Cloner::operator()(const_reference )
1154 //! and inserts them on *this. Copies the predicate from the source container.
1156 //! If cloner throws, all cloned elements are unlinked and disposed
1157 //! calling Disposer::operator()(pointer).
1158 //!
1159 //! <b>Complexity</b>: Linear to erased plus inserted elements.
1160 //!
1161 //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
1162 template <class Cloner, class Disposer>
1163 void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer)
1165 this->clear_and_dispose(disposer);
1166 if(!src.empty()){
1167 detail::exception_disposer<splaytree_impl, Disposer>
1168 rollback(*this, disposer);
1169 node_algorithms::clone
1170 (const_node_ptr(&src.priv_header())
1171 ,node_ptr(&this->priv_header())
1172 ,detail::node_cloner<Cloner, splaytree_impl>(cloner, this)
1173 ,detail::node_disposer<Disposer, splaytree_impl>(disposer, this));
1174 this->priv_size_traits().set_size(src.priv_size_traits().get_size());
1175 this->priv_comp() = src.priv_comp();
1176 rollback.release();
1180 //! <b>Effects</b>: Unlinks the leftmost node from the tree.
1181 //!
1182 //! <b>Complexity</b>: Average complexity is constant time.
1183 //!
1184 //! <b>Throws</b>: Nothing.
1185 //!
1186 //! <b>Notes</b>: This function breaks the tree and the tree can
1187 //! only be used for more unlink_leftmost_without_rebalance calls.
1188 //! This function is normally used to achieve a step by step
1189 //! controlled destruction of the tree.
1190 pointer unlink_leftmost_without_rebalance()
1192 node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance
1193 (node_ptr(&priv_header())));
1194 if(!to_be_disposed)
1195 return 0;
1196 this->priv_size_traits().decrement();
1197 if(safemode_or_autounlink)//If this is commented does not work with normal_link
1198 node_algorithms::init(to_be_disposed);
1199 return get_real_value_traits().to_value_ptr(to_be_disposed);
1202 //! <b>Requires</b>: i must be a valid iterator of *this.
1203 //!
1204 //! <b>Effects</b>: Rearranges the splay set so that the element pointed by i
1205 //! is placed as the root of the tree, improving future searches of this value.
1206 //!
1207 //! <b>Complexity</b>: Amortized logarithmic.
1208 //!
1209 //! <b>Throws</b>: Nothing.
1210 void splay_up(iterator i)
1211 { return node_algorithms::splay_up(i.pointed_node(), &priv_header()); }
1213 //! <b>Effects</b>: Rearranges the splay set so that if *this stores an element
1214 //! with a key equivalent to value the element is placed as the root of the
1215 //! tree. If the element is not present returns the last node compared with the key.
1216 //! If the tree is empty, end() is returned.
1217 //!
1218 //! <b>Complexity</b>: Amortized logarithmic.
1220 //! <b>Returns</b>: An iterator to the new root of the tree, end() if the tree is empty.
1222 //! <b>Throws</b>: If the comparison functor throws.
1223 template<class KeyType, class KeyValueCompare>
1224 iterator splay_down(const KeyType &key, KeyValueCompare comp)
1226 detail::key_nodeptr_comp<KeyValueCompare, splaytree_impl>
1227 key_node_comp(comp, this);
1228 node_ptr r = node_algorithms::splay_down(&priv_header(), key, key_node_comp);
1229 return iterator(r, this);
1232 //! <b>Effects</b>: Rearranges the splay set so that if *this stores an element
1233 //! with a key equivalent to value the element is placed as the root of the
1234 //! tree.
1235 //!
1236 //! <b>Complexity</b>: Amortized logarithmic.
1237 //!
1238 //! <b>Returns</b>: An iterator to the new root of the tree, end() if the tree is empty.
1240 //! <b>Throws</b>: If the predicate throws.
1241 iterator splay_down(const value_type &value)
1242 { return this->splay_down(value, priv_comp()); }
1244 //! <b>Requires</b>: replace_this must be a valid iterator of *this
1245 //! and with_this must not be inserted in any tree.
1246 //!
1247 //! <b>Effects</b>: Replaces replace_this in its position in the
1248 //! tree with with_this. The tree does not need to be rebalanced.
1249 //!
1250 //! <b>Complexity</b>: Constant.
1251 //!
1252 //! <b>Throws</b>: Nothing.
1253 //!
1254 //! <b>Note</b>: This function will break container ordering invariants if
1255 //! with_this is not equivalent to *replace_this according to the
1256 //! ordering rules. This function is faster than erasing and inserting
1257 //! the node, since no rebalancing or comparison is needed.
1258 void replace_node(iterator replace_this, reference with_this)
1260 node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this)
1261 , node_ptr(&priv_header())
1262 , get_real_value_traits().to_node_ptr(with_this));
1265 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1266 //! appropriate type. Otherwise the behavior is undefined.
1267 //!
1268 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1269 //! that points to the value
1270 //!
1271 //! <b>Complexity</b>: Constant.
1272 //!
1273 //! <b>Throws</b>: Nothing.
1274 //!
1275 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1276 //! is stateless.
1277 static iterator s_iterator_to(reference value)
1279 BOOST_STATIC_ASSERT((!stateful_value_traits));
1280 return iterator (value_traits::to_node_ptr(value), 0);
1283 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1284 //! appropriate type. Otherwise the behavior is undefined.
1285 //!
1286 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1287 //! set that points to the value
1288 //!
1289 //! <b>Complexity</b>: Constant.
1290 //!
1291 //! <b>Throws</b>: Nothing.
1292 //!
1293 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
1294 //! is stateless.
1295 static const_iterator s_iterator_to(const_reference value)
1297 BOOST_STATIC_ASSERT((!stateful_value_traits));
1298 return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), 0);
1301 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1302 //! appropriate type. Otherwise the behavior is undefined.
1303 //!
1304 //! <b>Effects</b>: Returns: a valid iterator i belonging to the set
1305 //! that points to the value
1306 //!
1307 //! <b>Complexity</b>: Constant.
1308 //!
1309 //! <b>Throws</b>: Nothing.
1310 iterator iterator_to(reference value)
1311 { return iterator (value_traits::to_node_ptr(value), this); }
1313 //! <b>Requires</b>: value must be an lvalue and shall be in a set of
1314 //! appropriate type. Otherwise the behavior is undefined.
1315 //!
1316 //! <b>Effects</b>: Returns: a valid const_iterator i belonging to the
1317 //! set that points to the value
1318 //!
1319 //! <b>Complexity</b>: Constant.
1320 //!
1321 //! <b>Throws</b>: Nothing.
1322 const_iterator iterator_to(const_reference value) const
1323 { return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), this); }
1325 //! <b>Requires</b>: value shall not be in a tree.
1326 //!
1327 //! <b>Effects</b>: init_node puts the hook of a value in a well-known default
1328 //! state.
1329 //!
1330 //! <b>Throws</b>: Nothing.
1331 //!
1332 //! <b>Complexity</b>: Constant time.
1333 //!
1334 //! <b>Note</b>: This function puts the hook in the well-known default state
1335 //! used by auto_unlink and safe hooks.
1336 static void init_node(reference value)
1337 { node_algorithms::init(value_traits::to_node_ptr(value)); }
1339 //! <b>Effects</b>: Rebalances the tree.
1340 //!
1341 //! <b>Throws</b>: Nothing.
1342 //!
1343 //! <b>Complexity</b>: Linear.
1344 void rebalance()
1345 { node_algorithms::rebalance(node_ptr(&priv_header())); }
1347 //! <b>Requires</b>: old_root is a node of a tree.
1348 //!
1349 //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
1351 //! <b>Returns</b>: The new root of the subtree.
1353 //! <b>Throws</b>: Nothing.
1354 //!
1355 //! <b>Complexity</b>: Linear to the elements in the subtree.
1356 iterator rebalance_subtree(iterator root)
1357 { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this); }
1360 //! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
1361 //! if x is not in such a tree.
1362 //!
1363 //! <b>Throws</b>: Nothing.
1364 //!
1365 //! <b>Complexity</b>: Constant time.
1366 //!
1367 //! <b>Note</b>: This static function is only usable with the "safe mode"
1368 //! hook and non-constant time size lists. Otherwise, the user must use
1369 //! the non-static "erase(reference )" member. If the user calls
1370 //! this function with a non "safe mode" or constant time size list
1371 //! a compilation error will be issued.
1372 template<class T>
1373 static void remove_node(T& value)
1375 //This function is only usable for safe mode hooks and non-constant
1376 //time lists.
1377 //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
1378 BOOST_STATIC_ASSERT((!constant_time_size));
1379 BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
1380 node_ptr to_remove(value_traits::to_node_ptr(value));
1381 node_algorithms::unlink_and_rebalance(to_remove);
1382 if(safemode_or_autounlink)
1383 node_algorithms::init(to_remove);
1387 /// @cond
1388 private:
1389 template<class Disposer>
1390 iterator private_erase(const_iterator b, const_iterator e, size_type &n, Disposer disposer)
1392 for(n = 0; b != e; ++n)
1393 this->erase_and_dispose(b++, disposer);
1394 return b.unconst();
1397 iterator private_erase(const_iterator b, const_iterator e, size_type &n)
1399 for(n = 0; b != e; ++n)
1400 this->erase(b++);
1401 return b.unconst();
1403 /// @endcond
1405 private:
1406 static splaytree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator)
1408 header_plus_size *r = detail::parent_from_member<header_plus_size, node>
1409 ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_);
1410 node_plus_pred_t *n = detail::parent_from_member
1411 <node_plus_pred_t, header_plus_size>(r, &node_plus_pred_t::header_plus_size_);
1412 data_t *d = detail::parent_from_member<data_t, node_plus_pred_t>(n, &data_t::node_plus_pred_);
1413 splaytree_impl *rb = detail::parent_from_member<splaytree_impl, data_t>(d, &splaytree_impl::data_);
1414 return *rb;
1417 static splaytree_impl &priv_container_from_iterator(const const_iterator &it)
1418 { return priv_container_from_end_iterator(it.end_iterator_from_it()); }
1421 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1422 template<class T, class ...Options>
1423 #else
1424 template<class Config>
1425 #endif
1426 inline bool operator<
1427 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1428 (const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
1429 #else
1430 (const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
1431 #endif
1432 { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
1434 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1435 template<class T, class ...Options>
1436 #else
1437 template<class Config>
1438 #endif
1439 bool operator==
1440 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1441 (const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
1442 #else
1443 (const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
1444 #endif
1446 typedef splaytree_impl<Config> tree_type;
1447 typedef typename tree_type::const_iterator const_iterator;
1449 if(tree_type::constant_time_size && x.size() != y.size()){
1450 return false;
1452 const_iterator end1 = x.end();
1453 const_iterator i1 = x.begin();
1454 const_iterator i2 = y.begin();
1455 if(tree_type::constant_time_size){
1456 while (i1 != end1 && *i1 == *i2) {
1457 ++i1;
1458 ++i2;
1460 return i1 == end1;
1462 else{
1463 const_iterator end2 = y.end();
1464 while (i1 != end1 && i2 != end2 && *i1 == *i2) {
1465 ++i1;
1466 ++i2;
1468 return i1 == end1 && i2 == end2;
1472 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1473 template<class T, class ...Options>
1474 #else
1475 template<class Config>
1476 #endif
1477 inline bool operator!=
1478 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1479 (const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
1480 #else
1481 (const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
1482 #endif
1483 { return !(x == y); }
1485 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1486 template<class T, class ...Options>
1487 #else
1488 template<class Config>
1489 #endif
1490 inline bool operator>
1491 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1492 (const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
1493 #else
1494 (const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
1495 #endif
1496 { return y < x; }
1498 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1499 template<class T, class ...Options>
1500 #else
1501 template<class Config>
1502 #endif
1503 inline bool operator<=
1504 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1505 (const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
1506 #else
1507 (const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
1508 #endif
1509 { return !(y < x); }
1511 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1512 template<class T, class ...Options>
1513 #else
1514 template<class Config>
1515 #endif
1516 inline bool operator>=
1517 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1518 (const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
1519 #else
1520 (const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
1521 #endif
1522 { return !(x < y); }
1524 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1525 template<class T, class ...Options>
1526 #else
1527 template<class Config>
1528 #endif
1529 inline void swap
1530 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
1531 (splaytree_impl<T, Options...> &x, splaytree_impl<T, Options...> &y)
1532 #else
1533 (splaytree_impl<Config> &x, splaytree_impl<Config> &y)
1534 #endif
1535 { x.swap(y); }
1537 /// @cond
1539 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1540 template<class T, class O1 = none, class O2 = none
1541 , class O3 = none, class O4 = none>
1542 #else
1543 template<class T, class ...Options>
1544 #endif
1545 struct make_splaytree_opt
1547 typedef typename pack_options
1548 < splay_set_defaults<T>,
1549 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1550 O1, O2, O3, O4
1551 #else
1552 Options...
1553 #endif
1554 >::type packed_options;
1555 typedef typename detail::get_value_traits
1556 <T, typename packed_options::value_traits>::type value_traits;
1558 typedef splaysetopt
1559 < value_traits
1560 , typename packed_options::compare
1561 , typename packed_options::size_type
1562 , packed_options::constant_time_size
1563 > type;
1565 /// @endcond
1567 //! Helper metafunction to define a \c splaytree that yields to the same type when the
1568 //! same options (either explicitly or implicitly) are used.
1569 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1570 template<class T, class ...Options>
1571 #else
1572 template<class T, class O1 = none, class O2 = none
1573 , class O3 = none, class O4 = none>
1574 #endif
1575 struct make_splaytree
1577 /// @cond
1578 typedef splaytree_impl
1579 < typename make_splaytree_opt<T,
1580 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1581 O1, O2, O3, O4
1582 #else
1583 Options...
1584 #endif
1585 >::type
1586 > implementation_defined;
1587 /// @endcond
1588 typedef implementation_defined type;
1591 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1592 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1593 template<class T, class O1, class O2, class O3, class O4>
1594 #else
1595 template<class T, class ...Options>
1596 #endif
1597 class splaytree
1598 : public make_splaytree<T,
1599 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1600 O1, O2, O3, O4
1601 #else
1602 Options...
1603 #endif
1604 >::type
1606 typedef typename make_splaytree
1607 <T,
1608 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1609 O1, O2, O3, O4
1610 #else
1611 Options...
1612 #endif
1613 >::type Base;
1615 public:
1616 typedef typename Base::value_compare value_compare;
1617 typedef typename Base::value_traits value_traits;
1618 typedef typename Base::real_value_traits real_value_traits;
1619 typedef typename Base::iterator iterator;
1620 typedef typename Base::const_iterator const_iterator;
1622 //Assert if passed value traits are compatible with the type
1623 BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
1625 splaytree( const value_compare &cmp = value_compare()
1626 , const value_traits &v_traits = value_traits())
1627 : Base(cmp, v_traits)
1630 template<class Iterator>
1631 splaytree( bool unique, Iterator b, Iterator e
1632 , const value_compare &cmp = value_compare()
1633 , const value_traits &v_traits = value_traits())
1634 : Base(unique, b, e, cmp, v_traits)
1637 static splaytree &container_from_end_iterator(iterator end_iterator)
1638 { return static_cast<splaytree &>(Base::container_from_end_iterator(end_iterator)); }
1640 static const splaytree &container_from_end_iterator(const_iterator end_iterator)
1641 { return static_cast<const splaytree &>(Base::container_from_end_iterator(end_iterator)); }
1644 #endif
1647 } //namespace intrusive
1648 } //namespace boost
1650 #include <boost/intrusive/detail/config_end.hpp>
1652 #endif //BOOST_INTRUSIVE_SPLAYTREE_HPP