comparison DEPENDENCIES/generic/include/boost/container/detail/tree.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
comparison
equal deleted inserted replaced
100:793467b5e61c 101:c530137014c0
1 ////////////////////////////////////////////////////////////////////////////// 1 //////////////////////////////////////////////////////////////////////////////
2 // 2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost 3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file 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) 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 // 6 //
7 // See http://www.boost.org/libs/container for documentation. 7 // See http://www.boost.org/libs/container for documentation.
8 // 8 //
9 ////////////////////////////////////////////////////////////////////////////// 9 //////////////////////////////////////////////////////////////////////////////
10 10
11 #ifndef BOOST_CONTAINER_TREE_HPP 11 #ifndef BOOST_CONTAINER_TREE_HPP
12 #define BOOST_CONTAINER_TREE_HPP 12 #define BOOST_CONTAINER_TREE_HPP
13 13
14 #include "config_begin.hpp" 14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 # pragma once
20 #endif
21
22 #include <boost/container/detail/config_begin.hpp>
15 #include <boost/container/detail/workaround.hpp> 23 #include <boost/container/detail/workaround.hpp>
24 // container
25 #include <boost/container/allocator_traits.hpp>
16 #include <boost/container/container_fwd.hpp> 26 #include <boost/container/container_fwd.hpp>
17 27 #include <boost/container/options.hpp>
18 #include <boost/move/utility.hpp> 28
19 #include <boost/intrusive/pointer_traits.hpp> 29 // container/detail
20 #include <boost/type_traits/has_trivial_destructor.hpp> 30 #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
21 #include <boost/detail/no_exceptions_support.hpp> 31 #include <boost/container/detail/compare_functors.hpp>
22 #include <boost/intrusive/rbtree.hpp> 32 #include <boost/container/detail/destroyers.hpp>
23 #include <boost/container/detail/utilities.hpp> 33 #include <boost/container/detail/iterator.hpp>
24 #include <boost/container/detail/iterators.hpp> 34 #include <boost/container/detail/iterators.hpp>
25 #include <boost/container/detail/algorithms.hpp>
26 #include <boost/container/detail/node_alloc_holder.hpp> 35 #include <boost/container/detail/node_alloc_holder.hpp>
27 #include <boost/container/detail/destroyers.hpp>
28 #include <boost/container/detail/pair.hpp> 36 #include <boost/container/detail/pair.hpp>
29 #include <boost/container/detail/type_traits.hpp> 37 #include <boost/container/detail/type_traits.hpp>
30 #include <boost/container/allocator_traits.hpp> 38 // intrusive
31 #include <boost/detail/no_exceptions_support.hpp> 39 #include <boost/intrusive/pointer_traits.hpp>
32 #ifndef BOOST_CONTAINER_PERFECT_FORWARDING 40 #include <boost/intrusive/rbtree.hpp>
33 #include <boost/container/detail/preprocessor.hpp> 41 #include <boost/intrusive/avltree.hpp>
42 #include <boost/intrusive/splaytree.hpp>
43 #include <boost/intrusive/sgtree.hpp>
44 // intrusive/detail
45 #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
46 // move
47 #include <boost/move/utility_core.hpp>
48 // move/detail
49 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
50 #include <boost/move/detail/fwd_macros.hpp>
34 #endif 51 #endif
35 52 // other
36 #include <utility> //std::pair 53 #include <boost/core/no_exceptions_support.hpp>
37 #include <iterator>
38 #include <algorithm>
39 54
40 namespace boost { 55 namespace boost {
41 namespace container { 56 namespace container {
42 namespace container_detail { 57 namespace container_detail {
43 58
44 template<class Key, class Value, class KeyCompare, class KeyOfValue> 59 template<class Key, class T, class Compare, class KeyOfValue>
45 struct tree_value_compare 60 struct tree_value_compare
46 : public KeyCompare 61 : public Compare
47 { 62 {
48 typedef Value value_type; 63 typedef T value_type;
49 typedef KeyCompare key_compare; 64 typedef Compare key_compare;
50 typedef KeyOfValue key_of_value; 65 typedef KeyOfValue key_of_value;
51 typedef Key key_type; 66 typedef Key key_type;
52 67
53 explicit tree_value_compare(const key_compare &kcomp) 68 explicit tree_value_compare(const key_compare &kcomp)
54 : KeyCompare(kcomp) 69 : Compare(kcomp)
55 {} 70 {}
56 71
57 tree_value_compare() 72 tree_value_compare()
58 : KeyCompare() 73 : Compare()
59 {} 74 {}
60 75
61 const key_compare &key_comp() const 76 const key_compare &key_comp() const
62 { return static_cast<const key_compare &>(*this); } 77 { return static_cast<const key_compare &>(*this); }
63 78
64 key_compare &key_comp() 79 key_compare &key_comp()
65 { return static_cast<key_compare &>(*this); } 80 { return static_cast<key_compare &>(*this); }
66 81
67 template<class T> 82 template<class U>
68 struct is_key 83 struct is_key
69 { 84 {
70 static const bool value = is_same<const T, const key_type>::value; 85 static const bool value = is_same<const U, const key_type>::value;
71 }; 86 };
72 87
73 template<class T> 88 template<class U>
74 typename enable_if_c<is_key<T>::value, const key_type &>::type 89 typename enable_if_c<is_key<U>::value, const key_type &>::type
75 key_forward(const T &key) const 90 key_forward(const U &key) const
76 { return key; } 91 { return key; }
77 92
78 template<class T> 93 template<class U>
79 typename enable_if_c<!is_key<T>::value, const key_type &>::type 94 typename enable_if_c<!is_key<U>::value, const key_type &>::type
80 key_forward(const T &key) const 95 key_forward(const U &key) const
81 { return KeyOfValue()(key); } 96 { return KeyOfValue()(key); }
82 97
83 template<class KeyType, class KeyType2> 98 template<class KeyType, class KeyType2>
84 bool operator()(const KeyType &key1, const KeyType2 &key2) const 99 bool operator()(const KeyType &key1, const KeyType2 &key2) const
85 { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } 100 { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
86 }; 101
87 102 template<class KeyType, class KeyType2>
88 template<class VoidPointer> 103 bool operator()(const KeyType &key1, const KeyType2 &key2)
89 struct rbtree_hook 104 { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
105 };
106
107 template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
108 struct intrusive_tree_hook;
109
110 template<class VoidPointer, bool OptimizeSize>
111 struct intrusive_tree_hook<VoidPointer, boost::container::red_black_tree, OptimizeSize>
90 { 112 {
91 typedef typename container_detail::bi::make_set_base_hook 113 typedef typename container_detail::bi::make_set_base_hook
92 < container_detail::bi::void_pointer<VoidPointer> 114 < container_detail::bi::void_pointer<VoidPointer>
93 , container_detail::bi::link_mode<container_detail::bi::normal_link> 115 , container_detail::bi::link_mode<container_detail::bi::normal_link>
94 , container_detail::bi::optimize_size<true> 116 , container_detail::bi::optimize_size<OptimizeSize>
117 >::type type;
118 };
119
120 template<class VoidPointer, bool OptimizeSize>
121 struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize>
122 {
123 typedef typename container_detail::bi::make_avl_set_base_hook
124 < container_detail::bi::void_pointer<VoidPointer>
125 , container_detail::bi::link_mode<container_detail::bi::normal_link>
126 , container_detail::bi::optimize_size<OptimizeSize>
127 >::type type;
128 };
129
130 template<class VoidPointer, bool OptimizeSize>
131 struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize>
132 {
133 typedef typename container_detail::bi::make_bs_set_base_hook
134 < container_detail::bi::void_pointer<VoidPointer>
135 , container_detail::bi::link_mode<container_detail::bi::normal_link>
136 >::type type;
137 };
138
139 template<class VoidPointer, bool OptimizeSize>
140 struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize>
141 {
142 typedef typename container_detail::bi::make_bs_set_base_hook
143 < container_detail::bi::void_pointer<VoidPointer>
144 , container_detail::bi::link_mode<container_detail::bi::normal_link>
95 >::type type; 145 >::type type;
96 }; 146 };
97 147
98 //This trait is used to type-pun std::pair because in C++03 148 //This trait is used to type-pun std::pair because in C++03
99 //compilers std::pair is useless for C++11 features 149 //compilers std::pair is useless for C++11 features
100 template<class T> 150 template<class T>
101 struct rbtree_internal_data_type 151 struct tree_internal_data_type
102 { 152 {
103 typedef T type; 153 typedef T type;
104 }; 154 };
105 155
106 template<class T1, class T2> 156 template<class T1, class T2>
107 struct rbtree_internal_data_type< std::pair<T1, T2> > 157 struct tree_internal_data_type< std::pair<T1, T2> >
108 { 158 {
109 typedef pair<T1, T2> type; 159 typedef pair<T1, T2> type;
110 }; 160 };
111 161
112
113 //The node to be store in the tree 162 //The node to be store in the tree
114 template <class T, class VoidPointer> 163 template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
115 struct rbtree_node 164 struct tree_node
116 : public rbtree_hook<VoidPointer>::type 165 : public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
117 { 166 {
118 private: 167 private:
119 //BOOST_COPYABLE_AND_MOVABLE(rbtree_node) 168 //BOOST_COPYABLE_AND_MOVABLE(tree_node)
120 rbtree_node(); 169 tree_node();
121 170
122 public: 171 public:
123 typedef typename rbtree_hook<VoidPointer>::type hook_type; 172 typedef typename intrusive_tree_hook
124 173 <VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
125 typedef T value_type; 174 typedef T value_type;
126 typedef typename rbtree_internal_data_type<T>::type internal_type; 175 typedef typename tree_internal_data_type<T>::type internal_type;
127 176
128 typedef rbtree_node<T, VoidPointer> node_type; 177 typedef tree_node< T, VoidPointer
178 , tree_type_value, OptimizeSize> node_type;
129 179
130 T &get_data() 180 T &get_data()
131 { 181 {
132 T* ptr = reinterpret_cast<T*>(&this->m_data); 182 T* ptr = reinterpret_cast<T*>(&this->m_data);
133 return *ptr; 183 return *ptr;
139 return *ptr; 189 return *ptr;
140 } 190 }
141 191
142 internal_type m_data; 192 internal_type m_data;
143 193
144 template<class A, class B> 194 template<class T1, class T2>
145 void do_assign(const std::pair<const A, B> &p) 195 void do_assign(const std::pair<const T1, T2> &p)
146 { 196 {
147 const_cast<A&>(m_data.first) = p.first; 197 const_cast<T1&>(m_data.first) = p.first;
148 m_data.second = p.second; 198 m_data.second = p.second;
149 } 199 }
150 200
151 template<class A, class B> 201 template<class T1, class T2>
152 void do_assign(const pair<const A, B> &p) 202 void do_assign(const pair<const T1, T2> &p)
153 { 203 {
154 const_cast<A&>(m_data.first) = p.first; 204 const_cast<T1&>(m_data.first) = p.first;
155 m_data.second = p.second; 205 m_data.second = p.second;
156 } 206 }
157 207
158 template<class V> 208 template<class V>
159 void do_assign(const V &v) 209 void do_assign(const V &v)
160 { m_data = v; } 210 { m_data = v; }
161 211
162 template<class A, class B> 212 template<class T1, class T2>
163 void do_move_assign(std::pair<const A, B> &p) 213 void do_move_assign(std::pair<const T1, T2> &p)
164 { 214 {
165 const_cast<A&>(m_data.first) = ::boost::move(p.first); 215 const_cast<T1&>(m_data.first) = ::boost::move(p.first);
166 m_data.second = ::boost::move(p.second); 216 m_data.second = ::boost::move(p.second);
167 } 217 }
168 218
169 template<class A, class B> 219 template<class T1, class T2>
170 void do_move_assign(pair<const A, B> &p) 220 void do_move_assign(pair<const T1, T2> &p)
171 { 221 {
172 const_cast<A&>(m_data.first) = ::boost::move(p.first); 222 const_cast<T1&>(m_data.first) = ::boost::move(p.first);
173 m_data.second = ::boost::move(p.second); 223 m_data.second = ::boost::move(p.second);
174 } 224 }
175 225
176 template<class V> 226 template<class V>
177 void do_move_assign(V &v) 227 void do_move_assign(V &v)
178 { m_data = ::boost::move(v); } 228 { m_data = ::boost::move(v); }
229 };
230
231 template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
232 struct iiterator_node_value_type< tree_node<T, VoidPointer, tree_type_value, OptimizeSize> > {
233 typedef T type;
179 }; 234 };
180 235
181 template<class Node, class Icont> 236 template<class Node, class Icont>
182 class insert_equal_end_hint_functor 237 class insert_equal_end_hint_functor
183 { 238 {
208 263
209 }//namespace container_detail { 264 }//namespace container_detail {
210 265
211 namespace container_detail { 266 namespace container_detail {
212 267
213 template<class A, class ValueCompare> 268 template< class NodeType, class NodeCompareType
214 struct intrusive_rbtree_type 269 , class SizeType, class HookType
215 { 270 , boost::container::tree_type_enum tree_type_value>
271 struct intrusive_tree_dispatch;
272
273 template<class NodeType, class NodeCompareType, class SizeType, class HookType>
274 struct intrusive_tree_dispatch
275 <NodeType, NodeCompareType, SizeType, HookType, boost::container::red_black_tree>
276 {
277 typedef typename container_detail::bi::make_rbtree
278 <NodeType
279 ,container_detail::bi::compare<NodeCompareType>
280 ,container_detail::bi::base_hook<HookType>
281 ,container_detail::bi::constant_time_size<true>
282 ,container_detail::bi::size_type<SizeType>
283 >::type type;
284 };
285
286 template<class NodeType, class NodeCompareType, class SizeType, class HookType>
287 struct intrusive_tree_dispatch
288 <NodeType, NodeCompareType, SizeType, HookType, boost::container::avl_tree>
289 {
290 typedef typename container_detail::bi::make_avltree
291 <NodeType
292 ,container_detail::bi::compare<NodeCompareType>
293 ,container_detail::bi::base_hook<HookType>
294 ,container_detail::bi::constant_time_size<true>
295 ,container_detail::bi::size_type<SizeType>
296 >::type type;
297 };
298
299 template<class NodeType, class NodeCompareType, class SizeType, class HookType>
300 struct intrusive_tree_dispatch
301 <NodeType, NodeCompareType, SizeType, HookType, boost::container::scapegoat_tree>
302 {
303 typedef typename container_detail::bi::make_sgtree
304 <NodeType
305 ,container_detail::bi::compare<NodeCompareType>
306 ,container_detail::bi::base_hook<HookType>
307 ,container_detail::bi::floating_point<true>
308 ,container_detail::bi::size_type<SizeType>
309 >::type type;
310 };
311
312 template<class NodeType, class NodeCompareType, class SizeType, class HookType>
313 struct intrusive_tree_dispatch
314 <NodeType, NodeCompareType, SizeType, HookType, boost::container::splay_tree>
315 {
316 typedef typename container_detail::bi::make_splaytree
317 <NodeType
318 ,container_detail::bi::compare<NodeCompareType>
319 ,container_detail::bi::base_hook<HookType>
320 ,container_detail::bi::constant_time_size<true>
321 ,container_detail::bi::size_type<SizeType>
322 >::type type;
323 };
324
325 template<class Allocator, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
326 struct intrusive_tree_type
327 {
328 private:
216 typedef typename boost::container:: 329 typedef typename boost::container::
217 allocator_traits<A>::value_type value_type; 330 allocator_traits<Allocator>::value_type value_type;
218 typedef typename boost::container:: 331 typedef typename boost::container::
219 allocator_traits<A>::void_pointer void_pointer; 332 allocator_traits<Allocator>::void_pointer void_pointer;
220 typedef typename boost::container:: 333 typedef typename boost::container::
221 allocator_traits<A>::size_type size_type; 334 allocator_traits<Allocator>::size_type size_type;
222 typedef typename container_detail::rbtree_node 335 typedef typename container_detail::tree_node
223 <value_type, void_pointer> node_type; 336 < value_type, void_pointer
224 typedef node_compare<ValueCompare, node_type> node_compare_type; 337 , tree_type_value, OptimizeSize> node_type;
225 typedef typename container_detail::bi::make_rbtree 338 typedef value_to_node_compare
226 <node_type 339 <node_type, ValueCompare> node_compare_type;
227 ,container_detail::bi::compare<node_compare_type> 340 //Deducing the hook type from node_type (e.g. node_type::hook_type) would
228 ,container_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type> 341 //provoke an early instantiation of node_type that could ruin recursive
229 ,container_detail::bi::constant_time_size<true> 342 //tree definitions, so retype the complete type to avoid any problem.
230 ,container_detail::bi::size_type<size_type> 343 typedef typename intrusive_tree_hook
231 >::type container_type; 344 <void_pointer, tree_type_value
232 typedef container_type type ; 345 , OptimizeSize>::type hook_type;
346 public:
347 typedef typename intrusive_tree_dispatch
348 < node_type, node_compare_type
349 , size_type, hook_type
350 , tree_type_value>::type type;
351 };
352
353 //Trait to detect manually rebalanceable tree types
354 template<boost::container::tree_type_enum tree_type_value>
355 struct is_manually_balanceable
356 { static const bool value = true; };
357
358 template<> struct is_manually_balanceable<red_black_tree>
359 { static const bool value = false; };
360
361 template<> struct is_manually_balanceable<avl_tree>
362 { static const bool value = false; };
363
364 //Proxy traits to implement different operations depending on the
365 //is_manually_balanceable<>::value
366 template< boost::container::tree_type_enum tree_type_value
367 , bool IsManuallyRebalanceable = is_manually_balanceable<tree_type_value>::value>
368 struct intrusive_tree_proxy
369 {
370 template<class Icont>
371 static void rebalance(Icont &) {}
372 };
373
374 template<boost::container::tree_type_enum tree_type_value>
375 struct intrusive_tree_proxy<tree_type_value, true>
376 {
377 template<class Icont>
378 static void rebalance(Icont &c)
379 { c.rebalance(); }
233 }; 380 };
234 381
235 } //namespace container_detail { 382 } //namespace container_detail {
236 383
237 namespace container_detail { 384 namespace container_detail {
238 385
239 template <class Key, class Value, class KeyOfValue, 386 //This functor will be used with Intrusive clone functions to obtain
240 class KeyCompare, class A> 387 //already allocated nodes from a intrusive container instead of
241 class rbtree 388 //allocating new ones. When the intrusive container runs out of nodes
389 //the node holder is used instead.
390 template<class AllocHolder, bool DoMove>
391 class RecyclingCloner
392 {
393 typedef typename AllocHolder::intrusive_container intrusive_container;
394 typedef typename AllocHolder::Node node_type;
395 typedef typename AllocHolder::NodePtr node_ptr_type;
396
397 public:
398 RecyclingCloner(AllocHolder &holder, intrusive_container &itree)
399 : m_holder(holder), m_icont(itree)
400 {}
401
402 static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>)
403 { p->do_move_assign(const_cast<node_type &>(other).m_data); }
404
405 static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>)
406 { p->do_assign(other.m_data); }
407
408 node_ptr_type operator()(const node_type &other) const
409 {
410 if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
411 //First recycle a node (this can't throw)
412 BOOST_TRY{
413 //This can throw
414 this->do_assign(p, other, bool_<DoMove>());
415 return p;
416 }
417 BOOST_CATCH(...){
418 //If there is an exception destroy the whole source
419 m_holder.destroy_node(p);
420 while((p = m_icont.unlink_leftmost_without_rebalance())){
421 m_holder.destroy_node(p);
422 }
423 BOOST_RETHROW
424 }
425 BOOST_CATCH_END
426 }
427 else{
428 return m_holder.create_node(other.m_data);
429 }
430 }
431
432 AllocHolder &m_holder;
433 intrusive_container &m_icont;
434 };
435
436 template<class KeyValueCompare, class Node>
437 //where KeyValueCompare is tree_value_compare<Key, T, Compare, KeyOfValue>
438 struct key_node_compare
439 : private KeyValueCompare
440 {
441 explicit key_node_compare(const KeyValueCompare &comp)
442 : KeyValueCompare(comp)
443 {}
444
445 template<class T>
446 struct is_node
447 {
448 static const bool value = is_same<T, Node>::value;
449 };
450
451 template<class T>
452 typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type
453 key_forward(const T &node) const
454 { return node.get_data(); }
455
456 template<class T>
457 typename enable_if_c<!is_node<T>::value, const T &>::type
458 key_forward(const T &key) const
459 { return key; }
460
461 template<class KeyType, class KeyType2>
462 bool operator()(const KeyType &key1, const KeyType2 &key2) const
463 { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
464 };
465
466 template <class Key, class T, class KeyOfValue,
467 class Compare, class Allocator,
468 class Options = tree_assoc_defaults>
469 class tree
242 : protected container_detail::node_alloc_holder 470 : protected container_detail::node_alloc_holder
243 < A 471 < Allocator
244 , typename container_detail::intrusive_rbtree_type 472 , typename container_detail::intrusive_tree_type
245 <A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> 473 < Allocator, tree_value_compare<Key, T, Compare, KeyOfValue> //ValComp
246 >::type 474 , Options::tree_type, Options::optimize_size>::type
247 , tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
248 > 475 >
249 { 476 {
250 typedef tree_value_compare 477 typedef tree_value_compare
251 <Key, Value, KeyCompare, KeyOfValue> ValComp; 478 <Key, T, Compare, KeyOfValue> ValComp;
252 typedef typename container_detail::intrusive_rbtree_type 479 typedef typename container_detail::intrusive_tree_type
253 < A, ValComp>::type Icont; 480 < Allocator, ValComp, Options::tree_type
254 typedef container_detail::node_alloc_holder 481 , Options::optimize_size>::type Icont;
255 <A, Icont, ValComp> AllocHolder; 482 typedef container_detail::node_alloc_holder
483 <Allocator, Icont> AllocHolder;
256 typedef typename AllocHolder::NodePtr NodePtr; 484 typedef typename AllocHolder::NodePtr NodePtr;
257 typedef rbtree < Key, Value, KeyOfValue 485 typedef tree < Key, T, KeyOfValue
258 , KeyCompare, A> ThisType; 486 , Compare, Allocator, Options> ThisType;
259 typedef typename AllocHolder::NodeAlloc NodeAlloc; 487 typedef typename AllocHolder::NodeAlloc NodeAlloc;
488 typedef boost::container::
489 allocator_traits<NodeAlloc> allocator_traits_type;
260 typedef typename AllocHolder::ValAlloc ValAlloc; 490 typedef typename AllocHolder::ValAlloc ValAlloc;
261 typedef typename AllocHolder::Node Node; 491 typedef typename AllocHolder::Node Node;
262 typedef typename Icont::iterator iiterator; 492 typedef typename Icont::iterator iiterator;
263 typedef typename Icont::const_iterator iconst_iterator; 493 typedef typename Icont::const_iterator iconst_iterator;
264 typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; 494 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; 495 typedef typename AllocHolder::alloc_version alloc_version;
268 496 typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
269 class RecyclingCloner; 497
270 friend class RecyclingCloner; 498 BOOST_COPYABLE_AND_MOVABLE(tree)
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 499
347 public: 500 public:
348 501
349 typedef Key key_type; 502 typedef Key key_type;
350 typedef Value value_type; 503 typedef T value_type;
351 typedef A allocator_type; 504 typedef Allocator allocator_type;
352 typedef KeyCompare key_compare; 505 typedef Compare key_compare;
353 typedef ValComp value_compare; 506 typedef ValComp value_compare;
354 typedef typename boost::container:: 507 typedef typename boost::container::
355 allocator_traits<A>::pointer pointer; 508 allocator_traits<Allocator>::pointer pointer;
356 typedef typename boost::container:: 509 typedef typename boost::container::
357 allocator_traits<A>::const_pointer const_pointer; 510 allocator_traits<Allocator>::const_pointer const_pointer;
358 typedef typename boost::container:: 511 typedef typename boost::container::
359 allocator_traits<A>::reference reference; 512 allocator_traits<Allocator>::reference reference;
360 typedef typename boost::container:: 513 typedef typename boost::container::
361 allocator_traits<A>::const_reference const_reference; 514 allocator_traits<Allocator>::const_reference const_reference;
362 typedef typename boost::container:: 515 typedef typename boost::container::
363 allocator_traits<A>::size_type size_type; 516 allocator_traits<Allocator>::size_type size_type;
364 typedef typename boost::container:: 517 typedef typename boost::container::
365 allocator_traits<A>::difference_type difference_type; 518 allocator_traits<Allocator>::difference_type difference_type;
366 typedef difference_type rbtree_difference_type; 519 typedef difference_type tree_difference_type;
367 typedef pointer rbtree_pointer; 520 typedef pointer tree_pointer;
368 typedef const_pointer rbtree_const_pointer; 521 typedef const_pointer tree_const_pointer;
369 typedef reference rbtree_reference; 522 typedef reference tree_reference;
370 typedef const_reference rbtree_const_reference; 523 typedef const_reference tree_const_reference;
371 typedef NodeAlloc stored_allocator_type; 524 typedef NodeAlloc stored_allocator_type;
372 525
373 private: 526 private:
374 527
375 template<class KeyValueCompare> 528 typedef key_node_compare<value_compare, Node> KeyNodeCompare;
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 529
406 public: 530 public:
407 typedef container_detail::iterator<iiterator, false> iterator; 531 typedef container_detail::iterator_from_iiterator<iiterator, false> iterator;
408 typedef container_detail::iterator<iiterator, true > const_iterator; 532 typedef container_detail::iterator_from_iiterator<iiterator, true > const_iterator;
409 typedef std::reverse_iterator<iterator> reverse_iterator; 533 typedef boost::container::reverse_iterator<iterator> reverse_iterator;
410 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 534 typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
411 535
412 rbtree() 536 tree()
413 : AllocHolder(ValComp(key_compare())) 537 : AllocHolder()
414 {} 538 {}
415 539
416 explicit rbtree(const key_compare& comp, const allocator_type& a = allocator_type()) 540 explicit tree(const key_compare& comp, const allocator_type& a = allocator_type())
417 : AllocHolder(a, ValComp(comp)) 541 : AllocHolder(ValComp(comp), a)
418 {} 542 {}
419 543
420 explicit rbtree(const allocator_type& a) 544 explicit tree(const allocator_type& a)
421 : AllocHolder(a) 545 : AllocHolder(a)
422 {} 546 {}
423 547
424 template <class InputIterator> 548 template <class InputIterator>
425 rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, 549 tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
426 const allocator_type& a 550 const allocator_type& a
427 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 551 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
428 , typename container_detail::enable_if_c 552 , typename container_detail::enable_if_c
429 < container_detail::is_input_iterator<InputIterator>::value 553 < container_detail::is_input_iterator<InputIterator>::value
430 || container_detail::is_same<alloc_version, allocator_v1>::value 554 || container_detail::is_same<alloc_version, version_1>::value
431 >::type * = 0 555 >::type * = 0
432 #endif 556 #endif
433 ) 557 )
434 : AllocHolder(a, value_compare(comp)) 558 : AllocHolder(value_compare(comp), a)
435 { 559 {
436 //Use cend() as hint to achieve linear time for 560 //Use cend() as hint to achieve linear time for
437 //ordered ranges as required by the standard 561 //ordered ranges as required by the standard
438 //for the constructor 562 //for the constructor
439 const const_iterator end_it(this->cend()); 563 const const_iterator end_it(this->cend());
448 } 572 }
449 } 573 }
450 } 574 }
451 575
452 template <class InputIterator> 576 template <class InputIterator>
453 rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, 577 tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
454 const allocator_type& a 578 const allocator_type& a
455 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 579 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
456 , typename container_detail::enable_if_c 580 , typename container_detail::enable_if_c
457 < !(container_detail::is_input_iterator<InputIterator>::value 581 < !(container_detail::is_input_iterator<InputIterator>::value
458 || container_detail::is_same<alloc_version, allocator_v1>::value) 582 || container_detail::is_same<alloc_version, version_1>::value)
459 >::type * = 0 583 >::type * = 0
460 #endif 584 #endif
461 ) 585 )
462 : AllocHolder(a, value_compare(comp)) 586 : AllocHolder(value_compare(comp), a)
463 { 587 {
464 if(unique_insertion){ 588 if(unique_insertion){
465 //Use cend() as hint to achieve linear time for 589 //Use cend() as hint to achieve linear time for
466 //ordered ranges as required by the standard 590 //ordered ranges as required by the standard
467 //for the constructor 591 //for the constructor
471 } 595 }
472 } 596 }
473 else{ 597 else{
474 //Optimized allocation and construction 598 //Optimized allocation and construction
475 this->allocate_many_and_construct 599 this->allocate_many_and_construct
476 ( first, std::distance(first, last) 600 ( first, boost::container::iterator_distance(first, last)
477 , insert_equal_end_hint_functor<Node, Icont>(this->icont())); 601 , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
478 } 602 }
479 } 603 }
480 604
481 template <class InputIterator> 605 template <class InputIterator>
482 rbtree( ordered_range_t, InputIterator first, InputIterator last 606 tree( ordered_range_t, InputIterator first, InputIterator last
483 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() 607 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
484 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 608 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
485 , typename container_detail::enable_if_c 609 , typename container_detail::enable_if_c
486 < container_detail::is_input_iterator<InputIterator>::value 610 < container_detail::is_input_iterator<InputIterator>::value
487 || container_detail::is_same<alloc_version, allocator_v1>::value 611 || container_detail::is_same<alloc_version, version_1>::value
488 >::type * = 0 612 >::type * = 0
489 #endif 613 #endif
490 ) 614 )
491 : AllocHolder(a, value_compare(comp)) 615 : AllocHolder(value_compare(comp), a)
492 { 616 {
493 for ( ; first != last; ++first){ 617 for ( ; first != last; ++first){
494 this->push_back_impl(*first); 618 this->push_back_impl(*first);
495 } 619 }
496 } 620 }
497 621
498 template <class InputIterator> 622 template <class InputIterator>
499 rbtree( ordered_range_t, InputIterator first, InputIterator last 623 tree( ordered_range_t, InputIterator first, InputIterator last
500 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() 624 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
501 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 625 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
502 , typename container_detail::enable_if_c 626 , typename container_detail::enable_if_c
503 < !(container_detail::is_input_iterator<InputIterator>::value 627 < !(container_detail::is_input_iterator<InputIterator>::value
504 || container_detail::is_same<alloc_version, allocator_v1>::value) 628 || container_detail::is_same<alloc_version, version_1>::value)
505 >::type * = 0 629 >::type * = 0
506 #endif 630 #endif
507 ) 631 )
508 : AllocHolder(a, value_compare(comp)) 632 : AllocHolder(value_compare(comp), a)
509 { 633 {
510 //Optimized allocation and construction 634 //Optimized allocation and construction
511 this->allocate_many_and_construct 635 this->allocate_many_and_construct
512 ( first, std::distance(first, last) 636 ( first, boost::container::iterator_distance(first, last)
513 , container_detail::push_back_functor<Node, Icont>(this->icont())); 637 , container_detail::push_back_functor<Node, Icont>(this->icont()));
514 } 638 }
515 639
516 rbtree(const rbtree& x) 640 tree(const tree& x)
517 : AllocHolder(x, x.value_comp()) 641 : AllocHolder(x.value_comp(), x)
518 { 642 {
519 this->icont().clone_from 643 this->icont().clone_from
520 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 644 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
521 } 645 }
522 646
523 rbtree(BOOST_RV_REF(rbtree) x) 647 tree(BOOST_RV_REF(tree) x)
524 : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.value_comp()) 648 : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp())
525 {} 649 {}
526 650
527 rbtree(const rbtree& x, const allocator_type &a) 651 tree(const tree& x, const allocator_type &a)
528 : AllocHolder(a, x.value_comp()) 652 : AllocHolder(x.value_comp(), a)
529 { 653 {
530 this->icont().clone_from 654 this->icont().clone_from
531 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 655 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
532 } 656 }
533 657
534 rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a) 658 tree(BOOST_RV_REF(tree) x, const allocator_type &a)
535 : AllocHolder(a, x.value_comp()) 659 : AllocHolder(x.value_comp(), a)
536 { 660 {
537 if(this->node_alloc() == x.node_alloc()){ 661 if(this->node_alloc() == x.node_alloc()){
538 this->icont().swap(x.icont()); 662 this->icont().swap(x.icont());
539 } 663 }
540 else{ 664 else{
541 this->icont().clone_from 665 this->icont().clone_from
542 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 666 (x.icont(), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc()));
543 } 667 }
544 } 668 }
545 669
546 ~rbtree() 670 ~tree()
547 {} //AllocHolder clears the tree 671 {} //AllocHolder clears the tree
548 672
549 rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x) 673 tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
550 { 674 {
551 if (&x != this){ 675 if (&x != this){
552 NodeAlloc &this_alloc = this->get_stored_allocator(); 676 NodeAlloc &this_alloc = this->get_stored_allocator();
553 const NodeAlloc &x_alloc = x.get_stored_allocator(); 677 const NodeAlloc &x_alloc = x.get_stored_allocator();
554 container_detail::bool_<allocator_traits<NodeAlloc>:: 678 container_detail::bool_<allocator_traits<NodeAlloc>::
563 Icont other_tree(::boost::move(this->icont())); 687 Icont other_tree(::boost::move(this->icont()));
564 688
565 //Now recreate the source tree reusing nodes stored by other_tree 689 //Now recreate the source tree reusing nodes stored by other_tree
566 this->icont().clone_from 690 this->icont().clone_from
567 (x.icont() 691 (x.icont()
568 , RecyclingCloner(*this, other_tree) 692 , RecyclingCloner<AllocHolder, false>(*this, other_tree)
569 , Destroyer(this->node_alloc())); 693 , Destroyer(this->node_alloc()));
570 694
571 //If there are remaining nodes, destroy them 695 //If there are remaining nodes, destroy them
572 NodePtr p; 696 NodePtr p;
573 while((p = other_tree.unlink_leftmost_without_rebalance())){ 697 while((p = other_tree.unlink_leftmost_without_rebalance())){
575 } 699 }
576 } 700 }
577 return *this; 701 return *this;
578 } 702 }
579 703
580 rbtree& operator=(BOOST_RV_REF(rbtree) x) 704 tree& operator=(BOOST_RV_REF(tree) x)
581 { 705 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
582 if (&x != this){ 706 && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value )
583 NodeAlloc &this_alloc = this->get_stored_allocator(); 707 {
584 const NodeAlloc &x_alloc = x.get_stored_allocator(); 708 BOOST_ASSERT(this != &x);
585 //If allocators are equal we can just swap pointers 709 NodeAlloc &this_alloc = this->node_alloc();
586 if(this_alloc == x_alloc){ 710 NodeAlloc &x_alloc = x.node_alloc();
587 //Destroy and swap pointers 711 const bool propagate_alloc = allocator_traits<NodeAlloc>::
588 this->clear(); 712 propagate_on_container_move_assignment::value;
589 this->icont() = ::boost::move(x.icont()); 713 const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
590 //Move allocator if needed 714 //Resources can be transferred if both allocators are
591 this->AllocHolder::move_assign_alloc(x); 715 //going to be equal after this function (either propagated or already equal)
716 if(propagate_alloc || allocators_equal){
717 //Destroy
718 this->clear();
719 //Move allocator if needed
720 this->AllocHolder::move_assign_alloc(x);
721 //Obtain resources
722 this->icont() = boost::move(x.icont());
723 }
724 //Else do a one by one move
725 else{
726 //Transfer all the nodes to a temporary tree
727 //If anything goes wrong, all the nodes will be destroyed
728 //automatically
729 Icont other_tree(::boost::move(this->icont()));
730
731 //Now recreate the source tree reusing nodes stored by other_tree
732 this->icont().clone_from
733 (x.icont()
734 , RecyclingCloner<AllocHolder, true>(*this, other_tree)
735 , Destroyer(this->node_alloc()));
736
737 //If there are remaining nodes, destroy them
738 NodePtr p;
739 while((p = other_tree.unlink_leftmost_without_rebalance())){
740 AllocHolder::destroy_node(p);
592 } 741 }
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 } 742 }
613 return *this; 743 return *this;
614 } 744 }
615 745
616 public: 746 public:
617 // accessors: 747 // accessors:
618 value_compare value_comp() const 748 value_compare value_comp() const
619 { return this->icont().value_comp().value_comp(); } 749 { return this->icont().value_comp().predicate(); }
620 750
621 key_compare key_comp() const 751 key_compare key_comp() const
622 { return this->icont().value_comp().value_comp().key_comp(); } 752 { return this->icont().value_comp().predicate().key_comp(); }
623 753
624 allocator_type get_allocator() const 754 allocator_type get_allocator() const
625 { return allocator_type(this->node_alloc()); } 755 { return allocator_type(this->node_alloc()); }
626 756
627 const stored_allocator_type &get_stored_allocator() const 757 const stored_allocator_type &get_stored_allocator() const
696 826
697 size_type max_size() const 827 size_type max_size() const
698 { return AllocHolder::max_size(); } 828 { return AllocHolder::max_size(); }
699 829
700 void swap(ThisType& x) 830 void swap(ThisType& x)
831 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
832 && boost::container::container_detail::is_nothrow_swappable<Compare>::value )
701 { AllocHolder::swap(x); } 833 { AllocHolder::swap(x); }
702 834
703 public: 835 public:
704 836
705 typedef typename Icont::insert_commit_data insert_commit_data; 837 typedef typename Icont::insert_commit_data insert_commit_data;
730 return ret; 862 return ret;
731 } 863 }
732 864
733 template<class MovableConvertible> 865 template<class MovableConvertible>
734 iterator insert_unique_commit 866 iterator insert_unique_commit
735 (BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data) 867 (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data)
736 { 868 {
737 NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv)); 869 NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(v));
738 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 870 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
739 iterator ret(this->icont().insert_unique_commit(*tmp, data)); 871 iterator ret(this->icont().insert_unique_commit(*tmp, data));
740 destroy_deallocator.release(); 872 destroy_deallocator.release();
741 return ret; 873 return ret;
742 } 874 }
751 } 883 }
752 return ret; 884 return ret;
753 } 885 }
754 886
755 template<class MovableConvertible> 887 template<class MovableConvertible>
756 std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) mv) 888 std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v)
757 { 889 {
758 insert_commit_data data; 890 insert_commit_data data;
759 std::pair<iterator,bool> ret = 891 std::pair<iterator,bool> ret =
760 this->insert_unique_check(KeyOfValue()(mv), data); 892 this->insert_unique_check(KeyOfValue()(v), data);
761 if(ret.second){ 893 if(ret.second){
762 ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); 894 ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
763 } 895 }
764 return ret; 896 return ret;
765 } 897 }
766 898
767 private: 899 private:
768 900
769 template<class MovableConvertible> 901 template<class MovableConvertible>
770 void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv) 902 void push_back_impl(BOOST_FWD_REF(MovableConvertible) v)
771 { 903 {
772 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); 904 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
773 //push_back has no-throw guarantee so avoid any deallocator/destroyer 905 //push_back has no-throw guarantee so avoid any deallocator/destroyer
774 this->icont().push_back(*tmp); 906 this->icont().push_back(*tmp);
775 } 907 }
776 908
777 std::pair<iterator, bool> emplace_unique_impl(NodePtr p) 909 std::pair<iterator, bool> emplace_unique_impl(NodePtr p)
804 return iterator(iiterator(this->icont().insert_unique_commit(*p, data))); 936 return iterator(iiterator(this->icont().insert_unique_commit(*p, data)));
805 } 937 }
806 938
807 public: 939 public:
808 940
809 #ifdef BOOST_CONTAINER_PERFECT_FORWARDING 941 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
810 942
811 template <class... Args> 943 template <class... Args>
812 std::pair<iterator, bool> emplace_unique(Args&&... args) 944 std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
813 { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); } 945 { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); }
814 946
815 template <class... Args> 947 template <class... Args>
816 iterator emplace_hint_unique(const_iterator hint, Args&&... args) 948 iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
817 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); } 949 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); }
818 950
819 template <class... Args> 951 template <class... Args>
820 iterator emplace_equal(Args&&... args) 952 iterator emplace_equal(BOOST_FWD_REF(Args)... args)
821 { 953 {
822 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); 954 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
823 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 955 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
824 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 956 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
825 destroy_deallocator.release(); 957 destroy_deallocator.release();
826 return ret; 958 return ret;
827 } 959 }
828 960
829 template <class... Args> 961 template <class... Args>
830 iterator emplace_hint_equal(const_iterator hint, Args&&... args) 962 iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
831 { 963 {
832 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); 964 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
833 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 965 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
834 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); 966 iterator ret(this->icont().insert_equal(hint.get(), *tmp));
835 destroy_deallocator.release(); 967 destroy_deallocator.release();
836 return ret; 968 return ret;
837 } 969 }
838 970
839 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 971 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
840 972
841 #define BOOST_PP_LOCAL_MACRO(n) \ 973 #define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \
842 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 974 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
843 std::pair<iterator, bool> emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 975 std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
844 { \ 976 { return this->emplace_unique_impl(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
845 return this->emplace_unique_impl \ 977 \
846 (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 978 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
847 } \ 979 iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
848 \ 980 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
849 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 981 \
850 iterator emplace_hint_unique(const_iterator hint \ 982 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
851 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 983 iterator emplace_equal(BOOST_MOVE_UREF##N)\
852 { \ 984 {\
853 return this->emplace_unique_hint_impl \ 985 NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\
854 (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 986 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\
855 } \ 987 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\
856 \ 988 destroy_deallocator.release();\
857 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 989 return ret;\
858 iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 990 }\
859 { \ 991 \
860 NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 992 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
861 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \ 993 iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
862 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \ 994 {\
863 destroy_deallocator.release(); \ 995 NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\
864 return ret; \ 996 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\
865 } \ 997 iterator ret(this->icont().insert_equal(hint.get(), *tmp));\
866 \ 998 destroy_deallocator.release();\
867 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 999 return ret;\
868 iterator emplace_hint_equal(const_iterator hint \ 1000 }\
869 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 1001 //
870 { \ 1002 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE)
871 NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 1003 #undef BOOST_CONTAINER_TREE_EMPLACE_CODE
872 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \ 1004
873 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \ 1005 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
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 1006
883 iterator insert_unique(const_iterator hint, const value_type& v) 1007 iterator insert_unique(const_iterator hint, const value_type& v)
884 { 1008 {
885 insert_commit_data data; 1009 insert_commit_data data;
886 std::pair<iterator,bool> ret = 1010 std::pair<iterator,bool> ret =
889 return ret.first; 1013 return ret.first;
890 return this->insert_unique_commit(v, data); 1014 return this->insert_unique_commit(v, data);
891 } 1015 }
892 1016
893 template<class MovableConvertible> 1017 template<class MovableConvertible>
894 iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) 1018 iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
895 { 1019 {
896 insert_commit_data data; 1020 insert_commit_data data;
897 std::pair<iterator,bool> ret = 1021 std::pair<iterator,bool> ret =
898 this->insert_unique_check(hint, KeyOfValue()(mv), data); 1022 this->insert_unique_check(hint, KeyOfValue()(v), data);
899 if(!ret.second) 1023 if(!ret.second)
900 return ret.first; 1024 return ret.first;
901 return this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); 1025 return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
902 } 1026 }
903 1027
904 template <class InputIterator> 1028 template <class InputIterator>
905 void insert_unique(InputIterator first, InputIterator last) 1029 void insert_unique(InputIterator first, InputIterator last)
906 { 1030 {
916 destroy_deallocator.release(); 1040 destroy_deallocator.release();
917 return ret; 1041 return ret;
918 } 1042 }
919 1043
920 template<class MovableConvertible> 1044 template<class MovableConvertible>
921 iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv) 1045 iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v)
922 { 1046 {
923 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); 1047 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
924 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1048 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
925 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1049 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
926 destroy_deallocator.release(); 1050 destroy_deallocator.release();
927 return ret; 1051 return ret;
928 } 1052 }
935 destroy_deallocator.release(); 1059 destroy_deallocator.release();
936 return ret; 1060 return ret;
937 } 1061 }
938 1062
939 template<class MovableConvertible> 1063 template<class MovableConvertible>
940 iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) 1064 iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
941 { 1065 {
942 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); 1066 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
943 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1067 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
944 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); 1068 iterator ret(this->icont().insert_equal(hint.get(), *tmp));
945 destroy_deallocator.release(); 1069 destroy_deallocator.release();
946 return ret; 1070 return ret;
947 } 1071 }
963 { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } 1087 { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); }
964 1088
965 void clear() 1089 void clear()
966 { AllocHolder::clear(alloc_version()); } 1090 { AllocHolder::clear(alloc_version()); }
967 1091
968 // set operations: 1092 // search operations. Const and non-const overloads even if no iterator is returned
1093 // so splay implementations can to their rebalancing when searching in non-const versions
969 iterator find(const key_type& k) 1094 iterator find(const key_type& k)
970 { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } 1095 { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
971 1096
972 const_iterator find(const key_type& k) const 1097 const_iterator find(const key_type& k) const
973 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); } 1098 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); }
999 std::pair<iiterator, iiterator> ret = 1124 std::pair<iiterator, iiterator> ret =
1000 this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp())); 1125 this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp()));
1001 return std::pair<const_iterator,const_iterator> 1126 return std::pair<const_iterator,const_iterator>
1002 (const_iterator(ret.first), const_iterator(ret.second)); 1127 (const_iterator(ret.first), const_iterator(ret.second));
1003 } 1128 }
1004 }; 1129
1005 1130 std::pair<iterator,iterator> lower_bound_range(const key_type& k)
1006 template <class Key, class Value, class KeyOfValue, 1131 {
1007 class KeyCompare, class A> 1132 std::pair<iiterator, iiterator> ret =
1008 inline bool 1133 this->icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
1009 operator==(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 1134 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
1010 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 1135 }
1011 { 1136
1012 return x.size() == y.size() && 1137 std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
1013 std::equal(x.begin(), x.end(), y.begin()); 1138 {
1014 } 1139 std::pair<iiterator, iiterator> ret =
1015 1140 this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
1016 template <class Key, class Value, class KeyOfValue, 1141 return std::pair<const_iterator,const_iterator>
1017 class KeyCompare, class A> 1142 (const_iterator(ret.first), const_iterator(ret.second));
1018 inline bool 1143 }
1019 operator<(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 1144
1020 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 1145 void rebalance()
1021 { 1146 { intrusive_tree_proxy_t::rebalance(this->icont()); }
1022 return std::lexicographical_compare(x.begin(), x.end(), 1147
1023 y.begin(), y.end()); 1148 friend bool operator==(const tree& x, const tree& y)
1024 } 1149 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
1025 1150
1026 template <class Key, class Value, class KeyOfValue, 1151 friend bool operator<(const tree& x, const tree& y)
1027 class KeyCompare, class A> 1152 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
1028 inline bool 1153
1029 operator!=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 1154 friend bool operator!=(const tree& x, const tree& y)
1030 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) { 1155 { return !(x == y); }
1031 return !(x == y); 1156
1032 } 1157 friend bool operator>(const tree& x, const tree& y)
1033 1158 { return y < x; }
1034 template <class Key, class Value, class KeyOfValue, 1159
1035 class KeyCompare, class A> 1160 friend bool operator<=(const tree& x, const tree& y)
1036 inline bool 1161 { return !(y < x); }
1037 operator>(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 1162
1038 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) { 1163 friend bool operator>=(const tree& x, const tree& y)
1039 return y < x; 1164 { return !(x < y); }
1040 } 1165
1041 1166 friend void swap(tree& x, tree& y)
1042 template <class Key, class Value, class KeyOfValue, 1167 { x.swap(y); }
1043 class KeyCompare, class A> 1168 };
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 1169
1068 } //namespace container_detail { 1170 } //namespace container_detail {
1069 } //namespace container { 1171 } //namespace container {
1070 /* 1172
1173 template <class T>
1174 struct has_trivial_destructor_after_move;
1175
1071 //!has_trivial_destructor_after_move<> == true_type 1176 //!has_trivial_destructor_after_move<> == true_type
1072 //!specialization for optimizations 1177 //!specialization for optimizations
1073 template <class K, class V, class KOV, 1178 template <class Key, class T, class KeyOfValue, class Compare, class Allocator, class Options>
1074 class C, class A>
1075 struct has_trivial_destructor_after_move 1179 struct has_trivial_destructor_after_move
1076 <boost::container::container_detail::rbtree<K, V, KOV, C, A> > 1180 <
1077 { 1181 ::boost::container::container_detail::tree
1078 static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value; 1182 <Key, T, KeyOfValue, Compare, Allocator, Options>
1079 }; 1183 >
1080 */ 1184 {
1185 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
1186 static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
1187 ::boost::has_trivial_destructor_after_move<pointer>::value &&
1188 ::boost::has_trivial_destructor_after_move<Compare>::value;
1189 };
1190
1081 } //namespace boost { 1191 } //namespace boost {
1082 1192
1083 #include <boost/container/detail/config_end.hpp> 1193 #include <boost/container/detail/config_end.hpp>
1084 1194
1085 #endif //BOOST_CONTAINER_TREE_HPP 1195 #endif //BOOST_CONTAINER_TREE_HPP