tree.hpp 52 KB

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