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