comparison DEPENDENCIES/generic/include/boost/container/detail/tree.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_CONTAINER_TREE_HPP
12 #define BOOST_CONTAINER_TREE_HPP
13
14 #include "config_begin.hpp"
15 #include <boost/container/detail/workaround.hpp>
16 #include <boost/container/container_fwd.hpp>
17
18 #include <boost/move/utility.hpp>
19 #include <boost/intrusive/pointer_traits.hpp>
20 #include <boost/type_traits/has_trivial_destructor.hpp>
21 #include <boost/detail/no_exceptions_support.hpp>
22 #include <boost/intrusive/rbtree.hpp>
23 #include <boost/container/detail/utilities.hpp>
24 #include <boost/container/detail/iterators.hpp>
25 #include <boost/container/detail/algorithms.hpp>
26 #include <boost/container/detail/node_alloc_holder.hpp>
27 #include <boost/container/detail/destroyers.hpp>
28 #include <boost/container/detail/pair.hpp>
29 #include <boost/container/detail/type_traits.hpp>
30 #include <boost/container/allocator_traits.hpp>
31 #include <boost/detail/no_exceptions_support.hpp>
32 #ifndef BOOST_CONTAINER_PERFECT_FORWARDING
33 #include <boost/container/detail/preprocessor.hpp>
34 #endif
35
36 #include <utility> //std::pair
37 #include <iterator>
38 #include <algorithm>
39
40 namespace boost {
41 namespace container {
42 namespace container_detail {
43
44 template<class Key, class Value, class KeyCompare, class KeyOfValue>
45 struct tree_value_compare
46 : public KeyCompare
47 {
48 typedef Value value_type;
49 typedef KeyCompare key_compare;
50 typedef KeyOfValue key_of_value;
51 typedef Key key_type;
52
53 explicit tree_value_compare(const key_compare &kcomp)
54 : KeyCompare(kcomp)
55 {}
56
57 tree_value_compare()
58 : KeyCompare()
59 {}
60
61 const key_compare &key_comp() const
62 { return static_cast<const key_compare &>(*this); }
63
64 key_compare &key_comp()
65 { return static_cast<key_compare &>(*this); }
66
67 template<class T>
68 struct is_key
69 {
70 static const bool value = is_same<const T, const key_type>::value;
71 };
72
73 template<class T>
74 typename enable_if_c<is_key<T>::value, const key_type &>::type
75 key_forward(const T &key) const
76 { return key; }
77
78 template<class T>
79 typename enable_if_c<!is_key<T>::value, const key_type &>::type
80 key_forward(const T &key) const
81 { return KeyOfValue()(key); }
82
83 template<class KeyType, class KeyType2>
84 bool operator()(const KeyType &key1, const KeyType2 &key2) const
85 { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
86 };
87
88 template<class VoidPointer>
89 struct rbtree_hook
90 {
91 typedef typename container_detail::bi::make_set_base_hook
92 < container_detail::bi::void_pointer<VoidPointer>
93 , container_detail::bi::link_mode<container_detail::bi::normal_link>
94 , container_detail::bi::optimize_size<true>
95 >::type type;
96 };
97
98 //This trait is used to type-pun std::pair because in C++03
99 //compilers std::pair is useless for C++11 features
100 template<class T>
101 struct rbtree_internal_data_type
102 {
103 typedef T type;
104 };
105
106 template<class T1, class T2>
107 struct rbtree_internal_data_type< std::pair<T1, T2> >
108 {
109 typedef pair<T1, T2> type;
110 };
111
112
113 //The node to be store in the tree
114 template <class T, class VoidPointer>
115 struct rbtree_node
116 : public rbtree_hook<VoidPointer>::type
117 {
118 private:
119 //BOOST_COPYABLE_AND_MOVABLE(rbtree_node)
120 rbtree_node();
121
122 public:
123 typedef typename rbtree_hook<VoidPointer>::type hook_type;
124
125 typedef T value_type;
126 typedef typename rbtree_internal_data_type<T>::type internal_type;
127
128 typedef rbtree_node<T, VoidPointer> node_type;
129
130 T &get_data()
131 {
132 T* ptr = reinterpret_cast<T*>(&this->m_data);
133 return *ptr;
134 }
135
136 const T &get_data() const
137 {
138 const T* ptr = reinterpret_cast<const T*>(&this->m_data);
139 return *ptr;
140 }
141
142 internal_type m_data;
143
144 template<class A, class B>
145 void do_assign(const std::pair<const A, B> &p)
146 {
147 const_cast<A&>(m_data.first) = p.first;
148 m_data.second = p.second;
149 }
150
151 template<class A, class B>
152 void do_assign(const pair<const A, B> &p)
153 {
154 const_cast<A&>(m_data.first) = p.first;
155 m_data.second = p.second;
156 }
157
158 template<class V>
159 void do_assign(const V &v)
160 { m_data = v; }
161
162 template<class A, class B>
163 void do_move_assign(std::pair<const A, B> &p)
164 {
165 const_cast<A&>(m_data.first) = ::boost::move(p.first);
166 m_data.second = ::boost::move(p.second);
167 }
168
169 template<class A, class B>
170 void do_move_assign(pair<const A, B> &p)
171 {
172 const_cast<A&>(m_data.first) = ::boost::move(p.first);
173 m_data.second = ::boost::move(p.second);
174 }
175
176 template<class V>
177 void do_move_assign(V &v)
178 { m_data = ::boost::move(v); }
179 };
180
181 template<class Node, class Icont>
182 class insert_equal_end_hint_functor
183 {
184 Icont &icont_;
185
186 public:
187 insert_equal_end_hint_functor(Icont &icont)
188 : icont_(icont)
189 {}
190
191 void operator()(Node &n)
192 { this->icont_.insert_equal(this->icont_.cend(), n); }
193 };
194
195 template<class Node, class Icont>
196 class push_back_functor
197 {
198 Icont &icont_;
199
200 public:
201 push_back_functor(Icont &icont)
202 : icont_(icont)
203 {}
204
205 void operator()(Node &n)
206 { this->icont_.push_back(n); }
207 };
208
209 }//namespace container_detail {
210
211 namespace container_detail {
212
213 template<class A, class ValueCompare>
214 struct intrusive_rbtree_type
215 {
216 typedef typename boost::container::
217 allocator_traits<A>::value_type value_type;
218 typedef typename boost::container::
219 allocator_traits<A>::void_pointer void_pointer;
220 typedef typename boost::container::
221 allocator_traits<A>::size_type size_type;
222 typedef typename container_detail::rbtree_node
223 <value_type, void_pointer> node_type;
224 typedef node_compare<ValueCompare, node_type> node_compare_type;
225 typedef typename container_detail::bi::make_rbtree
226 <node_type
227 ,container_detail::bi::compare<node_compare_type>
228 ,container_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type>
229 ,container_detail::bi::constant_time_size<true>
230 ,container_detail::bi::size_type<size_type>
231 >::type container_type;
232 typedef container_type type ;
233 };
234
235 } //namespace container_detail {
236
237 namespace container_detail {
238
239 template <class Key, class Value, class KeyOfValue,
240 class KeyCompare, class A>
241 class rbtree
242 : protected container_detail::node_alloc_holder
243 < A
244 , typename container_detail::intrusive_rbtree_type
245 <A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
246 >::type
247 , tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
248 >
249 {
250 typedef tree_value_compare
251 <Key, Value, KeyCompare, KeyOfValue> ValComp;
252 typedef typename container_detail::intrusive_rbtree_type
253 < A, ValComp>::type Icont;
254 typedef container_detail::node_alloc_holder
255 <A, Icont, ValComp> AllocHolder;
256 typedef typename AllocHolder::NodePtr NodePtr;
257 typedef rbtree < Key, Value, KeyOfValue
258 , KeyCompare, A> ThisType;
259 typedef typename AllocHolder::NodeAlloc NodeAlloc;
260 typedef typename AllocHolder::ValAlloc ValAlloc;
261 typedef typename AllocHolder::Node Node;
262 typedef typename Icont::iterator iiterator;
263 typedef typename Icont::const_iterator iconst_iterator;
264 typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer;
265 typedef typename AllocHolder::allocator_v1 allocator_v1;
266 typedef typename AllocHolder::allocator_v2 allocator_v2;
267 typedef typename AllocHolder::alloc_version alloc_version;
268
269 class RecyclingCloner;
270 friend class RecyclingCloner;
271
272 class RecyclingCloner
273 {
274 public:
275 RecyclingCloner(AllocHolder &holder, Icont &irbtree)
276 : m_holder(holder), m_icont(irbtree)
277 {}
278
279 NodePtr operator()(const Node &other) const
280 {
281 if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
282 //First recycle a node (this can't throw)
283 BOOST_TRY{
284 //This can throw
285 p->do_assign(other.m_data);
286 return p;
287 }
288 BOOST_CATCH(...){
289 //If there is an exception destroy the whole source
290 m_holder.destroy_node(p);
291 while((p = m_icont.unlink_leftmost_without_rebalance())){
292 m_holder.destroy_node(p);
293 }
294 BOOST_RETHROW
295 }
296 BOOST_CATCH_END
297 }
298 else{
299 return m_holder.create_node(other.m_data);
300 }
301 }
302
303 AllocHolder &m_holder;
304 Icont &m_icont;
305 };
306
307 class RecyclingMoveCloner;
308 friend class RecyclingMoveCloner;
309
310 class RecyclingMoveCloner
311 {
312 public:
313 RecyclingMoveCloner(AllocHolder &holder, Icont &irbtree)
314 : m_holder(holder), m_icont(irbtree)
315 {}
316
317 NodePtr operator()(const Node &other) const
318 {
319 if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
320 //First recycle a node (this can't throw)
321 BOOST_TRY{
322 //This can throw
323 p->do_move_assign(const_cast<Node &>(other).m_data);
324 return p;
325 }
326 BOOST_CATCH(...){
327 //If there is an exception destroy the whole source
328 m_holder.destroy_node(p);
329 while((p = m_icont.unlink_leftmost_without_rebalance())){
330 m_holder.destroy_node(p);
331 }
332 BOOST_RETHROW
333 }
334 BOOST_CATCH_END
335 }
336 else{
337 return m_holder.create_node(other.m_data);
338 }
339 }
340
341 AllocHolder &m_holder;
342 Icont &m_icont;
343 };
344
345 BOOST_COPYABLE_AND_MOVABLE(rbtree)
346
347 public:
348
349 typedef Key key_type;
350 typedef Value value_type;
351 typedef A allocator_type;
352 typedef KeyCompare key_compare;
353 typedef ValComp value_compare;
354 typedef typename boost::container::
355 allocator_traits<A>::pointer pointer;
356 typedef typename boost::container::
357 allocator_traits<A>::const_pointer const_pointer;
358 typedef typename boost::container::
359 allocator_traits<A>::reference reference;
360 typedef typename boost::container::
361 allocator_traits<A>::const_reference const_reference;
362 typedef typename boost::container::
363 allocator_traits<A>::size_type size_type;
364 typedef typename boost::container::
365 allocator_traits<A>::difference_type difference_type;
366 typedef difference_type rbtree_difference_type;
367 typedef pointer rbtree_pointer;
368 typedef const_pointer rbtree_const_pointer;
369 typedef reference rbtree_reference;
370 typedef const_reference rbtree_const_reference;
371 typedef NodeAlloc stored_allocator_type;
372
373 private:
374
375 template<class KeyValueCompare>
376 struct key_node_compare
377 : private KeyValueCompare
378 {
379 key_node_compare(const KeyValueCompare &comp)
380 : KeyValueCompare(comp)
381 {}
382
383 template<class T>
384 struct is_node
385 {
386 static const bool value = is_same<T, Node>::value;
387 };
388
389 template<class T>
390 typename enable_if_c<is_node<T>::value, const value_type &>::type
391 key_forward(const T &node) const
392 { return node.get_data(); }
393
394 template<class T>
395 typename enable_if_c<!is_node<T>::value, const T &>::type
396 key_forward(const T &key) const
397 { return key; }
398
399 template<class KeyType, class KeyType2>
400 bool operator()(const KeyType &key1, const KeyType2 &key2) const
401 { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
402 };
403
404 typedef key_node_compare<value_compare> KeyNodeCompare;
405
406 public:
407 typedef container_detail::iterator<iiterator, false> iterator;
408 typedef container_detail::iterator<iiterator, true > const_iterator;
409 typedef std::reverse_iterator<iterator> reverse_iterator;
410 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
411
412 rbtree()
413 : AllocHolder(ValComp(key_compare()))
414 {}
415
416 explicit rbtree(const key_compare& comp, const allocator_type& a = allocator_type())
417 : AllocHolder(a, ValComp(comp))
418 {}
419
420 explicit rbtree(const allocator_type& a)
421 : AllocHolder(a)
422 {}
423
424 template <class InputIterator>
425 rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
426 const allocator_type& a
427 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
428 , typename container_detail::enable_if_c
429 < container_detail::is_input_iterator<InputIterator>::value
430 || container_detail::is_same<alloc_version, allocator_v1>::value
431 >::type * = 0
432 #endif
433 )
434 : AllocHolder(a, value_compare(comp))
435 {
436 //Use cend() as hint to achieve linear time for
437 //ordered ranges as required by the standard
438 //for the constructor
439 const const_iterator end_it(this->cend());
440 if(unique_insertion){
441 for ( ; first != last; ++first){
442 this->insert_unique(end_it, *first);
443 }
444 }
445 else{
446 for ( ; first != last; ++first){
447 this->insert_equal(end_it, *first);
448 }
449 }
450 }
451
452 template <class InputIterator>
453 rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
454 const allocator_type& a
455 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
456 , typename container_detail::enable_if_c
457 < !(container_detail::is_input_iterator<InputIterator>::value
458 || container_detail::is_same<alloc_version, allocator_v1>::value)
459 >::type * = 0
460 #endif
461 )
462 : AllocHolder(a, value_compare(comp))
463 {
464 if(unique_insertion){
465 //Use cend() as hint to achieve linear time for
466 //ordered ranges as required by the standard
467 //for the constructor
468 const const_iterator end_it(this->cend());
469 for ( ; first != last; ++first){
470 this->insert_unique(end_it, *first);
471 }
472 }
473 else{
474 //Optimized allocation and construction
475 this->allocate_many_and_construct
476 ( first, std::distance(first, last)
477 , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
478 }
479 }
480
481 template <class InputIterator>
482 rbtree( ordered_range_t, InputIterator first, InputIterator last
483 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
484 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
485 , typename container_detail::enable_if_c
486 < container_detail::is_input_iterator<InputIterator>::value
487 || container_detail::is_same<alloc_version, allocator_v1>::value
488 >::type * = 0
489 #endif
490 )
491 : AllocHolder(a, value_compare(comp))
492 {
493 for ( ; first != last; ++first){
494 this->push_back_impl(*first);
495 }
496 }
497
498 template <class InputIterator>
499 rbtree( ordered_range_t, InputIterator first, InputIterator last
500 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
501 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
502 , typename container_detail::enable_if_c
503 < !(container_detail::is_input_iterator<InputIterator>::value
504 || container_detail::is_same<alloc_version, allocator_v1>::value)
505 >::type * = 0
506 #endif
507 )
508 : AllocHolder(a, value_compare(comp))
509 {
510 //Optimized allocation and construction
511 this->allocate_many_and_construct
512 ( first, std::distance(first, last)
513 , container_detail::push_back_functor<Node, Icont>(this->icont()));
514 }
515
516 rbtree(const rbtree& x)
517 : AllocHolder(x, x.value_comp())
518 {
519 this->icont().clone_from
520 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
521 }
522
523 rbtree(BOOST_RV_REF(rbtree) x)
524 : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.value_comp())
525 {}
526
527 rbtree(const rbtree& x, const allocator_type &a)
528 : AllocHolder(a, x.value_comp())
529 {
530 this->icont().clone_from
531 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
532 }
533
534 rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a)
535 : AllocHolder(a, x.value_comp())
536 {
537 if(this->node_alloc() == x.node_alloc()){
538 this->icont().swap(x.icont());
539 }
540 else{
541 this->icont().clone_from
542 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
543 }
544 }
545
546 ~rbtree()
547 {} //AllocHolder clears the tree
548
549 rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x)
550 {
551 if (&x != this){
552 NodeAlloc &this_alloc = this->get_stored_allocator();
553 const NodeAlloc &x_alloc = x.get_stored_allocator();
554 container_detail::bool_<allocator_traits<NodeAlloc>::
555 propagate_on_container_copy_assignment::value> flag;
556 if(flag && this_alloc != x_alloc){
557 this->clear();
558 }
559 this->AllocHolder::copy_assign_alloc(x);
560 //Transfer all the nodes to a temporary tree
561 //If anything goes wrong, all the nodes will be destroyed
562 //automatically
563 Icont other_tree(::boost::move(this->icont()));
564
565 //Now recreate the source tree reusing nodes stored by other_tree
566 this->icont().clone_from
567 (x.icont()
568 , RecyclingCloner(*this, other_tree)
569 , Destroyer(this->node_alloc()));
570
571 //If there are remaining nodes, destroy them
572 NodePtr p;
573 while((p = other_tree.unlink_leftmost_without_rebalance())){
574 AllocHolder::destroy_node(p);
575 }
576 }
577 return *this;
578 }
579
580 rbtree& operator=(BOOST_RV_REF(rbtree) x)
581 {
582 if (&x != this){
583 NodeAlloc &this_alloc = this->get_stored_allocator();
584 const NodeAlloc &x_alloc = x.get_stored_allocator();
585 //If allocators are equal we can just swap pointers
586 if(this_alloc == x_alloc){
587 //Destroy and swap pointers
588 this->clear();
589 this->icont() = ::boost::move(x.icont());
590 //Move allocator if needed
591 this->AllocHolder::move_assign_alloc(x);
592 }
593 //If unequal allocators, then do a one by one move
594 else{
595 //Transfer all the nodes to a temporary tree
596 //If anything goes wrong, all the nodes will be destroyed
597 //automatically
598 Icont other_tree(::boost::move(this->icont()));
599
600 //Now recreate the source tree reusing nodes stored by other_tree
601 this->icont().clone_from
602 (x.icont()
603 , RecyclingMoveCloner(*this, other_tree)
604 , Destroyer(this->node_alloc()));
605
606 //If there are remaining nodes, destroy them
607 NodePtr p;
608 while((p = other_tree.unlink_leftmost_without_rebalance())){
609 AllocHolder::destroy_node(p);
610 }
611 }
612 }
613 return *this;
614 }
615
616 public:
617 // accessors:
618 value_compare value_comp() const
619 { return this->icont().value_comp().value_comp(); }
620
621 key_compare key_comp() const
622 { return this->icont().value_comp().value_comp().key_comp(); }
623
624 allocator_type get_allocator() const
625 { return allocator_type(this->node_alloc()); }
626
627 const stored_allocator_type &get_stored_allocator() const
628 { return this->node_alloc(); }
629
630 stored_allocator_type &get_stored_allocator()
631 { return this->node_alloc(); }
632
633 iterator begin()
634 { return iterator(this->icont().begin()); }
635
636 const_iterator begin() const
637 { return this->cbegin(); }
638
639 iterator end()
640 { return iterator(this->icont().end()); }
641
642 const_iterator end() const
643 { return this->cend(); }
644
645 reverse_iterator rbegin()
646 { return reverse_iterator(end()); }
647
648 const_reverse_iterator rbegin() const
649 { return this->crbegin(); }
650
651 reverse_iterator rend()
652 { return reverse_iterator(begin()); }
653
654 const_reverse_iterator rend() const
655 { return this->crend(); }
656
657 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
658 //!
659 //! <b>Throws</b>: Nothing.
660 //!
661 //! <b>Complexity</b>: Constant.
662 const_iterator cbegin() const
663 { return const_iterator(this->non_const_icont().begin()); }
664
665 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
666 //!
667 //! <b>Throws</b>: Nothing.
668 //!
669 //! <b>Complexity</b>: Constant.
670 const_iterator cend() const
671 { return const_iterator(this->non_const_icont().end()); }
672
673 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
674 //! of the reversed container.
675 //!
676 //! <b>Throws</b>: Nothing.
677 //!
678 //! <b>Complexity</b>: Constant.
679 const_reverse_iterator crbegin() const
680 { return const_reverse_iterator(cend()); }
681
682 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
683 //! of the reversed container.
684 //!
685 //! <b>Throws</b>: Nothing.
686 //!
687 //! <b>Complexity</b>: Constant.
688 const_reverse_iterator crend() const
689 { return const_reverse_iterator(cbegin()); }
690
691 bool empty() const
692 { return !this->size(); }
693
694 size_type size() const
695 { return this->icont().size(); }
696
697 size_type max_size() const
698 { return AllocHolder::max_size(); }
699
700 void swap(ThisType& x)
701 { AllocHolder::swap(x); }
702
703 public:
704
705 typedef typename Icont::insert_commit_data insert_commit_data;
706
707 // insert/erase
708 std::pair<iterator,bool> insert_unique_check
709 (const key_type& key, insert_commit_data &data)
710 {
711 std::pair<iiterator, bool> ret =
712 this->icont().insert_unique_check(key, KeyNodeCompare(value_comp()), data);
713 return std::pair<iterator, bool>(iterator(ret.first), ret.second);
714 }
715
716 std::pair<iterator,bool> insert_unique_check
717 (const_iterator hint, const key_type& key, insert_commit_data &data)
718 {
719 std::pair<iiterator, bool> ret =
720 this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(value_comp()), data);
721 return std::pair<iterator, bool>(iterator(ret.first), ret.second);
722 }
723
724 iterator insert_unique_commit(const value_type& v, insert_commit_data &data)
725 {
726 NodePtr tmp = AllocHolder::create_node(v);
727 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
728 iterator ret(this->icont().insert_unique_commit(*tmp, data));
729 destroy_deallocator.release();
730 return ret;
731 }
732
733 template<class MovableConvertible>
734 iterator insert_unique_commit
735 (BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data)
736 {
737 NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv));
738 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
739 iterator ret(this->icont().insert_unique_commit(*tmp, data));
740 destroy_deallocator.release();
741 return ret;
742 }
743
744 std::pair<iterator,bool> insert_unique(const value_type& v)
745 {
746 insert_commit_data data;
747 std::pair<iterator,bool> ret =
748 this->insert_unique_check(KeyOfValue()(v), data);
749 if(ret.second){
750 ret.first = this->insert_unique_commit(v, data);
751 }
752 return ret;
753 }
754
755 template<class MovableConvertible>
756 std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) mv)
757 {
758 insert_commit_data data;
759 std::pair<iterator,bool> ret =
760 this->insert_unique_check(KeyOfValue()(mv), data);
761 if(ret.second){
762 ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data);
763 }
764 return ret;
765 }
766
767 private:
768
769 template<class MovableConvertible>
770 void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv)
771 {
772 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
773 //push_back has no-throw guarantee so avoid any deallocator/destroyer
774 this->icont().push_back(*tmp);
775 }
776
777 std::pair<iterator, bool> emplace_unique_impl(NodePtr p)
778 {
779 value_type &v = p->get_data();
780 insert_commit_data data;
781 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc());
782 std::pair<iterator,bool> ret =
783 this->insert_unique_check(KeyOfValue()(v), data);
784 if(!ret.second){
785 return ret;
786 }
787 //No throw insertion part, release rollback
788 destroy_deallocator.release();
789 return std::pair<iterator,bool>
790 ( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
791 , true );
792 }
793
794 iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p)
795 {
796 value_type &v = p->get_data();
797 insert_commit_data data;
798 std::pair<iterator,bool> ret =
799 this->insert_unique_check(hint, KeyOfValue()(v), data);
800 if(!ret.second){
801 Destroyer(this->node_alloc())(p);
802 return ret.first;
803 }
804 return iterator(iiterator(this->icont().insert_unique_commit(*p, data)));
805 }
806
807 public:
808
809 #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
810
811 template <class... Args>
812 std::pair<iterator, bool> emplace_unique(Args&&... args)
813 { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); }
814
815 template <class... Args>
816 iterator emplace_hint_unique(const_iterator hint, Args&&... args)
817 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); }
818
819 template <class... Args>
820 iterator emplace_equal(Args&&... args)
821 {
822 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
823 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
824 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
825 destroy_deallocator.release();
826 return ret;
827 }
828
829 template <class... Args>
830 iterator emplace_hint_equal(const_iterator hint, Args&&... args)
831 {
832 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
833 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
834 iterator ret(this->icont().insert_equal(hint.get(), *tmp));
835 destroy_deallocator.release();
836 return ret;
837 }
838
839 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
840
841 #define BOOST_PP_LOCAL_MACRO(n) \
842 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
843 std::pair<iterator, bool> emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
844 { \
845 return this->emplace_unique_impl \
846 (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
847 } \
848 \
849 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
850 iterator emplace_hint_unique(const_iterator hint \
851 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
852 { \
853 return this->emplace_unique_hint_impl \
854 (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
855 } \
856 \
857 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
858 iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
859 { \
860 NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
861 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \
862 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \
863 destroy_deallocator.release(); \
864 return ret; \
865 } \
866 \
867 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
868 iterator emplace_hint_equal(const_iterator hint \
869 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
870 { \
871 NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
872 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \
873 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \
874 destroy_deallocator.release(); \
875 return ret; \
876 } \
877 //!
878 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
879 #include BOOST_PP_LOCAL_ITERATE()
880
881 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
882
883 iterator insert_unique(const_iterator hint, const value_type& v)
884 {
885 insert_commit_data data;
886 std::pair<iterator,bool> ret =
887 this->insert_unique_check(hint, KeyOfValue()(v), data);
888 if(!ret.second)
889 return ret.first;
890 return this->insert_unique_commit(v, data);
891 }
892
893 template<class MovableConvertible>
894 iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv)
895 {
896 insert_commit_data data;
897 std::pair<iterator,bool> ret =
898 this->insert_unique_check(hint, KeyOfValue()(mv), data);
899 if(!ret.second)
900 return ret.first;
901 return this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data);
902 }
903
904 template <class InputIterator>
905 void insert_unique(InputIterator first, InputIterator last)
906 {
907 for( ; first != last; ++first)
908 this->insert_unique(*first);
909 }
910
911 iterator insert_equal(const value_type& v)
912 {
913 NodePtr tmp(AllocHolder::create_node(v));
914 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
915 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
916 destroy_deallocator.release();
917 return ret;
918 }
919
920 template<class MovableConvertible>
921 iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv)
922 {
923 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
924 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
925 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
926 destroy_deallocator.release();
927 return ret;
928 }
929
930 iterator insert_equal(const_iterator hint, const value_type& v)
931 {
932 NodePtr tmp(AllocHolder::create_node(v));
933 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
934 iterator ret(this->icont().insert_equal(hint.get(), *tmp));
935 destroy_deallocator.release();
936 return ret;
937 }
938
939 template<class MovableConvertible>
940 iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv)
941 {
942 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
943 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
944 iterator ret(this->icont().insert_equal(hint.get(), *tmp));
945 destroy_deallocator.release();
946 return ret;
947 }
948
949 template <class InputIterator>
950 void insert_equal(InputIterator first, InputIterator last)
951 {
952 for( ; first != last; ++first)
953 this->insert_equal(*first);
954 }
955
956 iterator erase(const_iterator position)
957 { return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); }
958
959 size_type erase(const key_type& k)
960 { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); }
961
962 iterator erase(const_iterator first, const_iterator last)
963 { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); }
964
965 void clear()
966 { AllocHolder::clear(alloc_version()); }
967
968 // set operations:
969 iterator find(const key_type& k)
970 { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
971
972 const_iterator find(const key_type& k) const
973 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); }
974
975 size_type count(const key_type& k) const
976 { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); }
977
978 iterator lower_bound(const key_type& k)
979 { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); }
980
981 const_iterator lower_bound(const key_type& k) const
982 { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); }
983
984 iterator upper_bound(const key_type& k)
985 { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
986
987 const_iterator upper_bound(const key_type& k) const
988 { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
989
990 std::pair<iterator,iterator> equal_range(const key_type& k)
991 {
992 std::pair<iiterator, iiterator> ret =
993 this->icont().equal_range(k, KeyNodeCompare(value_comp()));
994 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
995 }
996
997 std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
998 {
999 std::pair<iiterator, iiterator> ret =
1000 this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp()));
1001 return std::pair<const_iterator,const_iterator>
1002 (const_iterator(ret.first), const_iterator(ret.second));
1003 }
1004 };
1005
1006 template <class Key, class Value, class KeyOfValue,
1007 class KeyCompare, class A>
1008 inline bool
1009 operator==(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1010 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
1011 {
1012 return x.size() == y.size() &&
1013 std::equal(x.begin(), x.end(), y.begin());
1014 }
1015
1016 template <class Key, class Value, class KeyOfValue,
1017 class KeyCompare, class A>
1018 inline bool
1019 operator<(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1020 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
1021 {
1022 return std::lexicographical_compare(x.begin(), x.end(),
1023 y.begin(), y.end());
1024 }
1025
1026 template <class Key, class Value, class KeyOfValue,
1027 class KeyCompare, class A>
1028 inline bool
1029 operator!=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1030 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
1031 return !(x == y);
1032 }
1033
1034 template <class Key, class Value, class KeyOfValue,
1035 class KeyCompare, class A>
1036 inline bool
1037 operator>(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1038 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
1039 return y < x;
1040 }
1041
1042 template <class Key, class Value, class KeyOfValue,
1043 class KeyCompare, class A>
1044 inline bool
1045 operator<=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1046 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
1047 return !(y < x);
1048 }
1049
1050 template <class Key, class Value, class KeyOfValue,
1051 class KeyCompare, class A>
1052 inline bool
1053 operator>=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1054 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
1055 return !(x < y);
1056 }
1057
1058
1059 template <class Key, class Value, class KeyOfValue,
1060 class KeyCompare, class A>
1061 inline void
1062 swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
1063 rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
1064 {
1065 x.swap(y);
1066 }
1067
1068 } //namespace container_detail {
1069 } //namespace container {
1070 /*
1071 //!has_trivial_destructor_after_move<> == true_type
1072 //!specialization for optimizations
1073 template <class K, class V, class KOV,
1074 class C, class A>
1075 struct has_trivial_destructor_after_move
1076 <boost::container::container_detail::rbtree<K, V, KOV, C, A> >
1077 {
1078 static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
1079 };
1080 */
1081 } //namespace boost {
1082
1083 #include <boost/container/detail/config_end.hpp>
1084
1085 #endif //BOOST_CONTAINER_TREE_HPP