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