Mercurial > hg > vamp-build-and-test
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 |