1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_TREE_HPP 12 #define BOOST_CONTAINER_TREE_HPP 13 14 #ifndef BOOST_CONFIG_HPP 15 # include <boost/config.hpp> 16 #endif 17 18 #if defined(BOOST_HAS_PRAGMA_ONCE) 19 # pragma once 20 #endif 21 22 #include <boost/container/detail/config_begin.hpp> 23 #include <boost/container/detail/workaround.hpp> 24 // container 25 #include <boost/container/allocator_traits.hpp> 26 #include <boost/container/container_fwd.hpp> 27 #include <boost/container/options.hpp> 28 #include <boost/container/node_handle.hpp> 29 30 // container/detail 31 #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare 32 #include <boost/container/detail/compare_functors.hpp> 33 #include <boost/container/detail/destroyers.hpp> 34 #include <boost/container/detail/iterator.hpp> 35 #include <boost/container/detail/iterators.hpp> 36 #include <boost/container/detail/node_alloc_holder.hpp> 37 #include <boost/container/detail/pair.hpp> 38 #include <boost/container/detail/type_traits.hpp> 39 // intrusive 40 #include <boost/intrusive/pointer_traits.hpp> 41 #include <boost/intrusive/rbtree.hpp> 42 #include <boost/intrusive/avltree.hpp> 43 #include <boost/intrusive/splaytree.hpp> 44 #include <boost/intrusive/sgtree.hpp> 45 // intrusive/detail 46 #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair 47 #include <boost/intrusive/detail/tree_value_compare.hpp> //tree_value_compare 48 // move 49 #include <boost/move/utility_core.hpp> 50 // move/detail 51 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 52 #include <boost/move/detail/fwd_macros.hpp> 53 #endif 54 #include <boost/move/detail/move_helpers.hpp> 55 // other 56 #include <boost/core/no_exceptions_support.hpp> 57 58 59 60 #include <boost/container/detail/std_fwd.hpp> 61 62 namespace boost { 63 namespace container { 64 namespace dtl { 65 66 using boost::intrusive::tree_value_compare; 67 68 template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> 69 struct intrusive_tree_hook; 70 71 template<class VoidPointer, bool OptimizeSize> 72 struct intrusive_tree_hook<VoidPointer, boost::container::red_black_tree, OptimizeSize> 73 { 74 typedef typename dtl::bi::make_set_base_hook 75 < dtl::bi::void_pointer<VoidPointer> 76 , dtl::bi::link_mode<dtl::bi::normal_link> 77 , dtl::bi::optimize_size<OptimizeSize> 78 >::type type; 79 }; 80 81 template<class VoidPointer, bool OptimizeSize> 82 struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize> 83 { 84 typedef typename dtl::bi::make_avl_set_base_hook 85 < dtl::bi::void_pointer<VoidPointer> 86 , dtl::bi::link_mode<dtl::bi::normal_link> 87 , dtl::bi::optimize_size<OptimizeSize> 88 >::type type; 89 }; 90 91 template<class VoidPointer, bool OptimizeSize> 92 struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize> 93 { 94 typedef typename dtl::bi::make_bs_set_base_hook 95 < dtl::bi::void_pointer<VoidPointer> 96 , dtl::bi::link_mode<dtl::bi::normal_link> 97 >::type type; 98 }; 99 100 template<class VoidPointer, bool OptimizeSize> 101 struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize> 102 { 103 typedef typename dtl::bi::make_bs_set_base_hook 104 < dtl::bi::void_pointer<VoidPointer> 105 , dtl::bi::link_mode<dtl::bi::normal_link> 106 >::type type; 107 }; 108 109 //This trait is used to type-pun std::pair because in C++03 110 //compilers std::pair is useless for C++11 features 111 template<class T> 112 struct tree_internal_data_type 113 { 114 typedef T type; 115 }; 116 117 template<class T1, class T2> 118 struct tree_internal_data_type< std::pair<T1, T2> > 119 { 120 typedef pair<typename boost::move_detail::remove_const<T1>::type, T2> type; 121 }; 122 123 //The node to be store in the tree 124 template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> 125 struct tree_node 126 : public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type 127 { 128 public: 129 typedef typename intrusive_tree_hook 130 <VoidPointer, tree_type_value, OptimizeSize>::type hook_type; 131 typedef T value_type; 132 typedef typename tree_internal_data_type<T>::type internal_type; 133 134 typedef tree_node< T, VoidPointer 135 , tree_type_value, OptimizeSize> node_t; 136 137 typedef typename boost::container::dtl::aligned_storage 138 <sizeof(T), boost::container::dtl::alignment_of<T>::value>::type storage_t; 139 storage_t m_storage; 140 141 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) 142 #pragma GCC diagnostic push 143 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 144 #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING 145 # endif 146 get_databoost::container::dtl::tree_node147 BOOST_CONTAINER_FORCEINLINE T &get_data() 148 { return *reinterpret_cast<T*>(this->m_storage.data); } 149 get_databoost::container::dtl::tree_node150 BOOST_CONTAINER_FORCEINLINE const T &get_data() const 151 { return *reinterpret_cast<const T*>(this->m_storage.data); } 152 get_data_ptrboost::container::dtl::tree_node153 BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() 154 { return reinterpret_cast<T*>(this->m_storage.data); } 155 get_data_ptrboost::container::dtl::tree_node156 BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const 157 { return reinterpret_cast<T*>(this->m_storage.data); } 158 get_real_databoost::container::dtl::tree_node159 BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() 160 { return *reinterpret_cast<internal_type*>(this->m_storage.data); } 161 get_real_databoost::container::dtl::tree_node162 BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const 163 { return *reinterpret_cast<const internal_type*>(this->m_storage.data); } 164 get_real_data_ptrboost::container::dtl::tree_node165 BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() 166 { return reinterpret_cast<internal_type*>(this->m_storage.data); } 167 get_real_data_ptrboost::container::dtl::tree_node168 BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const 169 { return reinterpret_cast<internal_type*>(this->m_storage.data); } 170 ~tree_nodeboost::container::dtl::tree_node171 BOOST_CONTAINER_FORCEINLINE ~tree_node() 172 { reinterpret_cast<internal_type*>(this->m_storage.data)->~internal_type(); } 173 174 #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) 175 #pragma GCC diagnostic pop 176 #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING 177 # endif 178 destroy_headerboost::container::dtl::tree_node179 BOOST_CONTAINER_FORCEINLINE void destroy_header() 180 { static_cast<hook_type*>(this)->~hook_type(); } 181 182 template<class T1, class T2> do_assignboost::container::dtl::tree_node183 BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair<const T1, T2> &p) 184 { 185 const_cast<T1&>(this->get_real_data().first) = p.first; 186 this->get_real_data().second = p.second; 187 } 188 189 template<class T1, class T2> do_assignboost::container::dtl::tree_node190 BOOST_CONTAINER_FORCEINLINE void do_assign(const pair<const T1, T2> &p) 191 { 192 const_cast<T1&>(this->get_real_data().first) = p.first; 193 this->get_real_data().second = p.second; 194 } 195 196 template<class V> do_assignboost::container::dtl::tree_node197 BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v) 198 { this->get_real_data() = v; } 199 200 template<class T1, class T2> do_move_assignboost::container::dtl::tree_node201 BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair<const T1, T2> &p) 202 { 203 const_cast<T1&>(this->get_real_data().first) = ::boost::move(p.first); 204 this->get_real_data().second = ::boost::move(p.second); 205 } 206 207 template<class T1, class T2> do_move_assignboost::container::dtl::tree_node208 BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair<const T1, T2> &p) 209 { 210 const_cast<T1&>(this->get_real_data().first) = ::boost::move(p.first); 211 this->get_real_data().second = ::boost::move(p.second); 212 } 213 214 template<class V> do_move_assignboost::container::dtl::tree_node215 BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v) 216 { this->get_real_data() = ::boost::move(v); } 217 }; 218 219 template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> 220 struct iiterator_node_value_type< tree_node<T, VoidPointer, tree_type_value, OptimizeSize> > { 221 typedef T type; 222 }; 223 224 template<class Node, class Icont> 225 class insert_equal_end_hint_functor 226 { 227 Icont &icont_; 228 229 public: insert_equal_end_hint_functor(Icont & icont)230 BOOST_CONTAINER_FORCEINLINE insert_equal_end_hint_functor(Icont &icont) 231 : icont_(icont) 232 {} 233 operator ()(Node & n)234 BOOST_CONTAINER_FORCEINLINE void operator()(Node &n) 235 { this->icont_.insert_equal(this->icont_.cend(), n); } 236 }; 237 238 template<class Node, class Icont> 239 class push_back_functor 240 { 241 Icont &icont_; 242 243 public: push_back_functor(Icont & icont)244 BOOST_CONTAINER_FORCEINLINE push_back_functor(Icont &icont) 245 : icont_(icont) 246 {} 247 operator ()(Node & n)248 BOOST_CONTAINER_FORCEINLINE void operator()(Node &n) 249 { this->icont_.push_back(n); } 250 }; 251 252 }//namespace dtl { 253 254 namespace dtl { 255 256 template< class NodeType, class NodeCompareType 257 , class SizeType, class HookType 258 , boost::container::tree_type_enum tree_type_value> 259 struct intrusive_tree_dispatch; 260 261 template<class NodeType, class NodeCompareType, class SizeType, class HookType> 262 struct intrusive_tree_dispatch 263 <NodeType, NodeCompareType, SizeType, HookType, boost::container::red_black_tree> 264 { 265 typedef typename dtl::bi::make_rbtree 266 <NodeType 267 ,dtl::bi::compare<NodeCompareType> 268 ,dtl::bi::base_hook<HookType> 269 ,dtl::bi::constant_time_size<true> 270 ,dtl::bi::size_type<SizeType> 271 >::type type; 272 }; 273 274 template<class NodeType, class NodeCompareType, class SizeType, class HookType> 275 struct intrusive_tree_dispatch 276 <NodeType, NodeCompareType, SizeType, HookType, boost::container::avl_tree> 277 { 278 typedef typename dtl::bi::make_avltree 279 <NodeType 280 ,dtl::bi::compare<NodeCompareType> 281 ,dtl::bi::base_hook<HookType> 282 ,dtl::bi::constant_time_size<true> 283 ,dtl::bi::size_type<SizeType> 284 >::type type; 285 }; 286 287 template<class NodeType, class NodeCompareType, class SizeType, class HookType> 288 struct intrusive_tree_dispatch 289 <NodeType, NodeCompareType, SizeType, HookType, boost::container::scapegoat_tree> 290 { 291 typedef typename dtl::bi::make_sgtree 292 <NodeType 293 ,dtl::bi::compare<NodeCompareType> 294 ,dtl::bi::base_hook<HookType> 295 ,dtl::bi::floating_point<true> 296 ,dtl::bi::size_type<SizeType> 297 >::type type; 298 }; 299 300 template<class NodeType, class NodeCompareType, class SizeType, class HookType> 301 struct intrusive_tree_dispatch 302 <NodeType, NodeCompareType, SizeType, HookType, boost::container::splay_tree> 303 { 304 typedef typename dtl::bi::make_splaytree 305 <NodeType 306 ,dtl::bi::compare<NodeCompareType> 307 ,dtl::bi::base_hook<HookType> 308 ,dtl::bi::constant_time_size<true> 309 ,dtl::bi::size_type<SizeType> 310 >::type type; 311 }; 312 313 template<class Allocator, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> 314 struct intrusive_tree_type 315 { 316 private: 317 typedef typename boost::container:: 318 allocator_traits<Allocator>::value_type value_type; 319 typedef typename boost::container:: 320 allocator_traits<Allocator>::void_pointer void_pointer; 321 typedef typename boost::container:: 322 allocator_traits<Allocator>::size_type size_type; 323 typedef typename dtl::tree_node 324 < value_type, void_pointer 325 , tree_type_value, OptimizeSize> node_t; 326 typedef value_to_node_compare 327 <node_t, ValueCompare> node_compare_type; 328 //Deducing the hook type from node_t (e.g. node_t::hook_type) would 329 //provoke an early instantiation of node_t that could ruin recursive 330 //tree definitions, so retype the complete type to avoid any problem. 331 typedef typename intrusive_tree_hook 332 <void_pointer, tree_type_value 333 , OptimizeSize>::type hook_type; 334 public: 335 typedef typename intrusive_tree_dispatch 336 < node_t, node_compare_type 337 , size_type, hook_type 338 , tree_type_value>::type type; 339 }; 340 341 //Trait to detect manually rebalanceable tree types 342 template<boost::container::tree_type_enum tree_type_value> 343 struct is_manually_balanceable 344 { static const bool value = true; }; 345 346 template<> struct is_manually_balanceable<red_black_tree> 347 { static const bool value = false; }; 348 349 template<> struct is_manually_balanceable<avl_tree> 350 { static const bool value = false; }; 351 352 //Proxy traits to implement different operations depending on the 353 //is_manually_balanceable<>::value 354 template< boost::container::tree_type_enum tree_type_value 355 , bool IsManuallyRebalanceable = is_manually_balanceable<tree_type_value>::value> 356 struct intrusive_tree_proxy 357 { 358 template<class Icont> rebalanceboost::container::dtl::intrusive_tree_proxy359 BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &) {} 360 }; 361 362 template<boost::container::tree_type_enum tree_type_value> 363 struct intrusive_tree_proxy<tree_type_value, true> 364 { 365 template<class Icont> rebalanceboost::container::dtl::intrusive_tree_proxy366 BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &c) 367 { c.rebalance(); } 368 }; 369 370 } //namespace dtl { 371 372 namespace dtl { 373 374 //This functor will be used with Intrusive clone functions to obtain 375 //already allocated nodes from a intrusive container instead of 376 //allocating new ones. When the intrusive container runs out of nodes 377 //the node holder is used instead. 378 template<class AllocHolder, bool DoMove> 379 class RecyclingCloner 380 { 381 typedef typename AllocHolder::intrusive_container intrusive_container; 382 typedef typename AllocHolder::Node node_t; 383 typedef typename AllocHolder::NodePtr node_ptr_type; 384 385 public: RecyclingCloner(AllocHolder & holder,intrusive_container & itree)386 RecyclingCloner(AllocHolder &holder, intrusive_container &itree) 387 : m_holder(holder), m_icont(itree) 388 {} 389 do_assign(node_ptr_type & p,const node_t & other,bool_<true>)390 BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>) 391 { p->do_move_assign(const_cast<node_t &>(other).get_real_data()); } 392 do_assign(node_ptr_type & p,const node_t & other,bool_<false>)393 BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>) 394 { p->do_assign(other.get_real_data()); } 395 operator ()(const node_t & other) const396 node_ptr_type operator()(const node_t &other) const 397 { 398 if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){ 399 //First recycle a node (this can't throw) 400 BOOST_TRY{ 401 //This can throw 402 this->do_assign(p, other, bool_<DoMove>()); 403 return p; 404 } 405 BOOST_CATCH(...){ 406 //If there is an exception destroy the whole source 407 m_holder.destroy_node(p); 408 while((p = m_icont.unlink_leftmost_without_rebalance())){ 409 m_holder.destroy_node(p); 410 } 411 BOOST_RETHROW 412 } 413 BOOST_CATCH_END 414 } 415 else{ 416 return m_holder.create_node(other.get_real_data()); 417 } 418 } 419 420 AllocHolder &m_holder; 421 intrusive_container &m_icont; 422 }; 423 424 425 template<class KeyCompare, class KeyOfValue> 426 struct key_node_compare 427 : public boost::intrusive::detail::ebo_functor_holder<KeyCompare> 428 { key_node_compareboost::container::dtl::key_node_compare429 BOOST_CONTAINER_FORCEINLINE explicit key_node_compare(const KeyCompare &comp) 430 : base_t(comp) 431 {} 432 433 typedef boost::intrusive::detail::ebo_functor_holder<KeyCompare> base_t; 434 typedef KeyCompare key_compare; 435 typedef KeyOfValue key_of_value; 436 typedef typename KeyOfValue::type key_type; 437 438 439 template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> 440 BOOST_CONTAINER_FORCEINLINE static const key_type & key_fromboost::container::dtl::key_node_compare441 key_from(const tree_node<T, VoidPointer, tree_type_value, OptimizeSize> &n) 442 { 443 return key_of_value()(n.get_data()); 444 } 445 446 template <class T> 447 BOOST_CONTAINER_FORCEINLINE static const T & key_fromboost::container::dtl::key_node_compare448 key_from(const T &t) 449 { 450 return t; 451 } 452 key_compboost::container::dtl::key_node_compare453 BOOST_CONTAINER_FORCEINLINE const key_compare &key_comp() const 454 { return static_cast<const key_compare &>(*this); } 455 key_compboost::container::dtl::key_node_compare456 BOOST_CONTAINER_FORCEINLINE key_compare &key_comp() 457 { return static_cast<key_compare &>(*this); } 458 operator ()boost::container::dtl::key_node_compare459 BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const 460 { return this->key_comp()(key1, key2); } 461 462 template<class U> operator ()boost::container::dtl::key_node_compare463 BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const U &nonkey2) const 464 { return this->key_comp()(key1, this->key_from(nonkey2)); } 465 466 template<class U> operator ()boost::container::dtl::key_node_compare467 BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const 468 { return this->key_comp()(this->key_from(nonkey1), key2); } 469 470 template<class U, class V> operator ()boost::container::dtl::key_node_compare471 BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const V &nonkey2) const 472 { return this->key_comp()(this->key_from(nonkey1), this->key_from(nonkey2)); } 473 }; 474 475 template<class Options> 476 struct get_tree_opt 477 { 478 typedef Options type; 479 }; 480 481 template<> 482 struct get_tree_opt<void> 483 { 484 typedef tree_assoc_defaults type; 485 }; 486 487 template<class, class KeyOfValue> 488 struct real_key_of_value 489 { 490 typedef KeyOfValue type; 491 }; 492 493 template<class T> 494 struct real_key_of_value<T, void> 495 { 496 typedef dtl::identity<T> type; 497 }; 498 499 template<class T1, class T2> 500 struct real_key_of_value<std::pair<T1, T2>, int> 501 { 502 typedef dtl::select1st<T1> type; 503 }; 504 505 template<class T1, class T2> 506 struct real_key_of_value<boost::container::pair<T1, T2>, int> 507 { 508 typedef dtl::select1st<T1> type; 509 }; 510 511 template <class T, class KeyOfValue, class Compare, class Allocator, class Options> 512 class tree 513 : public dtl::node_alloc_holder 514 < typename real_allocator<T, Allocator>::type 515 , typename dtl::intrusive_tree_type 516 < typename real_allocator<T, Allocator>::type 517 , tree_value_compare 518 <typename allocator_traits<typename real_allocator<T, Allocator>::type>::pointer, Compare, typename real_key_of_value<T, KeyOfValue>::type> 519 , get_tree_opt<Options>::type::tree_type 520 , get_tree_opt<Options>::type::optimize_size 521 >::type 522 > 523 { 524 typedef tree < T, KeyOfValue 525 , Compare, Allocator, Options> ThisType; 526 public: 527 typedef typename real_allocator<T, Allocator>::type allocator_type; 528 529 private: 530 typedef allocator_traits<allocator_type> allocator_traits_t; 531 typedef typename real_key_of_value<T, KeyOfValue>::type key_of_value_t; 532 typedef tree_value_compare 533 < typename allocator_traits_t::pointer 534 , Compare 535 , key_of_value_t> ValComp; 536 typedef typename get_tree_opt<Options>::type options_type; 537 typedef typename dtl::intrusive_tree_type 538 < allocator_type, ValComp 539 , options_type::tree_type 540 , options_type::optimize_size 541 >::type Icont; 542 typedef dtl::node_alloc_holder 543 <allocator_type, Icont> AllocHolder; 544 typedef typename AllocHolder::NodePtr NodePtr; 545 546 typedef typename AllocHolder::NodeAlloc NodeAlloc; 547 typedef boost::container:: 548 allocator_traits<NodeAlloc> allocator_traits_type; 549 typedef typename AllocHolder::ValAlloc ValAlloc; 550 typedef typename AllocHolder::Node Node; 551 typedef typename Icont::iterator iiterator; 552 typedef typename Icont::const_iterator iconst_iterator; 553 typedef dtl::allocator_destroyer<NodeAlloc> Destroyer; 554 typedef typename AllocHolder::alloc_version alloc_version; 555 typedef intrusive_tree_proxy<options_type::tree_type> intrusive_tree_proxy_t; 556 557 BOOST_COPYABLE_AND_MOVABLE(tree) 558 559 public: 560 561 typedef typename key_of_value_t::type key_type; 562 typedef T value_type; 563 typedef Compare key_compare; 564 typedef ValComp value_compare; 565 typedef typename boost::container:: 566 allocator_traits<allocator_type>::pointer pointer; 567 typedef typename boost::container:: 568 allocator_traits<allocator_type>::const_pointer const_pointer; 569 typedef typename boost::container:: 570 allocator_traits<allocator_type>::reference reference; 571 typedef typename boost::container:: 572 allocator_traits<allocator_type>::const_reference const_reference; 573 typedef typename boost::container:: 574 allocator_traits<allocator_type>::size_type size_type; 575 typedef typename boost::container:: 576 allocator_traits<allocator_type>::difference_type difference_type; 577 typedef dtl::iterator_from_iiterator 578 <iiterator, false> iterator; 579 typedef dtl::iterator_from_iiterator 580 <iiterator, true > const_iterator; 581 typedef boost::container::reverse_iterator 582 <iterator> reverse_iterator; 583 typedef boost::container::reverse_iterator 584 <const_iterator> const_reverse_iterator; 585 typedef node_handle 586 < NodeAlloc, void> node_type; 587 typedef insert_return_type_base 588 <iterator, node_type> insert_return_type; 589 590 typedef NodeAlloc stored_allocator_type; 591 592 private: 593 594 typedef key_node_compare<key_compare, key_of_value_t> KeyNodeCompare; 595 596 public: 597 tree()598 BOOST_CONTAINER_FORCEINLINE tree() 599 : AllocHolder() 600 {} 601 tree(const key_compare & comp)602 BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp) 603 : AllocHolder(ValComp(comp)) 604 {} 605 tree(const key_compare & comp,const allocator_type & a)606 BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a) 607 : AllocHolder(ValComp(comp), a) 608 {} 609 tree(const allocator_type & a)610 BOOST_CONTAINER_FORCEINLINE explicit tree(const allocator_type& a) 611 : AllocHolder(a) 612 {} 613 614 template <class InputIterator> tree(bool unique_insertion,InputIterator first,InputIterator last)615 tree(bool unique_insertion, InputIterator first, InputIterator last) 616 : AllocHolder(value_compare(key_compare())) 617 { 618 this->tree_construct(unique_insertion, first, last); 619 //AllocHolder clears in case of exception 620 } 621 622 template <class InputIterator> tree(bool unique_insertion,InputIterator first,InputIterator last,const key_compare & comp)623 tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp) 624 : AllocHolder(value_compare(comp)) 625 { 626 this->tree_construct(unique_insertion, first, last); 627 //AllocHolder clears in case of exception 628 } 629 630 template <class InputIterator> tree(bool unique_insertion,InputIterator first,InputIterator last,const key_compare & comp,const allocator_type & a)631 tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a) 632 : AllocHolder(value_compare(comp), a) 633 { 634 this->tree_construct(unique_insertion, first, last); 635 //AllocHolder clears in case of exception 636 } 637 638 //construct with ordered range 639 template <class InputIterator> tree(ordered_range_t,InputIterator first,InputIterator last)640 tree( ordered_range_t, InputIterator first, InputIterator last) 641 : AllocHolder(value_compare(key_compare())) 642 { 643 this->tree_construct(ordered_range_t(), first, last); 644 } 645 646 template <class InputIterator> tree(ordered_range_t,InputIterator first,InputIterator last,const key_compare & comp)647 tree( ordered_range_t, InputIterator first, InputIterator last, const key_compare& comp) 648 : AllocHolder(value_compare(comp)) 649 { 650 this->tree_construct(ordered_range_t(), first, last); 651 } 652 653 template <class InputIterator> tree(ordered_range_t,InputIterator first,InputIterator last,const key_compare & comp,const allocator_type & a)654 tree( ordered_range_t, InputIterator first, InputIterator last 655 , const key_compare& comp, const allocator_type& a) 656 : AllocHolder(value_compare(comp), a) 657 { 658 this->tree_construct(ordered_range_t(), first, last); 659 } 660 661 private: 662 663 template <class InputIterator> tree_construct(bool unique_insertion,InputIterator first,InputIterator last)664 void tree_construct(bool unique_insertion, InputIterator first, InputIterator last) 665 { 666 //Use cend() as hint to achieve linear time for 667 //ordered ranges as required by the standard 668 //for the constructor 669 if(unique_insertion){ 670 const const_iterator end_it(this->cend()); 671 for ( ; first != last; ++first){ 672 this->insert_unique_convertible(end_it, *first); 673 } 674 } 675 else{ 676 this->tree_construct_non_unique(first, last); 677 } 678 } 679 680 template <class InputIterator> tree_construct_non_unique(InputIterator first,InputIterator last,typename dtl::enable_if_or<void,dtl::is_same<alloc_version,version_1>,dtl::is_input_iterator<InputIterator>>::type * =0)681 void tree_construct_non_unique(InputIterator first, InputIterator last 682 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 683 , typename dtl::enable_if_or 684 < void 685 , dtl::is_same<alloc_version, version_1> 686 , dtl::is_input_iterator<InputIterator> 687 >::type * = 0 688 #endif 689 ) 690 { 691 //Use cend() as hint to achieve linear time for 692 //ordered ranges as required by the standard 693 //for the constructor 694 const const_iterator end_it(this->cend()); 695 for ( ; first != last; ++first){ 696 this->insert_equal_convertible(end_it, *first); 697 } 698 } 699 700 template <class InputIterator> tree_construct_non_unique(InputIterator first,InputIterator last,typename dtl::disable_if_or<void,dtl::is_same<alloc_version,version_1>,dtl::is_input_iterator<InputIterator>>::type * =0)701 void tree_construct_non_unique(InputIterator first, InputIterator last 702 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 703 , typename dtl::disable_if_or 704 < void 705 , dtl::is_same<alloc_version, version_1> 706 , dtl::is_input_iterator<InputIterator> 707 >::type * = 0 708 #endif 709 ) 710 { 711 //Optimized allocation and construction 712 this->allocate_many_and_construct 713 ( first, boost::container::iterator_distance(first, last) 714 , insert_equal_end_hint_functor<Node, Icont>(this->icont())); 715 } 716 717 template <class InputIterator> tree_construct(ordered_range_t,InputIterator first,InputIterator last,typename dtl::disable_if_or<void,dtl::is_same<alloc_version,version_1>,dtl::is_input_iterator<InputIterator>>::type * =0)718 void tree_construct( ordered_range_t, InputIterator first, InputIterator last 719 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 720 , typename dtl::disable_if_or 721 < void 722 , dtl::is_same<alloc_version, version_1> 723 , dtl::is_input_iterator<InputIterator> 724 >::type * = 0 725 #endif 726 ) 727 { 728 //Optimized allocation and construction 729 this->allocate_many_and_construct 730 ( first, boost::container::iterator_distance(first, last) 731 , dtl::push_back_functor<Node, Icont>(this->icont())); 732 //AllocHolder clears in case of exception 733 } 734 735 template <class InputIterator> tree_construct(ordered_range_t,InputIterator first,InputIterator last,typename dtl::enable_if_or<void,dtl::is_same<alloc_version,version_1>,dtl::is_input_iterator<InputIterator>>::type * =0)736 void tree_construct( ordered_range_t, InputIterator first, InputIterator last 737 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 738 , typename dtl::enable_if_or 739 < void 740 , dtl::is_same<alloc_version, version_1> 741 , dtl::is_input_iterator<InputIterator> 742 >::type * = 0 743 #endif 744 ) 745 { 746 for ( ; first != last; ++first){ 747 this->push_back_impl(*first); 748 } 749 } 750 751 public: 752 tree(const tree & x)753 BOOST_CONTAINER_FORCEINLINE tree(const tree& x) 754 : AllocHolder(x, x.value_comp()) 755 { 756 this->icont().clone_from 757 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 758 } 759 tree(BOOST_RV_REF (tree)x)760 BOOST_CONTAINER_FORCEINLINE tree(BOOST_RV_REF(tree) x) 761 BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value) 762 : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp()) 763 {} 764 tree(const tree & x,const allocator_type & a)765 BOOST_CONTAINER_FORCEINLINE tree(const tree& x, const allocator_type &a) 766 : AllocHolder(x.value_comp(), a) 767 { 768 this->icont().clone_from 769 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 770 //AllocHolder clears in case of exception 771 } 772 tree(BOOST_RV_REF (tree)x,const allocator_type & a)773 tree(BOOST_RV_REF(tree) x, const allocator_type &a) 774 : AllocHolder(x.value_comp(), a) 775 { 776 if(this->node_alloc() == x.node_alloc()){ 777 this->icont().swap(x.icont()); 778 } 779 else{ 780 this->icont().clone_from 781 (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc())); 782 } 783 //AllocHolder clears in case of exception 784 } 785 ~tree()786 BOOST_CONTAINER_FORCEINLINE ~tree() 787 {} //AllocHolder clears the tree 788 operator =(BOOST_COPY_ASSIGN_REF (tree)x)789 tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x) 790 { 791 if (BOOST_LIKELY(this != &x)) { 792 NodeAlloc &this_alloc = this->get_stored_allocator(); 793 const NodeAlloc &x_alloc = x.get_stored_allocator(); 794 dtl::bool_<allocator_traits<NodeAlloc>:: 795 propagate_on_container_copy_assignment::value> flag; 796 if(flag && this_alloc != x_alloc){ 797 this->clear(); 798 } 799 this->AllocHolder::copy_assign_alloc(x); 800 //Transfer all the nodes to a temporary tree 801 //If anything goes wrong, all the nodes will be destroyed 802 //automatically 803 Icont other_tree(::boost::move(this->icont())); 804 805 //Now recreate the source tree reusing nodes stored by other_tree 806 this->icont().clone_from 807 (x.icont() 808 , RecyclingCloner<AllocHolder, false>(*this, other_tree) 809 , Destroyer(this->node_alloc())); 810 811 //If there are remaining nodes, destroy them 812 NodePtr p; 813 while((p = other_tree.unlink_leftmost_without_rebalance())){ 814 AllocHolder::destroy_node(p); 815 } 816 } 817 return *this; 818 } 819 operator =(BOOST_RV_REF (tree)x)820 tree& operator=(BOOST_RV_REF(tree) x) 821 BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || 822 allocator_traits_type::is_always_equal::value) && 823 boost::container::dtl::is_nothrow_move_assignable<Compare>::value) 824 { 825 if (BOOST_LIKELY(this != &x)) { 826 NodeAlloc &this_alloc = this->node_alloc(); 827 NodeAlloc &x_alloc = x.node_alloc(); 828 const bool propagate_alloc = allocator_traits<NodeAlloc>:: 829 propagate_on_container_move_assignment::value; 830 const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; 831 //Resources can be transferred if both allocators are 832 //going to be equal after this function (either propagated or already equal) 833 if(propagate_alloc || allocators_equal){ 834 //Destroy 835 this->clear(); 836 //Move allocator if needed 837 this->AllocHolder::move_assign_alloc(x); 838 //Obtain resources 839 this->icont() = boost::move(x.icont()); 840 } 841 //Else do a one by one move 842 else{ 843 //Transfer all the nodes to a temporary tree 844 //If anything goes wrong, all the nodes will be destroyed 845 //automatically 846 Icont other_tree(::boost::move(this->icont())); 847 848 //Now recreate the source tree reusing nodes stored by other_tree 849 this->icont().clone_from 850 (::boost::move(x.icont()) 851 , RecyclingCloner<AllocHolder, true>(*this, other_tree) 852 , Destroyer(this->node_alloc())); 853 854 //If there are remaining nodes, destroy them 855 NodePtr p; 856 while((p = other_tree.unlink_leftmost_without_rebalance())){ 857 AllocHolder::destroy_node(p); 858 } 859 } 860 } 861 return *this; 862 } 863 864 public: 865 // accessors: value_comp() const866 BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const 867 { return this->icont().value_comp().predicate(); } 868 key_comp() const869 BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const 870 { return this->icont().value_comp().predicate().key_comp(); } 871 get_allocator() const872 BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const 873 { return allocator_type(this->node_alloc()); } 874 get_stored_allocator() const875 BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const 876 { return this->node_alloc(); } 877 get_stored_allocator()878 BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() 879 { return this->node_alloc(); } 880 begin()881 BOOST_CONTAINER_FORCEINLINE iterator begin() 882 { return iterator(this->icont().begin()); } 883 begin() const884 BOOST_CONTAINER_FORCEINLINE const_iterator begin() const 885 { return this->cbegin(); } 886 end()887 BOOST_CONTAINER_FORCEINLINE iterator end() 888 { return iterator(this->icont().end()); } 889 end() const890 BOOST_CONTAINER_FORCEINLINE const_iterator end() const 891 { return this->cend(); } 892 rbegin()893 BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() 894 { return reverse_iterator(end()); } 895 rbegin() const896 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const 897 { return this->crbegin(); } 898 rend()899 BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() 900 { return reverse_iterator(begin()); } 901 rend() const902 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const 903 { return this->crend(); } 904 905 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. 906 //! 907 //! <b>Throws</b>: Nothing. 908 //! 909 //! <b>Complexity</b>: Constant. cbegin() const910 BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const 911 { return const_iterator(this->non_const_icont().begin()); } 912 913 //! <b>Effects</b>: Returns a const_iterator to the end of the container. 914 //! 915 //! <b>Throws</b>: Nothing. 916 //! 917 //! <b>Complexity</b>: Constant. cend() const918 BOOST_CONTAINER_FORCEINLINE const_iterator cend() const 919 { return const_iterator(this->non_const_icont().end()); } 920 921 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 922 //! of the reversed container. 923 //! 924 //! <b>Throws</b>: Nothing. 925 //! 926 //! <b>Complexity</b>: Constant. crbegin() const927 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const 928 { return const_reverse_iterator(cend()); } 929 930 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end 931 //! of the reversed container. 932 //! 933 //! <b>Throws</b>: Nothing. 934 //! 935 //! <b>Complexity</b>: Constant. crend() const936 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const 937 { return const_reverse_iterator(cbegin()); } 938 empty() const939 BOOST_CONTAINER_FORCEINLINE bool empty() const 940 { return !this->size(); } 941 size() const942 BOOST_CONTAINER_FORCEINLINE size_type size() const 943 { return this->icont().size(); } 944 max_size() const945 BOOST_CONTAINER_FORCEINLINE size_type max_size() const 946 { return AllocHolder::max_size(); } 947 swap(ThisType & x)948 BOOST_CONTAINER_FORCEINLINE void swap(ThisType& x) 949 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value 950 && boost::container::dtl::is_nothrow_swappable<Compare>::value ) 951 { AllocHolder::swap(x); } 952 953 public: 954 955 typedef typename Icont::insert_commit_data insert_commit_data; 956 957 // insert/erase insert_unique_check(const key_type & key,insert_commit_data & data)958 std::pair<iterator,bool> insert_unique_check 959 (const key_type& key, insert_commit_data &data) 960 { 961 std::pair<iiterator, bool> ret = 962 this->icont().insert_unique_check(key, KeyNodeCompare(key_comp()), data); 963 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 964 } 965 insert_unique_check(const_iterator hint,const key_type & key,insert_commit_data & data)966 std::pair<iterator,bool> insert_unique_check 967 (const_iterator hint, const key_type& key, insert_commit_data &data) 968 { 969 BOOST_ASSERT((priv_is_linked)(hint)); 970 std::pair<iiterator, bool> ret = 971 this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(key_comp()), data); 972 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 973 } 974 975 template<class MovableConvertible> insert_unique_commit(BOOST_FWD_REF (MovableConvertible)v,insert_commit_data & data)976 iterator insert_unique_commit 977 (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data) 978 { 979 NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(v)); 980 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 981 iterator ret(this->icont().insert_unique_commit(*tmp, data)); 982 destroy_deallocator.release(); 983 return ret; 984 } 985 986 template<class MovableConvertible> insert_unique(BOOST_FWD_REF (MovableConvertible)v)987 std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v) 988 { 989 insert_commit_data data; 990 std::pair<iterator,bool> ret = 991 this->insert_unique_check(key_of_value_t()(v), data); 992 if(ret.second){ 993 ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data); 994 } 995 return ret; 996 } 997 998 private: 999 1000 template<class KeyConvertible, class M> priv_insert_or_assign_commit(BOOST_FWD_REF (KeyConvertible)key,BOOST_FWD_REF (M)obj,insert_commit_data & data)1001 iiterator priv_insert_or_assign_commit 1002 (BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data) 1003 { 1004 NodePtr tmp = AllocHolder::create_node(boost::forward<KeyConvertible>(key), boost::forward<M>(obj)); 1005 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1006 iiterator ret(this->icont().insert_unique_commit(*tmp, data)); 1007 destroy_deallocator.release(); 1008 return ret; 1009 } 1010 priv_is_linked(const_iterator const position) const1011 bool priv_is_linked(const_iterator const position) const 1012 { 1013 iiterator const cur(position.get()); 1014 return cur == this->icont().end() || 1015 cur == this->icont().root() || 1016 iiterator(cur).go_parent().go_left() == cur || 1017 iiterator(cur).go_parent().go_right() == cur; 1018 } 1019 1020 template<class MovableConvertible> push_back_impl(BOOST_FWD_REF (MovableConvertible)v)1021 void push_back_impl(BOOST_FWD_REF(MovableConvertible) v) 1022 { 1023 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); 1024 //push_back has no-throw guarantee so avoid any deallocator/destroyer 1025 this->icont().push_back(*tmp); 1026 } 1027 emplace_unique_impl(NodePtr p)1028 std::pair<iterator, bool> emplace_unique_impl(NodePtr p) 1029 { 1030 value_type &v = p->get_data(); 1031 insert_commit_data data; 1032 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc()); 1033 std::pair<iterator,bool> ret = 1034 this->insert_unique_check(key_of_value_t()(v), data); 1035 if(!ret.second){ 1036 return ret; 1037 } 1038 //No throw insertion part, release rollback 1039 destroy_deallocator.release(); 1040 return std::pair<iterator,bool> 1041 ( iterator(this->icont().insert_unique_commit(*p, data)) 1042 , true ); 1043 } 1044 emplace_unique_hint_impl(const_iterator hint,NodePtr p)1045 iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p) 1046 { 1047 BOOST_ASSERT((priv_is_linked)(hint)); 1048 value_type &v = p->get_data(); 1049 insert_commit_data data; 1050 std::pair<iterator,bool> ret = 1051 this->insert_unique_check(hint, key_of_value_t()(v), data); 1052 if(!ret.second){ 1053 Destroyer(this->node_alloc())(p); 1054 return ret.first; 1055 } 1056 return iterator(this->icont().insert_unique_commit(*p, data)); 1057 } 1058 1059 public: 1060 1061 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1062 1063 template <class... Args> emplace_unique(BOOST_FWD_REF (Args)...args)1064 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args) 1065 { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); } 1066 1067 template <class... Args> emplace_hint_unique(const_iterator hint,BOOST_FWD_REF (Args)...args)1068 BOOST_CONTAINER_FORCEINLINE iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args) 1069 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); } 1070 1071 template <class... Args> emplace_equal(BOOST_FWD_REF (Args)...args)1072 iterator emplace_equal(BOOST_FWD_REF(Args)... args) 1073 { 1074 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); 1075 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1076 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1077 destroy_deallocator.release(); 1078 return ret; 1079 } 1080 1081 template <class... Args> emplace_hint_equal(const_iterator hint,BOOST_FWD_REF (Args)...args)1082 iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args) 1083 { 1084 BOOST_ASSERT((priv_is_linked)(hint)); 1085 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); 1086 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1087 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); 1088 destroy_deallocator.release(); 1089 return ret; 1090 } 1091 1092 template <class KeyType, class... Args> try_emplace(const_iterator hint,BOOST_FWD_REF (KeyType)key,BOOST_FWD_REF (Args)...args)1093 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace 1094 (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args) 1095 { 1096 insert_commit_data data; 1097 const key_type & k = key; //Support emulated rvalue references 1098 std::pair<iiterator, bool> ret = 1099 hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data) 1100 : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data); 1101 if(ret.second){ 1102 ret.first = this->icont().insert_unique_commit 1103 (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data); 1104 } 1105 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 1106 } 1107 1108 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1109 1110 #define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \ 1111 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1112 std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\ 1113 { return this->emplace_unique_impl(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ 1114 \ 1115 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1116 iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1117 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ 1118 \ 1119 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1120 iterator emplace_equal(BOOST_MOVE_UREF##N)\ 1121 {\ 1122 NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ 1123 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\ 1124 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\ 1125 destroy_deallocator.release();\ 1126 return ret;\ 1127 }\ 1128 \ 1129 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1130 iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1131 {\ 1132 BOOST_ASSERT((priv_is_linked)(hint));\ 1133 NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ 1134 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\ 1135 iterator ret(this->icont().insert_equal(hint.get(), *tmp));\ 1136 destroy_deallocator.release();\ 1137 return ret;\ 1138 }\ 1139 \ 1140 template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\ 1141 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\ 1142 try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1143 {\ 1144 insert_commit_data data;\ 1145 const key_type & k = key;\ 1146 std::pair<iiterator, bool> ret =\ 1147 hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)\ 1148 : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);\ 1149 if(ret.second){\ 1150 ret.first = this->icont().insert_unique_commit\ 1151 (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\ 1152 }\ 1153 return std::pair<iterator, bool>(iterator(ret.first), ret.second);\ 1154 }\ 1155 // 1156 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE) 1157 #undef BOOST_CONTAINER_TREE_EMPLACE_CODE 1158 1159 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1160 1161 template<class MovableConvertible> insert_unique_convertible(const_iterator hint,BOOST_FWD_REF (MovableConvertible)v)1162 iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) 1163 { 1164 BOOST_ASSERT((priv_is_linked)(hint)); 1165 insert_commit_data data; 1166 std::pair<iterator,bool> ret = 1167 this->insert_unique_check(hint, key_of_value_t()(v), data); 1168 if(!ret.second) 1169 return ret.first; 1170 return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data); 1171 } 1172 1173 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator) 1174 1175 template <class InputIterator> insert_unique(InputIterator first,InputIterator last)1176 void insert_unique(InputIterator first, InputIterator last) 1177 { 1178 for( ; first != last; ++first) 1179 this->insert_unique(*first); 1180 } 1181 insert_equal(const value_type & v)1182 iterator insert_equal(const value_type& v) 1183 { 1184 NodePtr tmp(AllocHolder::create_node(v)); 1185 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1186 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1187 destroy_deallocator.release(); 1188 return ret; 1189 } 1190 1191 template<class MovableConvertible> insert_equal(BOOST_FWD_REF (MovableConvertible)v)1192 iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v) 1193 { 1194 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); 1195 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1196 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1197 destroy_deallocator.release(); 1198 return ret; 1199 } 1200 1201 template<class MovableConvertible> insert_equal_convertible(const_iterator hint,BOOST_FWD_REF (MovableConvertible)v)1202 iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) 1203 { 1204 BOOST_ASSERT((priv_is_linked)(hint)); 1205 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); 1206 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1207 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); 1208 destroy_deallocator.release(); 1209 return ret; 1210 } 1211 1212 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator) 1213 1214 template <class InputIterator> insert_equal(InputIterator first,InputIterator last)1215 void insert_equal(InputIterator first, InputIterator last) 1216 { 1217 for( ; first != last; ++first) 1218 this->insert_equal(*first); 1219 } 1220 1221 template<class KeyType, class M> insert_or_assign(const_iterator hint,BOOST_FWD_REF (KeyType)key,BOOST_FWD_REF (M)obj)1222 std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj) 1223 { 1224 insert_commit_data data; 1225 const key_type & k = key; //Support emulated rvalue references 1226 std::pair<iiterator, bool> ret = 1227 hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data) 1228 : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data); 1229 if(ret.second){ 1230 ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data); 1231 } 1232 else{ 1233 ret.first->get_data().second = boost::forward<M>(obj); 1234 } 1235 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 1236 } 1237 erase(const_iterator position)1238 iterator erase(const_iterator position) 1239 { 1240 BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); 1241 return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); 1242 } 1243 erase(const key_type & k)1244 BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k) 1245 { return AllocHolder::erase_key(k, KeyNodeCompare(key_comp()), alloc_version()); } 1246 erase(const_iterator first,const_iterator last)1247 iterator erase(const_iterator first, const_iterator last) 1248 { 1249 BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first))); 1250 BOOST_ASSERT(first == last || (priv_is_linked)(last)); 1251 return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); 1252 } 1253 extract(const key_type & k)1254 node_type extract(const key_type& k) 1255 { 1256 iterator const it = this->find(k); 1257 if(this->end() != it){ 1258 return this->extract(it); 1259 } 1260 return node_type(); 1261 } 1262 extract(const_iterator position)1263 node_type extract(const_iterator position) 1264 { 1265 BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); 1266 iiterator const iit(position.get()); 1267 this->icont().erase(iit); 1268 return node_type(iit.operator->(), this->node_alloc()); 1269 } 1270 insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1271 insert_return_type insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1272 { 1273 return this->insert_unique_node(this->end(), boost::move(nh)); 1274 } 1275 insert_unique_node(const_iterator hint,BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1276 insert_return_type insert_unique_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1277 { 1278 insert_return_type irt; //inserted == false, node.empty() 1279 if(!nh.empty()){ 1280 insert_commit_data data; 1281 std::pair<iterator,bool> ret = 1282 this->insert_unique_check(hint, key_of_value_t()(nh.value()), data); 1283 if(ret.second){ 1284 irt.inserted = true; 1285 irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data)); 1286 nh.release(); 1287 } 1288 else{ 1289 irt.position = ret.first; 1290 irt.node = boost::move(nh); 1291 } 1292 } 1293 else{ 1294 irt.position = this->end(); 1295 } 1296 return BOOST_MOVE_RET(insert_return_type, irt); 1297 } 1298 insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1299 iterator insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1300 { 1301 if(nh.empty()){ 1302 return this->end(); 1303 } 1304 else{ 1305 NodePtr const p(nh.release()); 1306 return iterator(this->icont().insert_equal(*p)); 1307 } 1308 } 1309 insert_equal_node(const_iterator hint,BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1310 iterator insert_equal_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1311 { 1312 if(nh.empty()){ 1313 return this->end(); 1314 } 1315 else{ 1316 NodePtr const p(nh.release()); 1317 return iterator(this->icont().insert_equal(hint.get(), *p)); 1318 } 1319 } 1320 1321 template<class C2> merge_unique(tree<T,KeyOfValue,C2,Allocator,Options> & source)1322 BOOST_CONTAINER_FORCEINLINE void merge_unique(tree<T, KeyOfValue, C2, Allocator, Options>& source) 1323 { return this->icont().merge_unique(source.icont()); } 1324 1325 template<class C2> merge_equal(tree<T,KeyOfValue,C2,Allocator,Options> & source)1326 BOOST_CONTAINER_FORCEINLINE void merge_equal(tree<T, KeyOfValue, C2, Allocator, Options>& source) 1327 { return this->icont().merge_equal(source.icont()); } clear()1328 BOOST_CONTAINER_FORCEINLINE void clear() 1329 { AllocHolder::clear(alloc_version()); } 1330 1331 // search operations. Const and non-const overloads even if no iterator is returned 1332 // so splay implementations can to their rebalancing when searching in non-const versions find(const key_type & k)1333 BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& k) 1334 { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); } 1335 find(const key_type & k) const1336 BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const 1337 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); } 1338 1339 template <class K> 1340 BOOST_CONTAINER_FORCEINLINE 1341 typename dtl::enable_if_transparent<key_compare, K, iterator>::type find(const K & k)1342 find(const K& k) 1343 { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); } 1344 1345 template <class K> 1346 BOOST_CONTAINER_FORCEINLINE 1347 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type find(const K & k) const1348 find(const K& k) const 1349 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); } 1350 count(const key_type & k) const1351 BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const 1352 { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); } 1353 1354 template <class K> 1355 BOOST_CONTAINER_FORCEINLINE 1356 typename dtl::enable_if_transparent<key_compare, K, size_type>::type count(const K & k) const1357 count(const K& k) const 1358 { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); } 1359 contains(const key_type & x) const1360 BOOST_CONTAINER_FORCEINLINE bool contains(const key_type& x) const 1361 { return this->find(x) != this->cend(); } 1362 1363 template<typename K> 1364 BOOST_CONTAINER_FORCEINLINE 1365 typename dtl::enable_if_transparent<key_compare, K, bool>::type contains(const K & x) const1366 contains(const K& x) const 1367 { return this->find(x) != this->cend(); } 1368 lower_bound(const key_type & k)1369 BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k) 1370 { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1371 lower_bound(const key_type & k) const1372 BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const 1373 { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1374 1375 template <class K> 1376 BOOST_CONTAINER_FORCEINLINE 1377 typename dtl::enable_if_transparent<key_compare, K, iterator>::type lower_bound(const K & k)1378 lower_bound(const K& k) 1379 { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1380 1381 template <class K> 1382 BOOST_CONTAINER_FORCEINLINE 1383 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type lower_bound(const K & k) const1384 lower_bound(const K& k) const 1385 { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1386 upper_bound(const key_type & k)1387 BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k) 1388 { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1389 upper_bound(const key_type & k) const1390 BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const 1391 { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1392 1393 template <class K> 1394 BOOST_CONTAINER_FORCEINLINE 1395 typename dtl::enable_if_transparent<key_compare, K, iterator>::type upper_bound(const K & k)1396 upper_bound(const K& k) 1397 { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1398 1399 template <class K> 1400 BOOST_CONTAINER_FORCEINLINE 1401 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type upper_bound(const K & k) const1402 upper_bound(const K& k) const 1403 { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1404 equal_range(const key_type & k)1405 std::pair<iterator,iterator> equal_range(const key_type& k) 1406 { 1407 std::pair<iiterator, iiterator> ret = 1408 this->icont().equal_range(k, KeyNodeCompare(key_comp())); 1409 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1410 } 1411 equal_range(const key_type & k) const1412 std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const 1413 { 1414 std::pair<iiterator, iiterator> ret = 1415 this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp())); 1416 return std::pair<const_iterator,const_iterator> 1417 (const_iterator(ret.first), const_iterator(ret.second)); 1418 } 1419 1420 template <class K> 1421 BOOST_CONTAINER_FORCEINLINE 1422 typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type equal_range(const K & k)1423 equal_range(const K& k) 1424 { 1425 std::pair<iiterator, iiterator> ret = 1426 this->icont().equal_range(k, KeyNodeCompare(key_comp())); 1427 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1428 } 1429 1430 template <class K> 1431 BOOST_CONTAINER_FORCEINLINE 1432 typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type equal_range(const K & k) const1433 equal_range(const K& k) const 1434 { 1435 std::pair<iiterator, iiterator> ret = 1436 this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp())); 1437 return std::pair<const_iterator,const_iterator> 1438 (const_iterator(ret.first), const_iterator(ret.second)); 1439 } 1440 lower_bound_range(const key_type & k)1441 std::pair<iterator,iterator> lower_bound_range(const key_type& k) 1442 { 1443 std::pair<iiterator, iiterator> ret = 1444 this->icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1445 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1446 } 1447 lower_bound_range(const key_type & k) const1448 std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const 1449 { 1450 std::pair<iiterator, iiterator> ret = 1451 this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1452 return std::pair<const_iterator,const_iterator> 1453 (const_iterator(ret.first), const_iterator(ret.second)); 1454 } 1455 1456 template <class K> 1457 BOOST_CONTAINER_FORCEINLINE 1458 typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type lower_bound_range(const K & k)1459 lower_bound_range(const K& k) 1460 { 1461 std::pair<iiterator, iiterator> ret = 1462 this->icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1463 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1464 } 1465 1466 template <class K> 1467 BOOST_CONTAINER_FORCEINLINE 1468 typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type lower_bound_range(const K & k) const1469 lower_bound_range(const K& k) const 1470 { 1471 std::pair<iiterator, iiterator> ret = 1472 this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1473 return std::pair<const_iterator,const_iterator> 1474 (const_iterator(ret.first), const_iterator(ret.second)); 1475 } 1476 rebalance()1477 BOOST_CONTAINER_FORCEINLINE void rebalance() 1478 { intrusive_tree_proxy_t::rebalance(this->icont()); } 1479 operator ==(const tree & x,const tree & y)1480 BOOST_CONTAINER_FORCEINLINE friend bool operator==(const tree& x, const tree& y) 1481 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } 1482 operator <(const tree & x,const tree & y)1483 BOOST_CONTAINER_FORCEINLINE friend bool operator<(const tree& x, const tree& y) 1484 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } 1485 operator !=(const tree & x,const tree & y)1486 BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const tree& x, const tree& y) 1487 { return !(x == y); } 1488 operator >(const tree & x,const tree & y)1489 BOOST_CONTAINER_FORCEINLINE friend bool operator>(const tree& x, const tree& y) 1490 { return y < x; } 1491 operator <=(const tree & x,const tree & y)1492 BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const tree& x, const tree& y) 1493 { return !(y < x); } 1494 operator >=(const tree & x,const tree & y)1495 BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const tree& x, const tree& y) 1496 { return !(x < y); } 1497 swap(tree & x,tree & y)1498 BOOST_CONTAINER_FORCEINLINE friend void swap(tree& x, tree& y) 1499 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value 1500 && boost::container::dtl::is_nothrow_swappable<Compare>::value ) 1501 { x.swap(y); } 1502 }; 1503 1504 } //namespace dtl { 1505 } //namespace container { 1506 1507 template <class T> 1508 struct has_trivial_destructor_after_move; 1509 1510 //!has_trivial_destructor_after_move<> == true_type 1511 //!specialization for optimizations 1512 template <class T, class KeyOfValue, class Compare, class Allocator, class Options> 1513 struct has_trivial_destructor_after_move 1514 < 1515 ::boost::container::dtl::tree 1516 <T, KeyOfValue, Compare, Allocator, Options> 1517 > 1518 { 1519 typedef typename ::boost::container::dtl::tree<T, KeyOfValue, Compare, Allocator, Options>::allocator_type allocator_type; 1520 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer; 1521 static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value && 1522 ::boost::has_trivial_destructor_after_move<pointer>::value && 1523 ::boost::has_trivial_destructor_after_move<Compare>::value; 1524 }; 1525 1526 } //namespace boost { 1527 1528 #include <boost/container/detail/config_end.hpp> 1529 1530 #endif //BOOST_CONTAINER_TREE_HPP 1531