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