tree.hpp 53 KB

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