tree.hpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479
  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. //`allocator_type::value_type` must match container's `value type`. If this
  395. //assertion fails, please review your allocator definition.
  396. BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<value_type, typename allocator_traits<allocator_type>::value_type>::value));
  397. typedef key_node_pred<key_compare, key_of_value_t, Node> KeyNodeCompare;
  398. public:
  399. inline tree()
  400. : AllocHolder()
  401. {}
  402. inline explicit tree(const key_compare& comp)
  403. : AllocHolder(ValComp(comp))
  404. {}
  405. inline explicit tree(const key_compare& comp, const allocator_type& a)
  406. : AllocHolder(ValComp(comp), a)
  407. {}
  408. inline explicit tree(const allocator_type& a)
  409. : AllocHolder(a)
  410. {}
  411. template <class InputIterator>
  412. tree(bool unique_insertion, InputIterator first, InputIterator last)
  413. : AllocHolder(value_compare(key_compare()))
  414. {
  415. this->tree_construct(unique_insertion, first, last);
  416. //AllocHolder clears in case of exception
  417. }
  418. template <class InputIterator>
  419. tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp)
  420. : AllocHolder(value_compare(comp))
  421. {
  422. this->tree_construct(unique_insertion, first, last);
  423. //AllocHolder clears in case of exception
  424. }
  425. template <class InputIterator>
  426. tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a)
  427. : AllocHolder(value_compare(comp), a)
  428. {
  429. this->tree_construct(unique_insertion, first, last);
  430. //AllocHolder clears in case of exception
  431. }
  432. //construct with ordered range
  433. template <class InputIterator>
  434. tree( ordered_range_t, InputIterator first, InputIterator last)
  435. : AllocHolder(value_compare(key_compare()))
  436. {
  437. this->tree_construct(ordered_range_t(), first, last);
  438. }
  439. template <class InputIterator>
  440. tree( ordered_range_t, InputIterator first, InputIterator last, const key_compare& comp)
  441. : AllocHolder(value_compare(comp))
  442. {
  443. this->tree_construct(ordered_range_t(), first, last);
  444. }
  445. template <class InputIterator>
  446. tree( ordered_range_t, InputIterator first, InputIterator last
  447. , const key_compare& comp, const allocator_type& a)
  448. : AllocHolder(value_compare(comp), a)
  449. {
  450. this->tree_construct(ordered_range_t(), first, last);
  451. }
  452. private:
  453. template <class InputIterator>
  454. void tree_construct(bool unique_insertion, InputIterator first, InputIterator last)
  455. {
  456. //Use cend() as hint to achieve linear time for
  457. //ordered ranges as required by the standard
  458. //for the constructor
  459. if(unique_insertion){
  460. const const_iterator end_it(this->cend());
  461. for ( ; first != last; ++first){
  462. this->insert_unique_hint_convertible(end_it, *first);
  463. }
  464. }
  465. else{
  466. this->tree_construct_non_unique(first, last);
  467. }
  468. }
  469. template <class InputIterator>
  470. void tree_construct_non_unique(InputIterator first, InputIterator last
  471. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  472. , typename dtl::enable_if_or
  473. < void
  474. , dtl::is_same<alloc_version, version_1>
  475. , dtl::is_input_iterator<InputIterator>
  476. >::type * = 0
  477. #endif
  478. )
  479. {
  480. //Use cend() as hint to achieve linear time for
  481. //ordered ranges as required by the standard
  482. //for the constructor
  483. const const_iterator end_it(this->cend());
  484. for ( ; first != last; ++first){
  485. this->insert_equal_hint_convertible(end_it, *first);
  486. }
  487. }
  488. template <class InputIterator>
  489. void tree_construct_non_unique(InputIterator first, InputIterator last
  490. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  491. , typename dtl::disable_if_or
  492. < void
  493. , dtl::is_same<alloc_version, version_1>
  494. , dtl::is_input_iterator<InputIterator>
  495. >::type * = 0
  496. #endif
  497. )
  498. {
  499. //Optimized allocation and construction
  500. this->allocate_many_and_construct
  501. ( first, boost::container::iterator_udistance(first, last)
  502. , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
  503. }
  504. template <class InputIterator>
  505. void tree_construct( ordered_range_t, InputIterator first, InputIterator last
  506. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  507. , typename dtl::disable_if_or
  508. < void
  509. , dtl::is_same<alloc_version, version_1>
  510. , dtl::is_input_iterator<InputIterator>
  511. >::type * = 0
  512. #endif
  513. )
  514. {
  515. //Optimized allocation and construction
  516. this->allocate_many_and_construct
  517. ( first, boost::container::iterator_udistance(first, last)
  518. , dtl::push_back_functor<Node, Icont>(this->icont()));
  519. //AllocHolder clears in case of exception
  520. }
  521. template <class InputIterator>
  522. void tree_construct( ordered_range_t, InputIterator first, InputIterator last
  523. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  524. , typename dtl::enable_if_or
  525. < void
  526. , dtl::is_same<alloc_version, version_1>
  527. , dtl::is_input_iterator<InputIterator>
  528. >::type * = 0
  529. #endif
  530. )
  531. {
  532. for ( ; first != last; ++first){
  533. this->push_back_impl(*first);
  534. }
  535. }
  536. public:
  537. inline tree(const tree& x)
  538. : AllocHolder(x, x.value_comp())
  539. {
  540. this->icont().clone_from
  541. (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
  542. }
  543. inline tree(BOOST_RV_REF(tree) x)
  544. BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
  545. : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp())
  546. {}
  547. inline tree(const tree& x, const allocator_type &a)
  548. : AllocHolder(x.value_comp(), a)
  549. {
  550. this->icont().clone_from
  551. (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
  552. //AllocHolder clears in case of exception
  553. }
  554. tree(BOOST_RV_REF(tree) x, const allocator_type &a)
  555. : AllocHolder(x.value_comp(), a)
  556. {
  557. if(this->node_alloc() == x.node_alloc()){
  558. this->icont().swap(x.icont());
  559. }
  560. else{
  561. this->icont().clone_from
  562. (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc()));
  563. }
  564. //AllocHolder clears in case of exception
  565. }
  566. inline ~tree()
  567. {} //AllocHolder clears the tree
  568. tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
  569. {
  570. if (BOOST_LIKELY(this != &x)) {
  571. NodeAlloc &this_alloc = this->get_stored_allocator();
  572. const NodeAlloc &x_alloc = x.get_stored_allocator();
  573. dtl::bool_<allocator_traits<NodeAlloc>::
  574. propagate_on_container_copy_assignment::value> flag;
  575. if(flag && this_alloc != x_alloc){
  576. this->clear();
  577. }
  578. this->AllocHolder::copy_assign_alloc(x);
  579. //Transfer all the nodes to a temporary tree
  580. //If anything goes wrong, all the nodes will be destroyed
  581. //automatically
  582. Icont other_tree(::boost::move(this->icont()));
  583. //Now recreate the source tree reusing nodes stored by other_tree
  584. this->icont().clone_from
  585. (x.icont()
  586. , RecyclingCloner<AllocHolder, false>(*this, other_tree)
  587. , Destroyer(this->node_alloc()));
  588. //If there are remaining nodes, destroy them
  589. NodePtr p;
  590. while((p = other_tree.unlink_leftmost_without_rebalance())){
  591. AllocHolder::destroy_node(p);
  592. }
  593. }
  594. return *this;
  595. }
  596. tree& operator=(BOOST_RV_REF(tree) x)
  597. BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
  598. allocator_traits_type::is_always_equal::value) &&
  599. boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
  600. {
  601. if (BOOST_LIKELY(this != &x)) {
  602. //We know resources can be transferred at comiple time if both allocators are
  603. //always equal or the allocator is going to be propagated
  604. const bool can_steal_resources_alloc
  605. = allocator_traits_type::propagate_on_container_move_assignment::value
  606. || allocator_traits_type::is_always_equal::value;
  607. dtl::bool_<can_steal_resources_alloc> flag;
  608. this->priv_move_assign(boost::move(x), flag);
  609. }
  610. return *this;
  611. }
  612. public:
  613. // accessors:
  614. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  615. value_compare value_comp() const
  616. { return value_compare(this->key_comp()); }
  617. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  618. key_compare key_comp() const
  619. { return this->icont().key_comp(); }
  620. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  621. allocator_type get_allocator() const
  622. { return allocator_type(this->node_alloc()); }
  623. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  624. const stored_allocator_type &get_stored_allocator() const
  625. { return this->node_alloc(); }
  626. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  627. stored_allocator_type &get_stored_allocator()
  628. { return this->node_alloc(); }
  629. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  630. iterator begin()
  631. { return iterator(this->icont().begin()); }
  632. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  633. const_iterator begin() const
  634. { return this->cbegin(); }
  635. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  636. iterator end()
  637. { return iterator(this->icont().end()); }
  638. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  639. const_iterator end() const
  640. { return this->cend(); }
  641. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  642. reverse_iterator rbegin()
  643. { return reverse_iterator(end()); }
  644. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  645. const_reverse_iterator rbegin() const
  646. { return this->crbegin(); }
  647. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  648. reverse_iterator rend()
  649. { return reverse_iterator(begin()); }
  650. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  651. const_reverse_iterator rend() const
  652. { return this->crend(); }
  653. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
  654. //!
  655. //! <b>Throws</b>: Nothing.
  656. //!
  657. //! <b>Complexity</b>: Constant.
  658. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  659. const_iterator cbegin() const
  660. { return const_iterator(this->non_const_icont().begin()); }
  661. //! <b>Effects</b>: Returns a const_iterator to the end of the container.
  662. //!
  663. //! <b>Throws</b>: Nothing.
  664. //!
  665. //! <b>Complexity</b>: Constant.
  666. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  667. const_iterator cend() const
  668. { return const_iterator(this->non_const_icont().end()); }
  669. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
  670. //! of the reversed container.
  671. //!
  672. //! <b>Throws</b>: Nothing.
  673. //!
  674. //! <b>Complexity</b>: Constant.
  675. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  676. const_reverse_iterator crbegin() const
  677. { return const_reverse_iterator(cend()); }
  678. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
  679. //! of the reversed container.
  680. //!
  681. //! <b>Throws</b>: Nothing.
  682. //!
  683. //! <b>Complexity</b>: Constant.
  684. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  685. const_reverse_iterator crend() const
  686. { return const_reverse_iterator(cbegin()); }
  687. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  688. bool empty() const
  689. { return !this->size(); }
  690. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  691. size_type size() const
  692. { return this->icont().size(); }
  693. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  694. size_type max_size() const
  695. { return AllocHolder::max_size(); }
  696. inline void swap(ThisType& x)
  697. BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
  698. && boost::container::dtl::is_nothrow_swappable<Compare>::value )
  699. { AllocHolder::swap(x); }
  700. public:
  701. typedef typename Icont::insert_commit_data insert_commit_data;
  702. // insert/erase
  703. std::pair<iterator,bool> insert_unique_check
  704. (const key_type& key, insert_commit_data &data)
  705. {
  706. std::pair<iiterator, bool> ret =
  707. this->icont().insert_unique_check(key, data);
  708. return std::pair<iterator, bool>(iterator(ret.first), ret.second);
  709. }
  710. std::pair<iterator,bool> insert_unique_check
  711. (const_iterator hint, const key_type& key, insert_commit_data &data)
  712. {
  713. BOOST_ASSERT((priv_is_linked)(hint));
  714. std::pair<iiterator, bool> ret =
  715. this->icont().insert_unique_check(hint.get(), key, data);
  716. return std::pair<iterator, bool>(iterator(ret.first), ret.second);
  717. }
  718. template<class MovableConvertible>
  719. iterator insert_unique_commit
  720. (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data)
  721. {
  722. NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(v));
  723. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
  724. iterator ret(this->icont().insert_unique_commit(*tmp, data));
  725. destroy_deallocator.release();
  726. return ret;
  727. }
  728. template<class MovableConvertible>
  729. std::pair<iterator,bool> insert_unique_convertible(BOOST_FWD_REF(MovableConvertible) v)
  730. {
  731. insert_commit_data data;
  732. std::pair<iterator,bool> ret =
  733. this->insert_unique_check(key_of_value_t()(v), data);
  734. if(ret.second){
  735. ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
  736. }
  737. return ret;
  738. }
  739. template<class MovableConvertible>
  740. iterator insert_unique_hint_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
  741. {
  742. BOOST_ASSERT((priv_is_linked)(hint));
  743. insert_commit_data data;
  744. std::pair<iterator,bool> ret =
  745. this->insert_unique_check(hint, key_of_value_t()(v), data);
  746. if(!ret.second)
  747. return ret.first;
  748. return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
  749. }
  750. private:
  751. void priv_move_assign(BOOST_RV_REF(tree) x, dtl::bool_<true> /*steal_resources*/)
  752. {
  753. //Destroy objects but retain memory in case x reuses it in the future
  754. this->clear();
  755. //Move allocator if needed
  756. this->AllocHolder::move_assign_alloc(x);
  757. //Obtain resources
  758. this->icont() = boost::move(x.icont());
  759. }
  760. void priv_move_assign(BOOST_RV_REF(tree) x, dtl::bool_<false> /*steal_resources*/)
  761. {
  762. //We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
  763. //Resources can be transferred if both allocators are equal
  764. if (this->node_alloc() == x.node_alloc()) {
  765. this->priv_move_assign(boost::move(x), dtl::true_());
  766. }
  767. else {
  768. //Transfer all the nodes to a temporary tree
  769. //If anything goes wrong, all the nodes will be destroyed
  770. //automatically
  771. Icont other_tree(::boost::move(this->icont()));
  772. //Now recreate the source tree reusing nodes stored by other_tree
  773. this->icont().clone_from
  774. (::boost::move(x.icont())
  775. , RecyclingCloner<AllocHolder, true>(*this, other_tree)
  776. , Destroyer(this->node_alloc()));
  777. //If there are remaining nodes, destroy them
  778. NodePtr p;
  779. while ((p = other_tree.unlink_leftmost_without_rebalance())) {
  780. AllocHolder::destroy_node(p);
  781. }
  782. }
  783. }
  784. template<class KeyConvertible, class M>
  785. iiterator priv_insert_or_assign_commit
  786. (BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data)
  787. {
  788. NodePtr tmp = AllocHolder::create_node(boost::forward<KeyConvertible>(key), boost::forward<M>(obj));
  789. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
  790. iiterator ret(this->icont().insert_unique_commit(*tmp, data));
  791. destroy_deallocator.release();
  792. return ret;
  793. }
  794. bool priv_is_linked(const_iterator const position) const
  795. {
  796. iiterator const cur(position.get());
  797. return cur == this->icont().end() ||
  798. cur == this->icont().root() ||
  799. iiterator(cur).go_parent().go_left() == cur ||
  800. iiterator(cur).go_parent().go_right() == cur;
  801. }
  802. template<class MovableConvertible>
  803. void push_back_impl(BOOST_FWD_REF(MovableConvertible) v)
  804. {
  805. NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
  806. //push_back has no-throw guarantee so avoid any deallocator/destroyer
  807. this->icont().push_back(*tmp);
  808. }
  809. std::pair<iterator, bool> emplace_unique_node(NodePtr p)
  810. {
  811. value_type &v = p->get_data();
  812. insert_commit_data data;
  813. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc());
  814. std::pair<iterator,bool> ret =
  815. this->insert_unique_check(key_of_value_t()(v), data);
  816. if(!ret.second){
  817. return ret;
  818. }
  819. //No throw insertion part, release rollback
  820. destroy_deallocator.release();
  821. return std::pair<iterator,bool>
  822. ( iterator(this->icont().insert_unique_commit(*p, data))
  823. , true );
  824. }
  825. iterator emplace_hint_unique_node(const_iterator hint, NodePtr p)
  826. {
  827. BOOST_ASSERT((priv_is_linked)(hint));
  828. value_type &v = p->get_data();
  829. insert_commit_data data;
  830. std::pair<iterator,bool> ret =
  831. this->insert_unique_check(hint, key_of_value_t()(v), data);
  832. if(!ret.second){
  833. //Destroy unneeded node
  834. Destroyer(this->node_alloc())(p);
  835. return ret.first;
  836. }
  837. return iterator(this->icont().insert_unique_commit(*p, data));
  838. }
  839. public:
  840. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  841. template <class... Args>
  842. inline std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
  843. { return this->emplace_unique_node(AllocHolder::create_node(boost::forward<Args>(args)...)); }
  844. template <class... Args>
  845. inline iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
  846. { return this->emplace_hint_unique_node(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); }
  847. template <class... Args>
  848. iterator emplace_equal(BOOST_FWD_REF(Args)... args)
  849. {
  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(this->icont().end(), *tmp));
  853. destroy_deallocator.release();
  854. return ret;
  855. }
  856. template <class... Args>
  857. iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
  858. {
  859. BOOST_ASSERT((priv_is_linked)(hint));
  860. NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
  861. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
  862. iterator ret(this->icont().insert_equal(hint.get(), *tmp));
  863. destroy_deallocator.release();
  864. return ret;
  865. }
  866. template <class KeyType, class... Args>
  867. inline std::pair<iterator, bool> try_emplace
  868. (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
  869. {
  870. insert_commit_data data;
  871. const key_type & k = key; //Support emulated rvalue references
  872. std::pair<iiterator, bool> ret =
  873. hint == const_iterator() ? this->icont().insert_unique_check( k, data)
  874. : this->icont().insert_unique_check(hint.get(), k, data);
  875. if(ret.second){
  876. ret.first = this->icont().insert_unique_commit
  877. (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data);
  878. }
  879. return std::pair<iterator, bool>(iterator(ret.first), ret.second);
  880. }
  881. #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  882. #define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \
  883. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  884. std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
  885. { return this->emplace_unique_node(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
  886. \
  887. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  888. iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  889. { return this->emplace_hint_unique_node(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
  890. \
  891. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  892. iterator emplace_equal(BOOST_MOVE_UREF##N)\
  893. {\
  894. NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\
  895. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\
  896. iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\
  897. destroy_deallocator.release();\
  898. return ret;\
  899. }\
  900. \
  901. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  902. iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  903. {\
  904. BOOST_ASSERT((priv_is_linked)(hint));\
  905. NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\
  906. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\
  907. iterator ret(this->icont().insert_equal(hint.get(), *tmp));\
  908. destroy_deallocator.release();\
  909. return ret;\
  910. }\
  911. \
  912. template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
  913. inline std::pair<iterator, bool>\
  914. try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  915. {\
  916. insert_commit_data data;\
  917. const key_type & k = key;\
  918. std::pair<iiterator, bool> ret =\
  919. hint == const_iterator() ? this->icont().insert_unique_check( k, data)\
  920. : this->icont().insert_unique_check(hint.get(), k, data);\
  921. if(ret.second){\
  922. ret.first = this->icont().insert_unique_commit\
  923. (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\
  924. }\
  925. return std::pair<iterator, bool>(iterator(ret.first), ret.second);\
  926. }\
  927. //
  928. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE)
  929. #undef BOOST_CONTAINER_TREE_EMPLACE_CODE
  930. #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  931. //BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_hint_convertible, const_iterator, const_iterator)
  932. template <class InputIterator>
  933. void insert_unique_range(InputIterator first, InputIterator last)
  934. {
  935. for( ; first != last; ++first)
  936. this->insert_unique_convertible(*first);
  937. }
  938. template<class MovableConvertible>
  939. iterator insert_equal_convertible(BOOST_FWD_REF(MovableConvertible) v)
  940. {
  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(this->icont().end(), *tmp));
  944. destroy_deallocator.release();
  945. return ret;
  946. }
  947. template<class MovableConvertible>
  948. iterator insert_equal_hint_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
  949. {
  950. BOOST_ASSERT((priv_is_linked)(hint));
  951. NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
  952. scoped_node_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
  953. iterator ret(this->icont().insert_equal(hint.get(), *tmp));
  954. destroy_deallocator.release();
  955. return ret;
  956. }
  957. BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
  958. (insert_equal, value_type, iterator, this->insert_equal_hint_convertible, const_iterator, const_iterator)
  959. template <class InputIterator>
  960. void insert_equal_range(InputIterator first, InputIterator last)
  961. {
  962. for( ; first != last; ++first)
  963. this->insert_equal_convertible(*first);
  964. }
  965. template<class KeyType, class M>
  966. std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
  967. {
  968. insert_commit_data data;
  969. const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
  970. std::pair<iiterator, bool> ret =
  971. hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data)
  972. : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
  973. if(ret.second){
  974. ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data);
  975. }
  976. else{
  977. ret.first->get_data().second = boost::forward<M>(obj);
  978. }
  979. return std::pair<iterator, bool>(iterator(ret.first), ret.second);
  980. }
  981. iterator erase(const_iterator position)
  982. {
  983. BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
  984. return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc())));
  985. }
  986. inline size_type erase(const key_type& k)
  987. { return AllocHolder::erase_key(k, alloc_version()); }
  988. size_type erase_unique(const key_type& k)
  989. {
  990. iterator i = this->find(k);
  991. size_type ret = static_cast<size_type>(i != this->end());
  992. if (ret)
  993. this->erase(i);
  994. return ret;
  995. }
  996. template <class K>
  997. inline typename dtl::enable_if_c<
  998. dtl::is_transparent<key_compare>::value && //transparent
  999. !dtl::is_convertible<K, iterator>::value && //not convertible to iterator
  1000. !dtl::is_convertible<K, const_iterator>::value //not convertible to const_iterator
  1001. , size_type>::type
  1002. erase(BOOST_FWD_REF(K) key)
  1003. {
  1004. const typename remove_cvref<K>::type & k = key; //Support emulated rvalue references
  1005. return AllocHolder::erase_key(k, KeyNodeCompare(key_comp()), alloc_version());
  1006. }
  1007. template <class K>
  1008. inline typename dtl::enable_if_c<
  1009. dtl::is_transparent<key_compare>::value && //transparent
  1010. !dtl::is_convertible<K, iterator>::value && //not convertible to iterator
  1011. !dtl::is_convertible<K, const_iterator>::value //not convertible to const_iterator
  1012. , size_type>::type
  1013. erase_unique(const K& k)
  1014. {
  1015. iterator i = this->find(k);
  1016. size_type ret = static_cast<size_type>(i != this->end());
  1017. if (ret)
  1018. this->erase(i);
  1019. return ret;
  1020. }
  1021. iterator erase(const_iterator first, const_iterator last)
  1022. {
  1023. BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first)));
  1024. BOOST_ASSERT(first == last || (priv_is_linked)(last));
  1025. return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version()));
  1026. }
  1027. node_type extract(const key_type& k)
  1028. {
  1029. iterator const it = this->find(k);
  1030. if(this->end() != it){
  1031. return this->extract(it);
  1032. }
  1033. return node_type();
  1034. }
  1035. node_type extract(const_iterator position)
  1036. {
  1037. BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
  1038. iiterator const iit(position.get());
  1039. this->icont().erase(iit);
  1040. return node_type(iit.operator->(), this->node_alloc());
  1041. }
  1042. insert_return_type insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
  1043. {
  1044. return this->insert_unique_node(this->end(), boost::move(nh));
  1045. }
  1046. insert_return_type insert_unique_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
  1047. {
  1048. insert_return_type irt; //inserted == false, node.empty()
  1049. if(!nh.empty()){
  1050. insert_commit_data data;
  1051. std::pair<iterator,bool> ret =
  1052. this->insert_unique_check(hint, key_of_value_t()(nh.value()), data);
  1053. if(ret.second){
  1054. irt.inserted = true;
  1055. irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data));
  1056. nh.release();
  1057. }
  1058. else{
  1059. irt.position = ret.first;
  1060. irt.node = boost::move(nh);
  1061. }
  1062. }
  1063. else{
  1064. irt.position = this->end();
  1065. }
  1066. return BOOST_MOVE_RET(insert_return_type, irt);
  1067. }
  1068. iterator insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
  1069. {
  1070. if(nh.empty()){
  1071. return this->end();
  1072. }
  1073. else{
  1074. NodePtr const p(nh.release());
  1075. return iterator(this->icont().insert_equal(*p));
  1076. }
  1077. }
  1078. iterator insert_equal_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
  1079. {
  1080. if(nh.empty()){
  1081. return this->end();
  1082. }
  1083. else{
  1084. NodePtr const p(nh.release());
  1085. return iterator(this->icont().insert_equal(hint.get(), *p));
  1086. }
  1087. }
  1088. template<class C2>
  1089. inline void merge_unique(tree<T, KeyOfValue, C2, Allocator, Options>& source)
  1090. { return this->icont().merge_unique(source.icont()); }
  1091. template<class C2>
  1092. inline void merge_equal(tree<T, KeyOfValue, C2, Allocator, Options>& source)
  1093. { return this->icont().merge_equal(source.icont()); }
  1094. inline void clear()
  1095. { AllocHolder::clear(alloc_version()); }
  1096. // search operations. Const and non-const overloads even if no iterator is returned
  1097. // so splay implementations can to their rebalancing when searching in non-const versions
  1098. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1099. iterator find(const key_type& k)
  1100. { return iterator(this->icont().find(k)); }
  1101. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1102. const_iterator find(const key_type& k) const
  1103. { return const_iterator(this->non_const_icont().find(k)); }
  1104. template <class K>
  1105. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1106. typename dtl::enable_if_transparent<key_compare, K, iterator>::type
  1107. find(const K& k)
  1108. { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); }
  1109. template <class K>
  1110. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1111. typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
  1112. find(const K& k) const
  1113. { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); }
  1114. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1115. size_type count(const key_type& k) const
  1116. { return size_type(this->icont().count(k)); }
  1117. template <class K>
  1118. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1119. typename dtl::enable_if_transparent<key_compare, K, size_type>::type
  1120. count(const K& k) const
  1121. { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); }
  1122. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1123. bool contains(const key_type& x) const
  1124. { return this->find(x) != this->cend(); }
  1125. template<typename K>
  1126. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1127. typename dtl::enable_if_transparent<key_compare, K, bool>::type
  1128. contains(const K& x) const
  1129. { return this->find(x) != this->cend(); }
  1130. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1131. iterator lower_bound(const key_type& k)
  1132. { return iterator(this->icont().lower_bound(k)); }
  1133. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1134. const_iterator lower_bound(const key_type& k) const
  1135. { return const_iterator(this->non_const_icont().lower_bound(k)); }
  1136. template <class K>
  1137. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1138. typename dtl::enable_if_transparent<key_compare, K, iterator>::type
  1139. lower_bound(const K& k)
  1140. { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
  1141. template <class K>
  1142. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1143. typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
  1144. lower_bound(const K& k) const
  1145. { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
  1146. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1147. iterator upper_bound(const key_type& k)
  1148. { return iterator(this->icont().upper_bound(k)); }
  1149. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1150. const_iterator upper_bound(const key_type& k) const
  1151. { return const_iterator(this->non_const_icont().upper_bound(k)); }
  1152. template <class K>
  1153. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1154. typename dtl::enable_if_transparent<key_compare, K, iterator>::type
  1155. upper_bound(const K& k)
  1156. { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
  1157. template <class K>
  1158. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1159. typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
  1160. upper_bound(const K& k) const
  1161. { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
  1162. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1163. std::pair<iterator,iterator> equal_range(const key_type& k)
  1164. {
  1165. std::pair<iiterator, iiterator> ret = this->icont().equal_range(k);
  1166. return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
  1167. }
  1168. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1169. std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
  1170. {
  1171. std::pair<iiterator, iiterator> ret =
  1172. this->non_const_icont().equal_range(k);
  1173. return std::pair<const_iterator,const_iterator>
  1174. (const_iterator(ret.first), const_iterator(ret.second));
  1175. }
  1176. template <class K>
  1177. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1178. typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
  1179. equal_range(const K& k)
  1180. {
  1181. std::pair<iiterator, iiterator> ret =
  1182. this->icont().equal_range(k, KeyNodeCompare(key_comp()));
  1183. return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
  1184. }
  1185. template <class K>
  1186. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1187. typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type
  1188. equal_range(const K& k) const
  1189. {
  1190. std::pair<iiterator, iiterator> ret =
  1191. this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp()));
  1192. return std::pair<const_iterator,const_iterator>
  1193. (const_iterator(ret.first), const_iterator(ret.second));
  1194. }
  1195. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1196. std::pair<iterator,iterator> lower_bound_range(const key_type& k)
  1197. {
  1198. std::pair<iiterator, iiterator> ret =
  1199. this->icont().lower_bound_range(k);
  1200. return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
  1201. }
  1202. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1203. std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
  1204. {
  1205. std::pair<iiterator, iiterator> ret =
  1206. this->non_const_icont().lower_bound_range(k);
  1207. return std::pair<const_iterator,const_iterator>
  1208. (const_iterator(ret.first), const_iterator(ret.second));
  1209. }
  1210. template <class K>
  1211. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1212. typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
  1213. lower_bound_range(const K& k)
  1214. {
  1215. std::pair<iiterator, iiterator> ret =
  1216. this->icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
  1217. return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
  1218. }
  1219. template <class K>
  1220. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1221. typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type
  1222. lower_bound_range(const K& k) const
  1223. {
  1224. std::pair<iiterator, iiterator> ret =
  1225. this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
  1226. return std::pair<const_iterator,const_iterator>
  1227. (const_iterator(ret.first), const_iterator(ret.second));
  1228. }
  1229. inline void rebalance()
  1230. { intrusive_tree_proxy_t::rebalance(this->icont()); }
  1231. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1232. friend bool operator==(const tree& x, const tree& y)
  1233. { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
  1234. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1235. friend bool operator<(const tree& x, const tree& y)
  1236. { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
  1237. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1238. friend bool operator!=(const tree& x, const tree& y)
  1239. { return !(x == y); }
  1240. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1241. friend bool operator>(const tree& x, const tree& y)
  1242. { return y < x; }
  1243. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1244. friend bool operator<=(const tree& x, const tree& y)
  1245. { return !(y < x); }
  1246. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1247. friend bool operator>=(const tree& x, const tree& y)
  1248. { return !(x < y); }
  1249. inline friend void swap(tree& x, tree& y)
  1250. BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
  1251. && boost::container::dtl::is_nothrow_swappable<Compare>::value )
  1252. { x.swap(y); }
  1253. };
  1254. } //namespace dtl {
  1255. } //namespace container {
  1256. template <class T>
  1257. struct has_trivial_destructor_after_move;
  1258. //!has_trivial_destructor_after_move<> == true_type
  1259. //!specialization for optimizations
  1260. template <class T, class KeyOfValue, class Compare, class Allocator, class Options>
  1261. struct has_trivial_destructor_after_move
  1262. <
  1263. ::boost::container::dtl::tree
  1264. <T, KeyOfValue, Compare, Allocator, Options>
  1265. >
  1266. {
  1267. typedef typename ::boost::container::dtl::tree<T, KeyOfValue, Compare, Allocator, Options>::allocator_type allocator_type;
  1268. typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
  1269. BOOST_STATIC_CONSTEXPR bool value =
  1270. ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
  1271. ::boost::has_trivial_destructor_after_move<pointer>::value &&
  1272. ::boost::has_trivial_destructor_after_move<Compare>::value;
  1273. };
  1274. } //namespace boost {
  1275. #include <boost/container/detail/config_end.hpp>
  1276. #endif //BOOST_CONTAINER_TREE_HPP