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,node_t & other,bool_<true>)390 BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, node_t &other, bool_<true>) 391 { p->do_move_assign(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 ()(typename dtl::if_c<DoMove,node_t &,const node_t &>::type other) const396 node_ptr_type operator() 397 (typename dtl::if_c<DoMove, node_t &, const node_t&>::type other) const 398 { 399 if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){ 400 //First recycle a node (this can't throw) 401 BOOST_TRY{ 402 //This can throw 403 this->do_assign(p, other, bool_<DoMove>()); 404 return p; 405 } 406 BOOST_CATCH(...){ 407 //If there is an exception destroy the whole source 408 m_holder.destroy_node(p); 409 while((p = m_icont.unlink_leftmost_without_rebalance())){ 410 m_holder.destroy_node(p); 411 } 412 BOOST_RETHROW 413 } 414 BOOST_CATCH_END 415 } 416 else{ 417 return m_holder.create_node(boost::move(other.get_real_data())); 418 } 419 } 420 421 AllocHolder &m_holder; 422 intrusive_container &m_icont; 423 }; 424 425 426 template<class KeyCompare, class KeyOfValue> 427 struct key_node_compare 428 : public boost::intrusive::detail::ebo_functor_holder<KeyCompare> 429 { key_node_compareboost::container::dtl::key_node_compare430 BOOST_CONTAINER_FORCEINLINE explicit key_node_compare(const KeyCompare &comp) 431 : base_t(comp) 432 {} 433 434 typedef boost::intrusive::detail::ebo_functor_holder<KeyCompare> base_t; 435 typedef KeyCompare key_compare; 436 typedef KeyOfValue key_of_value; 437 typedef typename KeyOfValue::type key_type; 438 439 440 template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> 441 BOOST_CONTAINER_FORCEINLINE static const key_type & key_fromboost::container::dtl::key_node_compare442 key_from(const tree_node<T, VoidPointer, tree_type_value, OptimizeSize> &n) 443 { 444 return key_of_value()(n.get_data()); 445 } 446 447 template <class T> 448 BOOST_CONTAINER_FORCEINLINE static const T & key_fromboost::container::dtl::key_node_compare449 key_from(const T &t) 450 { 451 return t; 452 } 453 key_compboost::container::dtl::key_node_compare454 BOOST_CONTAINER_FORCEINLINE const key_compare &key_comp() const 455 { return static_cast<const key_compare &>(*this); } 456 key_compboost::container::dtl::key_node_compare457 BOOST_CONTAINER_FORCEINLINE key_compare &key_comp() 458 { return static_cast<key_compare &>(*this); } 459 operator ()boost::container::dtl::key_node_compare460 BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const 461 { return this->key_comp()(key1, key2); } 462 463 template<class U> operator ()boost::container::dtl::key_node_compare464 BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const U &nonkey2) const 465 { return this->key_comp()(key1, this->key_from(nonkey2)); } 466 467 template<class U> operator ()boost::container::dtl::key_node_compare468 BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const 469 { return this->key_comp()(this->key_from(nonkey1), key2); } 470 471 template<class U, class V> operator ()boost::container::dtl::key_node_compare472 BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const V &nonkey2) const 473 { return this->key_comp()(this->key_from(nonkey1), this->key_from(nonkey2)); } 474 }; 475 476 template<class Options> 477 struct get_tree_opt 478 { 479 typedef Options type; 480 }; 481 482 template<> 483 struct get_tree_opt<void> 484 { 485 typedef tree_assoc_defaults type; 486 }; 487 488 template<class, class KeyOfValue> 489 struct real_key_of_value 490 { 491 typedef KeyOfValue type; 492 }; 493 494 template<class T> 495 struct real_key_of_value<T, void> 496 { 497 typedef dtl::identity<T> type; 498 }; 499 500 template<class T1, class T2> 501 struct real_key_of_value<std::pair<T1, T2>, int> 502 { 503 typedef dtl::select1st<T1> type; 504 }; 505 506 template<class T1, class T2> 507 struct real_key_of_value<boost::container::pair<T1, T2>, int> 508 { 509 typedef dtl::select1st<T1> type; 510 }; 511 512 template <class T, class KeyOfValue, class Compare, class Allocator, class Options> 513 class tree 514 : public dtl::node_alloc_holder 515 < typename real_allocator<T, Allocator>::type 516 , typename dtl::intrusive_tree_type 517 < typename real_allocator<T, Allocator>::type 518 , tree_value_compare 519 <typename allocator_traits<typename real_allocator<T, Allocator>::type>::pointer, Compare, typename real_key_of_value<T, KeyOfValue>::type> 520 , get_tree_opt<Options>::type::tree_type 521 , get_tree_opt<Options>::type::optimize_size 522 >::type 523 > 524 { 525 typedef tree < T, KeyOfValue 526 , Compare, Allocator, Options> ThisType; 527 public: 528 typedef typename real_allocator<T, Allocator>::type allocator_type; 529 530 private: 531 typedef allocator_traits<allocator_type> allocator_traits_t; 532 typedef typename real_key_of_value<T, KeyOfValue>::type key_of_value_t; 533 typedef tree_value_compare 534 < typename allocator_traits_t::pointer 535 , Compare 536 , key_of_value_t> ValComp; 537 typedef typename get_tree_opt<Options>::type options_type; 538 typedef typename dtl::intrusive_tree_type 539 < allocator_type, ValComp 540 , options_type::tree_type 541 , options_type::optimize_size 542 >::type Icont; 543 typedef dtl::node_alloc_holder 544 <allocator_type, Icont> AllocHolder; 545 typedef typename AllocHolder::NodePtr NodePtr; 546 547 typedef typename AllocHolder::NodeAlloc NodeAlloc; 548 typedef boost::container:: 549 allocator_traits<NodeAlloc> allocator_traits_type; 550 typedef typename AllocHolder::ValAlloc ValAlloc; 551 typedef typename AllocHolder::Node Node; 552 typedef typename Icont::iterator iiterator; 553 typedef typename Icont::const_iterator iconst_iterator; 554 typedef dtl::allocator_destroyer<NodeAlloc> Destroyer; 555 typedef typename AllocHolder::alloc_version alloc_version; 556 typedef intrusive_tree_proxy<options_type::tree_type> intrusive_tree_proxy_t; 557 558 BOOST_COPYABLE_AND_MOVABLE(tree) 559 560 public: 561 562 typedef typename key_of_value_t::type key_type; 563 typedef T value_type; 564 typedef Compare key_compare; 565 typedef ValComp value_compare; 566 typedef typename boost::container:: 567 allocator_traits<allocator_type>::pointer pointer; 568 typedef typename boost::container:: 569 allocator_traits<allocator_type>::const_pointer const_pointer; 570 typedef typename boost::container:: 571 allocator_traits<allocator_type>::reference reference; 572 typedef typename boost::container:: 573 allocator_traits<allocator_type>::const_reference const_reference; 574 typedef typename boost::container:: 575 allocator_traits<allocator_type>::size_type size_type; 576 typedef typename boost::container:: 577 allocator_traits<allocator_type>::difference_type difference_type; 578 typedef dtl::iterator_from_iiterator 579 <iiterator, false> iterator; 580 typedef dtl::iterator_from_iiterator 581 <iiterator, true > const_iterator; 582 typedef boost::container::reverse_iterator 583 <iterator> reverse_iterator; 584 typedef boost::container::reverse_iterator 585 <const_iterator> const_reverse_iterator; 586 typedef node_handle 587 < NodeAlloc, void> node_type; 588 typedef insert_return_type_base 589 <iterator, node_type> insert_return_type; 590 591 typedef NodeAlloc stored_allocator_type; 592 593 private: 594 595 typedef key_node_compare<key_compare, key_of_value_t> KeyNodeCompare; 596 597 public: 598 tree()599 BOOST_CONTAINER_FORCEINLINE tree() 600 : AllocHolder() 601 {} 602 tree(const key_compare & comp)603 BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp) 604 : AllocHolder(ValComp(comp)) 605 {} 606 tree(const key_compare & comp,const allocator_type & a)607 BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a) 608 : AllocHolder(ValComp(comp), a) 609 {} 610 tree(const allocator_type & a)611 BOOST_CONTAINER_FORCEINLINE explicit tree(const allocator_type& a) 612 : AllocHolder(a) 613 {} 614 615 template <class InputIterator> tree(bool unique_insertion,InputIterator first,InputIterator last)616 tree(bool unique_insertion, InputIterator first, InputIterator last) 617 : AllocHolder(value_compare(key_compare())) 618 { 619 this->tree_construct(unique_insertion, first, last); 620 //AllocHolder clears in case of exception 621 } 622 623 template <class InputIterator> tree(bool unique_insertion,InputIterator first,InputIterator last,const key_compare & comp)624 tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp) 625 : AllocHolder(value_compare(comp)) 626 { 627 this->tree_construct(unique_insertion, first, last); 628 //AllocHolder clears in case of exception 629 } 630 631 template <class InputIterator> tree(bool unique_insertion,InputIterator first,InputIterator last,const key_compare & comp,const allocator_type & a)632 tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a) 633 : AllocHolder(value_compare(comp), a) 634 { 635 this->tree_construct(unique_insertion, first, last); 636 //AllocHolder clears in case of exception 637 } 638 639 //construct with ordered range 640 template <class InputIterator> tree(ordered_range_t,InputIterator first,InputIterator last)641 tree( ordered_range_t, InputIterator first, InputIterator last) 642 : AllocHolder(value_compare(key_compare())) 643 { 644 this->tree_construct(ordered_range_t(), first, last); 645 } 646 647 template <class InputIterator> tree(ordered_range_t,InputIterator first,InputIterator last,const key_compare & comp)648 tree( ordered_range_t, InputIterator first, InputIterator last, const key_compare& comp) 649 : AllocHolder(value_compare(comp)) 650 { 651 this->tree_construct(ordered_range_t(), first, last); 652 } 653 654 template <class InputIterator> tree(ordered_range_t,InputIterator first,InputIterator last,const key_compare & comp,const allocator_type & a)655 tree( ordered_range_t, InputIterator first, InputIterator last 656 , const key_compare& comp, const allocator_type& a) 657 : AllocHolder(value_compare(comp), a) 658 { 659 this->tree_construct(ordered_range_t(), first, last); 660 } 661 662 private: 663 664 template <class InputIterator> tree_construct(bool unique_insertion,InputIterator first,InputIterator last)665 void tree_construct(bool unique_insertion, InputIterator first, InputIterator last) 666 { 667 //Use cend() as hint to achieve linear time for 668 //ordered ranges as required by the standard 669 //for the constructor 670 if(unique_insertion){ 671 const const_iterator end_it(this->cend()); 672 for ( ; first != last; ++first){ 673 this->insert_unique_convertible(end_it, *first); 674 } 675 } 676 else{ 677 this->tree_construct_non_unique(first, last); 678 } 679 } 680 681 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)682 void tree_construct_non_unique(InputIterator first, InputIterator last 683 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 684 , typename dtl::enable_if_or 685 < void 686 , dtl::is_same<alloc_version, version_1> 687 , dtl::is_input_iterator<InputIterator> 688 >::type * = 0 689 #endif 690 ) 691 { 692 //Use cend() as hint to achieve linear time for 693 //ordered ranges as required by the standard 694 //for the constructor 695 const const_iterator end_it(this->cend()); 696 for ( ; first != last; ++first){ 697 this->insert_equal_convertible(end_it, *first); 698 } 699 } 700 701 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)702 void tree_construct_non_unique(InputIterator first, InputIterator last 703 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 704 , typename dtl::disable_if_or 705 < void 706 , dtl::is_same<alloc_version, version_1> 707 , dtl::is_input_iterator<InputIterator> 708 >::type * = 0 709 #endif 710 ) 711 { 712 //Optimized allocation and construction 713 this->allocate_many_and_construct 714 ( first, boost::container::iterator_distance(first, last) 715 , insert_equal_end_hint_functor<Node, Icont>(this->icont())); 716 } 717 718 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)719 void tree_construct( ordered_range_t, InputIterator first, InputIterator last 720 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 721 , typename dtl::disable_if_or 722 < void 723 , dtl::is_same<alloc_version, version_1> 724 , dtl::is_input_iterator<InputIterator> 725 >::type * = 0 726 #endif 727 ) 728 { 729 //Optimized allocation and construction 730 this->allocate_many_and_construct 731 ( first, boost::container::iterator_distance(first, last) 732 , dtl::push_back_functor<Node, Icont>(this->icont())); 733 //AllocHolder clears in case of exception 734 } 735 736 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)737 void tree_construct( ordered_range_t, InputIterator first, InputIterator last 738 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 739 , typename dtl::enable_if_or 740 < void 741 , dtl::is_same<alloc_version, version_1> 742 , dtl::is_input_iterator<InputIterator> 743 >::type * = 0 744 #endif 745 ) 746 { 747 for ( ; first != last; ++first){ 748 this->push_back_impl(*first); 749 } 750 } 751 752 public: 753 tree(const tree & x)754 BOOST_CONTAINER_FORCEINLINE tree(const tree& x) 755 : AllocHolder(x, x.value_comp()) 756 { 757 this->icont().clone_from 758 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 759 } 760 tree(BOOST_RV_REF (tree)x)761 BOOST_CONTAINER_FORCEINLINE tree(BOOST_RV_REF(tree) x) 762 BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value) 763 : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp()) 764 {} 765 tree(const tree & x,const allocator_type & a)766 BOOST_CONTAINER_FORCEINLINE tree(const tree& x, const allocator_type &a) 767 : AllocHolder(x.value_comp(), a) 768 { 769 this->icont().clone_from 770 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 771 //AllocHolder clears in case of exception 772 } 773 tree(BOOST_RV_REF (tree)x,const allocator_type & a)774 tree(BOOST_RV_REF(tree) x, const allocator_type &a) 775 : AllocHolder(x.value_comp(), a) 776 { 777 if(this->node_alloc() == x.node_alloc()){ 778 this->icont().swap(x.icont()); 779 } 780 else{ 781 this->icont().clone_from 782 (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc())); 783 } 784 //AllocHolder clears in case of exception 785 } 786 ~tree()787 BOOST_CONTAINER_FORCEINLINE ~tree() 788 {} //AllocHolder clears the tree 789 operator =(BOOST_COPY_ASSIGN_REF (tree)x)790 tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x) 791 { 792 if (BOOST_LIKELY(this != &x)) { 793 NodeAlloc &this_alloc = this->get_stored_allocator(); 794 const NodeAlloc &x_alloc = x.get_stored_allocator(); 795 dtl::bool_<allocator_traits<NodeAlloc>:: 796 propagate_on_container_copy_assignment::value> flag; 797 if(flag && this_alloc != x_alloc){ 798 this->clear(); 799 } 800 this->AllocHolder::copy_assign_alloc(x); 801 //Transfer all the nodes to a temporary tree 802 //If anything goes wrong, all the nodes will be destroyed 803 //automatically 804 Icont other_tree(::boost::move(this->icont())); 805 806 //Now recreate the source tree reusing nodes stored by other_tree 807 this->icont().clone_from 808 (x.icont() 809 , RecyclingCloner<AllocHolder, false>(*this, other_tree) 810 , Destroyer(this->node_alloc())); 811 812 //If there are remaining nodes, destroy them 813 NodePtr p; 814 while((p = other_tree.unlink_leftmost_without_rebalance())){ 815 AllocHolder::destroy_node(p); 816 } 817 } 818 return *this; 819 } 820 operator =(BOOST_RV_REF (tree)x)821 tree& operator=(BOOST_RV_REF(tree) x) 822 BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || 823 allocator_traits_type::is_always_equal::value) && 824 boost::container::dtl::is_nothrow_move_assignable<Compare>::value) 825 { 826 if (BOOST_LIKELY(this != &x)) { 827 NodeAlloc &this_alloc = this->node_alloc(); 828 NodeAlloc &x_alloc = x.node_alloc(); 829 const bool propagate_alloc = allocator_traits<NodeAlloc>:: 830 propagate_on_container_move_assignment::value; 831 const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; 832 //Resources can be transferred if both allocators are 833 //going to be equal after this function (either propagated or already equal) 834 if(propagate_alloc || allocators_equal){ 835 //Destroy 836 this->clear(); 837 //Move allocator if needed 838 this->AllocHolder::move_assign_alloc(x); 839 //Obtain resources 840 this->icont() = boost::move(x.icont()); 841 } 842 //Else do a one by one move 843 else{ 844 //Transfer all the nodes to a temporary tree 845 //If anything goes wrong, all the nodes will be destroyed 846 //automatically 847 Icont other_tree(::boost::move(this->icont())); 848 849 //Now recreate the source tree reusing nodes stored by other_tree 850 this->icont().clone_from 851 (::boost::move(x.icont()) 852 , RecyclingCloner<AllocHolder, true>(*this, other_tree) 853 , Destroyer(this->node_alloc())); 854 855 //If there are remaining nodes, destroy them 856 NodePtr p; 857 while((p = other_tree.unlink_leftmost_without_rebalance())){ 858 AllocHolder::destroy_node(p); 859 } 860 } 861 } 862 return *this; 863 } 864 865 public: 866 // accessors: value_comp() const867 BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const 868 { return this->icont().value_comp().predicate(); } 869 key_comp() const870 BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const 871 { return this->icont().value_comp().predicate().key_comp(); } 872 get_allocator() const873 BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const 874 { return allocator_type(this->node_alloc()); } 875 get_stored_allocator() const876 BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const 877 { return this->node_alloc(); } 878 get_stored_allocator()879 BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() 880 { return this->node_alloc(); } 881 begin()882 BOOST_CONTAINER_FORCEINLINE iterator begin() 883 { return iterator(this->icont().begin()); } 884 begin() const885 BOOST_CONTAINER_FORCEINLINE const_iterator begin() const 886 { return this->cbegin(); } 887 end()888 BOOST_CONTAINER_FORCEINLINE iterator end() 889 { return iterator(this->icont().end()); } 890 end() const891 BOOST_CONTAINER_FORCEINLINE const_iterator end() const 892 { return this->cend(); } 893 rbegin()894 BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() 895 { return reverse_iterator(end()); } 896 rbegin() const897 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const 898 { return this->crbegin(); } 899 rend()900 BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() 901 { return reverse_iterator(begin()); } 902 rend() const903 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const 904 { return this->crend(); } 905 906 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. 907 //! 908 //! <b>Throws</b>: Nothing. 909 //! 910 //! <b>Complexity</b>: Constant. cbegin() const911 BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const 912 { return const_iterator(this->non_const_icont().begin()); } 913 914 //! <b>Effects</b>: Returns a const_iterator to the end of the container. 915 //! 916 //! <b>Throws</b>: Nothing. 917 //! 918 //! <b>Complexity</b>: Constant. cend() const919 BOOST_CONTAINER_FORCEINLINE const_iterator cend() const 920 { return const_iterator(this->non_const_icont().end()); } 921 922 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 923 //! of the reversed container. 924 //! 925 //! <b>Throws</b>: Nothing. 926 //! 927 //! <b>Complexity</b>: Constant. crbegin() const928 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const 929 { return const_reverse_iterator(cend()); } 930 931 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end 932 //! of the reversed container. 933 //! 934 //! <b>Throws</b>: Nothing. 935 //! 936 //! <b>Complexity</b>: Constant. crend() const937 BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const 938 { return const_reverse_iterator(cbegin()); } 939 empty() const940 BOOST_CONTAINER_FORCEINLINE bool empty() const 941 { return !this->size(); } 942 size() const943 BOOST_CONTAINER_FORCEINLINE size_type size() const 944 { return this->icont().size(); } 945 max_size() const946 BOOST_CONTAINER_FORCEINLINE size_type max_size() const 947 { return AllocHolder::max_size(); } 948 swap(ThisType & x)949 BOOST_CONTAINER_FORCEINLINE void swap(ThisType& x) 950 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value 951 && boost::container::dtl::is_nothrow_swappable<Compare>::value ) 952 { AllocHolder::swap(x); } 953 954 public: 955 956 typedef typename Icont::insert_commit_data insert_commit_data; 957 958 // insert/erase insert_unique_check(const key_type & key,insert_commit_data & data)959 std::pair<iterator,bool> insert_unique_check 960 (const key_type& key, insert_commit_data &data) 961 { 962 std::pair<iiterator, bool> ret = 963 this->icont().insert_unique_check(key, KeyNodeCompare(key_comp()), data); 964 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 965 } 966 insert_unique_check(const_iterator hint,const key_type & key,insert_commit_data & data)967 std::pair<iterator,bool> insert_unique_check 968 (const_iterator hint, const key_type& key, insert_commit_data &data) 969 { 970 BOOST_ASSERT((priv_is_linked)(hint)); 971 std::pair<iiterator, bool> ret = 972 this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(key_comp()), data); 973 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 974 } 975 976 template<class MovableConvertible> insert_unique_commit(BOOST_FWD_REF (MovableConvertible)v,insert_commit_data & data)977 iterator insert_unique_commit 978 (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data) 979 { 980 NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(v)); 981 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 982 iterator ret(this->icont().insert_unique_commit(*tmp, data)); 983 destroy_deallocator.release(); 984 return ret; 985 } 986 987 template<class MovableConvertible> insert_unique(BOOST_FWD_REF (MovableConvertible)v)988 std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v) 989 { 990 insert_commit_data data; 991 std::pair<iterator,bool> ret = 992 this->insert_unique_check(key_of_value_t()(v), data); 993 if(ret.second){ 994 ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data); 995 } 996 return ret; 997 } 998 999 private: 1000 1001 template<class KeyConvertible, class M> priv_insert_or_assign_commit(BOOST_FWD_REF (KeyConvertible)key,BOOST_FWD_REF (M)obj,insert_commit_data & data)1002 iiterator priv_insert_or_assign_commit 1003 (BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data) 1004 { 1005 NodePtr tmp = AllocHolder::create_node(boost::forward<KeyConvertible>(key), boost::forward<M>(obj)); 1006 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1007 iiterator ret(this->icont().insert_unique_commit(*tmp, data)); 1008 destroy_deallocator.release(); 1009 return ret; 1010 } 1011 priv_is_linked(const_iterator const position) const1012 bool priv_is_linked(const_iterator const position) const 1013 { 1014 iiterator const cur(position.get()); 1015 return cur == this->icont().end() || 1016 cur == this->icont().root() || 1017 iiterator(cur).go_parent().go_left() == cur || 1018 iiterator(cur).go_parent().go_right() == cur; 1019 } 1020 1021 template<class MovableConvertible> push_back_impl(BOOST_FWD_REF (MovableConvertible)v)1022 void push_back_impl(BOOST_FWD_REF(MovableConvertible) v) 1023 { 1024 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); 1025 //push_back has no-throw guarantee so avoid any deallocator/destroyer 1026 this->icont().push_back(*tmp); 1027 } 1028 emplace_unique_impl(NodePtr p)1029 std::pair<iterator, bool> emplace_unique_impl(NodePtr p) 1030 { 1031 value_type &v = p->get_data(); 1032 insert_commit_data data; 1033 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc()); 1034 std::pair<iterator,bool> ret = 1035 this->insert_unique_check(key_of_value_t()(v), data); 1036 if(!ret.second){ 1037 return ret; 1038 } 1039 //No throw insertion part, release rollback 1040 destroy_deallocator.release(); 1041 return std::pair<iterator,bool> 1042 ( iterator(this->icont().insert_unique_commit(*p, data)) 1043 , true ); 1044 } 1045 emplace_unique_hint_impl(const_iterator hint,NodePtr p)1046 iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p) 1047 { 1048 BOOST_ASSERT((priv_is_linked)(hint)); 1049 value_type &v = p->get_data(); 1050 insert_commit_data data; 1051 std::pair<iterator,bool> ret = 1052 this->insert_unique_check(hint, key_of_value_t()(v), data); 1053 if(!ret.second){ 1054 Destroyer(this->node_alloc())(p); 1055 return ret.first; 1056 } 1057 return iterator(this->icont().insert_unique_commit(*p, data)); 1058 } 1059 1060 public: 1061 1062 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1063 1064 template <class... Args> emplace_unique(BOOST_FWD_REF (Args)...args)1065 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args) 1066 { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); } 1067 1068 template <class... Args> emplace_hint_unique(const_iterator hint,BOOST_FWD_REF (Args)...args)1069 BOOST_CONTAINER_FORCEINLINE iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args) 1070 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); } 1071 1072 template <class... Args> emplace_equal(BOOST_FWD_REF (Args)...args)1073 iterator emplace_equal(BOOST_FWD_REF(Args)... args) 1074 { 1075 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); 1076 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1077 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1078 destroy_deallocator.release(); 1079 return ret; 1080 } 1081 1082 template <class... Args> emplace_hint_equal(const_iterator hint,BOOST_FWD_REF (Args)...args)1083 iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args) 1084 { 1085 BOOST_ASSERT((priv_is_linked)(hint)); 1086 NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); 1087 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1088 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); 1089 destroy_deallocator.release(); 1090 return ret; 1091 } 1092 1093 template <class KeyType, class... Args> try_emplace(const_iterator hint,BOOST_FWD_REF (KeyType)key,BOOST_FWD_REF (Args)...args)1094 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace 1095 (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args) 1096 { 1097 insert_commit_data data; 1098 const key_type & k = key; //Support emulated rvalue references 1099 std::pair<iiterator, bool> ret = 1100 hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data) 1101 : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data); 1102 if(ret.second){ 1103 ret.first = this->icont().insert_unique_commit 1104 (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data); 1105 } 1106 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 1107 } 1108 1109 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1110 1111 #define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \ 1112 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1113 std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\ 1114 { return this->emplace_unique_impl(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ 1115 \ 1116 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1117 iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1118 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ 1119 \ 1120 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1121 iterator emplace_equal(BOOST_MOVE_UREF##N)\ 1122 {\ 1123 NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ 1124 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\ 1125 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\ 1126 destroy_deallocator.release();\ 1127 return ret;\ 1128 }\ 1129 \ 1130 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 1131 iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1132 {\ 1133 BOOST_ASSERT((priv_is_linked)(hint));\ 1134 NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ 1135 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\ 1136 iterator ret(this->icont().insert_equal(hint.get(), *tmp));\ 1137 destroy_deallocator.release();\ 1138 return ret;\ 1139 }\ 1140 \ 1141 template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\ 1142 BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\ 1143 try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1144 {\ 1145 insert_commit_data data;\ 1146 const key_type & k = key;\ 1147 std::pair<iiterator, bool> ret =\ 1148 hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)\ 1149 : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);\ 1150 if(ret.second){\ 1151 ret.first = this->icont().insert_unique_commit\ 1152 (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\ 1153 }\ 1154 return std::pair<iterator, bool>(iterator(ret.first), ret.second);\ 1155 }\ 1156 // 1157 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE) 1158 #undef BOOST_CONTAINER_TREE_EMPLACE_CODE 1159 1160 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1161 1162 template<class MovableConvertible> insert_unique_convertible(const_iterator hint,BOOST_FWD_REF (MovableConvertible)v)1163 iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) 1164 { 1165 BOOST_ASSERT((priv_is_linked)(hint)); 1166 insert_commit_data data; 1167 std::pair<iterator,bool> ret = 1168 this->insert_unique_check(hint, key_of_value_t()(v), data); 1169 if(!ret.second) 1170 return ret.first; 1171 return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data); 1172 } 1173 1174 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator) 1175 1176 template <class InputIterator> insert_unique(InputIterator first,InputIterator last)1177 void insert_unique(InputIterator first, InputIterator last) 1178 { 1179 for( ; first != last; ++first) 1180 this->insert_unique(*first); 1181 } 1182 insert_equal(const value_type & v)1183 iterator insert_equal(const value_type& v) 1184 { 1185 NodePtr tmp(AllocHolder::create_node(v)); 1186 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1187 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1188 destroy_deallocator.release(); 1189 return ret; 1190 } 1191 1192 template<class MovableConvertible> insert_equal(BOOST_FWD_REF (MovableConvertible)v)1193 iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v) 1194 { 1195 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); 1196 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1197 iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); 1198 destroy_deallocator.release(); 1199 return ret; 1200 } 1201 1202 template<class MovableConvertible> insert_equal_convertible(const_iterator hint,BOOST_FWD_REF (MovableConvertible)v)1203 iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) 1204 { 1205 BOOST_ASSERT((priv_is_linked)(hint)); 1206 NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); 1207 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); 1208 iterator ret(this->icont().insert_equal(hint.get(), *tmp)); 1209 destroy_deallocator.release(); 1210 return ret; 1211 } 1212 1213 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator) 1214 1215 template <class InputIterator> insert_equal(InputIterator first,InputIterator last)1216 void insert_equal(InputIterator first, InputIterator last) 1217 { 1218 for( ; first != last; ++first) 1219 this->insert_equal(*first); 1220 } 1221 1222 template<class KeyType, class M> insert_or_assign(const_iterator hint,BOOST_FWD_REF (KeyType)key,BOOST_FWD_REF (M)obj)1223 std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj) 1224 { 1225 insert_commit_data data; 1226 const key_type & k = key; //Support emulated rvalue references 1227 std::pair<iiterator, bool> ret = 1228 hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data) 1229 : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data); 1230 if(ret.second){ 1231 ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data); 1232 } 1233 else{ 1234 ret.first->get_data().second = boost::forward<M>(obj); 1235 } 1236 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 1237 } 1238 erase(const_iterator position)1239 iterator erase(const_iterator position) 1240 { 1241 BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); 1242 return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); 1243 } 1244 erase(const key_type & k)1245 BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k) 1246 { return AllocHolder::erase_key(k, KeyNodeCompare(key_comp()), alloc_version()); } 1247 erase(const_iterator first,const_iterator last)1248 iterator erase(const_iterator first, const_iterator last) 1249 { 1250 BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first))); 1251 BOOST_ASSERT(first == last || (priv_is_linked)(last)); 1252 return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); 1253 } 1254 extract(const key_type & k)1255 node_type extract(const key_type& k) 1256 { 1257 iterator const it = this->find(k); 1258 if(this->end() != it){ 1259 return this->extract(it); 1260 } 1261 return node_type(); 1262 } 1263 extract(const_iterator position)1264 node_type extract(const_iterator position) 1265 { 1266 BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); 1267 iiterator const iit(position.get()); 1268 this->icont().erase(iit); 1269 return node_type(iit.operator->(), this->node_alloc()); 1270 } 1271 insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1272 insert_return_type insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1273 { 1274 return this->insert_unique_node(this->end(), boost::move(nh)); 1275 } 1276 insert_unique_node(const_iterator hint,BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1277 insert_return_type insert_unique_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1278 { 1279 insert_return_type irt; //inserted == false, node.empty() 1280 if(!nh.empty()){ 1281 insert_commit_data data; 1282 std::pair<iterator,bool> ret = 1283 this->insert_unique_check(hint, key_of_value_t()(nh.value()), data); 1284 if(ret.second){ 1285 irt.inserted = true; 1286 irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data)); 1287 nh.release(); 1288 } 1289 else{ 1290 irt.position = ret.first; 1291 irt.node = boost::move(nh); 1292 } 1293 } 1294 else{ 1295 irt.position = this->end(); 1296 } 1297 return BOOST_MOVE_RET(insert_return_type, irt); 1298 } 1299 insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1300 iterator insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1301 { 1302 if(nh.empty()){ 1303 return this->end(); 1304 } 1305 else{ 1306 NodePtr const p(nh.release()); 1307 return iterator(this->icont().insert_equal(*p)); 1308 } 1309 } 1310 insert_equal_node(const_iterator hint,BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)1311 iterator insert_equal_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) 1312 { 1313 if(nh.empty()){ 1314 return this->end(); 1315 } 1316 else{ 1317 NodePtr const p(nh.release()); 1318 return iterator(this->icont().insert_equal(hint.get(), *p)); 1319 } 1320 } 1321 1322 template<class C2> merge_unique(tree<T,KeyOfValue,C2,Allocator,Options> & source)1323 BOOST_CONTAINER_FORCEINLINE void merge_unique(tree<T, KeyOfValue, C2, Allocator, Options>& source) 1324 { return this->icont().merge_unique(source.icont()); } 1325 1326 template<class C2> merge_equal(tree<T,KeyOfValue,C2,Allocator,Options> & source)1327 BOOST_CONTAINER_FORCEINLINE void merge_equal(tree<T, KeyOfValue, C2, Allocator, Options>& source) 1328 { return this->icont().merge_equal(source.icont()); } clear()1329 BOOST_CONTAINER_FORCEINLINE void clear() 1330 { AllocHolder::clear(alloc_version()); } 1331 1332 // search operations. Const and non-const overloads even if no iterator is returned 1333 // so splay implementations can to their rebalancing when searching in non-const versions find(const key_type & k)1334 BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& k) 1335 { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); } 1336 find(const key_type & k) const1337 BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const 1338 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); } 1339 1340 template <class K> 1341 BOOST_CONTAINER_FORCEINLINE 1342 typename dtl::enable_if_transparent<key_compare, K, iterator>::type find(const K & k)1343 find(const K& k) 1344 { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); } 1345 1346 template <class K> 1347 BOOST_CONTAINER_FORCEINLINE 1348 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type find(const K & k) const1349 find(const K& k) const 1350 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); } 1351 count(const key_type & k) const1352 BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const 1353 { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); } 1354 1355 template <class K> 1356 BOOST_CONTAINER_FORCEINLINE 1357 typename dtl::enable_if_transparent<key_compare, K, size_type>::type count(const K & k) const1358 count(const K& k) const 1359 { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); } 1360 contains(const key_type & x) const1361 BOOST_CONTAINER_FORCEINLINE bool contains(const key_type& x) const 1362 { return this->find(x) != this->cend(); } 1363 1364 template<typename K> 1365 BOOST_CONTAINER_FORCEINLINE 1366 typename dtl::enable_if_transparent<key_compare, K, bool>::type contains(const K & x) const1367 contains(const K& x) const 1368 { return this->find(x) != this->cend(); } 1369 lower_bound(const key_type & k)1370 BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k) 1371 { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1372 lower_bound(const key_type & k) const1373 BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const 1374 { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1375 1376 template <class K> 1377 BOOST_CONTAINER_FORCEINLINE 1378 typename dtl::enable_if_transparent<key_compare, K, iterator>::type lower_bound(const K & k)1379 lower_bound(const K& k) 1380 { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1381 1382 template <class K> 1383 BOOST_CONTAINER_FORCEINLINE 1384 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type lower_bound(const K & k) const1385 lower_bound(const K& k) const 1386 { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); } 1387 upper_bound(const key_type & k)1388 BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k) 1389 { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1390 upper_bound(const key_type & k) const1391 BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const 1392 { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1393 1394 template <class K> 1395 BOOST_CONTAINER_FORCEINLINE 1396 typename dtl::enable_if_transparent<key_compare, K, iterator>::type upper_bound(const K & k)1397 upper_bound(const K& k) 1398 { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1399 1400 template <class K> 1401 BOOST_CONTAINER_FORCEINLINE 1402 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type upper_bound(const K & k) const1403 upper_bound(const K& k) const 1404 { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); } 1405 equal_range(const key_type & k)1406 std::pair<iterator,iterator> equal_range(const key_type& k) 1407 { 1408 std::pair<iiterator, iiterator> ret = 1409 this->icont().equal_range(k, KeyNodeCompare(key_comp())); 1410 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1411 } 1412 equal_range(const key_type & k) const1413 std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const 1414 { 1415 std::pair<iiterator, iiterator> ret = 1416 this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp())); 1417 return std::pair<const_iterator,const_iterator> 1418 (const_iterator(ret.first), const_iterator(ret.second)); 1419 } 1420 1421 template <class K> 1422 BOOST_CONTAINER_FORCEINLINE 1423 typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type equal_range(const K & k)1424 equal_range(const K& k) 1425 { 1426 std::pair<iiterator, iiterator> ret = 1427 this->icont().equal_range(k, KeyNodeCompare(key_comp())); 1428 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1429 } 1430 1431 template <class K> 1432 BOOST_CONTAINER_FORCEINLINE 1433 typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type equal_range(const K & k) const1434 equal_range(const K& k) const 1435 { 1436 std::pair<iiterator, iiterator> ret = 1437 this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp())); 1438 return std::pair<const_iterator,const_iterator> 1439 (const_iterator(ret.first), const_iterator(ret.second)); 1440 } 1441 lower_bound_range(const key_type & k)1442 std::pair<iterator,iterator> lower_bound_range(const key_type& k) 1443 { 1444 std::pair<iiterator, iiterator> ret = 1445 this->icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1446 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1447 } 1448 lower_bound_range(const key_type & k) const1449 std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const 1450 { 1451 std::pair<iiterator, iiterator> ret = 1452 this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1453 return std::pair<const_iterator,const_iterator> 1454 (const_iterator(ret.first), const_iterator(ret.second)); 1455 } 1456 1457 template <class K> 1458 BOOST_CONTAINER_FORCEINLINE 1459 typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type lower_bound_range(const K & k)1460 lower_bound_range(const K& k) 1461 { 1462 std::pair<iiterator, iiterator> ret = 1463 this->icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1464 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 1465 } 1466 1467 template <class K> 1468 BOOST_CONTAINER_FORCEINLINE 1469 typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type lower_bound_range(const K & k) const1470 lower_bound_range(const K& k) const 1471 { 1472 std::pair<iiterator, iiterator> ret = 1473 this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp())); 1474 return std::pair<const_iterator,const_iterator> 1475 (const_iterator(ret.first), const_iterator(ret.second)); 1476 } 1477 rebalance()1478 BOOST_CONTAINER_FORCEINLINE void rebalance() 1479 { intrusive_tree_proxy_t::rebalance(this->icont()); } 1480 operator ==(const tree & x,const tree & y)1481 BOOST_CONTAINER_FORCEINLINE friend bool operator==(const tree& x, const tree& y) 1482 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } 1483 operator <(const tree & x,const tree & y)1484 BOOST_CONTAINER_FORCEINLINE friend bool operator<(const tree& x, const tree& y) 1485 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } 1486 operator !=(const tree & x,const tree & y)1487 BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const tree& x, const tree& y) 1488 { return !(x == y); } 1489 operator >(const tree & x,const tree & y)1490 BOOST_CONTAINER_FORCEINLINE friend bool operator>(const tree& x, const tree& y) 1491 { return y < x; } 1492 operator <=(const tree & x,const tree & y)1493 BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const tree& x, const tree& y) 1494 { return !(y < x); } 1495 operator >=(const tree & x,const tree & y)1496 BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const tree& x, const tree& y) 1497 { return !(x < y); } 1498 swap(tree & x,tree & y)1499 BOOST_CONTAINER_FORCEINLINE friend void swap(tree& x, tree& y) 1500 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value 1501 && boost::container::dtl::is_nothrow_swappable<Compare>::value ) 1502 { x.swap(y); } 1503 }; 1504 1505 } //namespace dtl { 1506 } //namespace container { 1507 1508 template <class T> 1509 struct has_trivial_destructor_after_move; 1510 1511 //!has_trivial_destructor_after_move<> == true_type 1512 //!specialization for optimizations 1513 template <class T, class KeyOfValue, class Compare, class Allocator, class Options> 1514 struct has_trivial_destructor_after_move 1515 < 1516 ::boost::container::dtl::tree 1517 <T, KeyOfValue, Compare, Allocator, Options> 1518 > 1519 { 1520 typedef typename ::boost::container::dtl::tree<T, KeyOfValue, Compare, Allocator, Options>::allocator_type allocator_type; 1521 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer; 1522 static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value && 1523 ::boost::has_trivial_destructor_after_move<pointer>::value && 1524 ::boost::has_trivial_destructor_after_move<Compare>::value; 1525 }; 1526 1527 } //namespace boost { 1528 1529 #include <boost/container/detail/config_end.hpp> 1530 1531 #endif //BOOST_CONTAINER_TREE_HPP 1532