annotate DEPENDENCIES/generic/include/boost/container/detail/tree.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
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