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