sgtree.hpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-2014
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/intrusive for documentation.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. //
  13. // The option that yields to non-floating point 1/sqrt(2) alpha is taken
  14. // from the scapegoat tree implementation of the PSPP library.
  15. //
  16. /////////////////////////////////////////////////////////////////////////////
  17. #ifndef BOOST_INTRUSIVE_SGTREE_HPP
  18. #define BOOST_INTRUSIVE_SGTREE_HPP
  19. #include <boost/intrusive/detail/config_begin.hpp>
  20. #include <boost/intrusive/intrusive_fwd.hpp>
  21. #include <boost/intrusive/detail/assert.hpp>
  22. #include <boost/static_assert.hpp>
  23. #include <boost/intrusive/bs_set_hook.hpp>
  24. #include <boost/intrusive/bstree.hpp>
  25. #include <boost/intrusive/detail/tree_node.hpp>
  26. #include <boost/intrusive/pointer_traits.hpp>
  27. #include <boost/intrusive/detail/mpl.hpp>
  28. #include <boost/intrusive/detail/math.hpp>
  29. #include <boost/intrusive/detail/get_value_traits.hpp>
  30. #include <boost/intrusive/sgtree_algorithms.hpp>
  31. #include <boost/intrusive/detail/key_nodeptr_comp.hpp>
  32. #include <boost/intrusive/link_mode.hpp>
  33. #include <boost/move/utility_core.hpp>
  34. #include <boost/move/adl_move_swap.hpp>
  35. #include <cstddef>
  36. #include <boost/intrusive/detail/minimal_less_equal_header.hpp>
  37. #include <boost/intrusive/detail/minimal_pair_header.hpp> //std::pair
  38. #include <cmath>
  39. #include <cstddef>
  40. #if defined(BOOST_HAS_PRAGMA_ONCE)
  41. # pragma once
  42. #endif
  43. namespace boost {
  44. namespace intrusive {
  45. /// @cond
  46. namespace detail{
  47. /////////////////////////////////////////////////////////////
  48. //
  49. // Halpha for fixed floating_point<false> option
  50. //
  51. /////////////////////////////////////////////////////////////
  52. //! Returns floor(log2(n)/log2(sqrt(2))) -> floor(2*log2(n))
  53. //! Undefined if N is 0.
  54. //!
  55. //! This function does not use float point operations.
  56. inline std::size_t calculate_h_sqrt2 (std::size_t n)
  57. {
  58. std::size_t f_log2 = detail::floor_log2(n);
  59. return (2*f_log2) + static_cast<std::size_t>(n >= detail::sqrt2_pow_2xplus1(f_log2));
  60. }
  61. struct h_alpha_sqrt2_t
  62. {
  63. h_alpha_sqrt2_t(void){}
  64. std::size_t operator()(std::size_t n) const
  65. { return calculate_h_sqrt2(n); }
  66. };
  67. struct alpha_0_75_by_max_size_t
  68. {
  69. alpha_0_75_by_max_size_t(void){}
  70. std::size_t operator()(std::size_t max_tree_size) const
  71. {
  72. const std::size_t max_tree_size_limit = ((~std::size_t(0))/std::size_t(3));
  73. return max_tree_size > max_tree_size_limit ? max_tree_size/4*3 : max_tree_size*3/4;
  74. }
  75. };
  76. /////////////////////////////////////////////////////////////
  77. //
  78. // Halpha for fixed floating_point<true> option
  79. //
  80. /////////////////////////////////////////////////////////////
  81. struct h_alpha_t
  82. {
  83. explicit h_alpha_t(float inv_minus_logalpha)
  84. : inv_minus_logalpha_(inv_minus_logalpha)
  85. {}
  86. std::size_t operator()(std::size_t n) const
  87. {
  88. ////////////////////////////////////////////////////////////
  89. // This function must return "floor(log2(1/alpha(n)))" ->
  90. // floor(log2(n)/log(1/alpha)) ->
  91. // floor(log2(n)/-log2(alpha))
  92. // floor(log2(n)*(1/-log2(alpha)))
  93. ////////////////////////////////////////////////////////////
  94. return static_cast<std::size_t>(detail::fast_log2(float(n))*inv_minus_logalpha_);
  95. }
  96. private:
  97. //Since the function will be repeatedly called
  98. //precalculate constant data to avoid repeated
  99. //calls to log and division.
  100. //This will store 1/(-std::log2(alpha_))
  101. float inv_minus_logalpha_;
  102. };
  103. struct alpha_by_max_size_t
  104. {
  105. explicit alpha_by_max_size_t(float alpha)
  106. : alpha_(alpha)
  107. {}
  108. float operator()(std::size_t max_tree_size) const
  109. { return float(max_tree_size)*alpha_; }
  110. private:
  111. float alpha_;
  112. };
  113. template<bool Activate, class SizeType>
  114. struct alpha_holder
  115. {
  116. typedef boost::intrusive::detail::h_alpha_t h_alpha_t;
  117. typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t;
  118. alpha_holder()
  119. : max_tree_size_()
  120. { set_alpha(0.70711f); } // ~1/sqrt(2)
  121. float get_alpha() const
  122. { return alpha_; }
  123. void set_alpha(float alpha)
  124. {
  125. alpha_ = alpha;
  126. inv_minus_logalpha_ = 1/(-detail::fast_log2(alpha));
  127. }
  128. h_alpha_t get_h_alpha_t() const
  129. { return h_alpha_t(inv_minus_logalpha_); }
  130. multiply_by_alpha_t get_multiply_by_alpha_t() const
  131. { return multiply_by_alpha_t(alpha_); }
  132. protected:
  133. float alpha_;
  134. float inv_minus_logalpha_;
  135. SizeType max_tree_size_;
  136. };
  137. template<class SizeType>
  138. struct alpha_holder<false, SizeType>
  139. {
  140. //This specialization uses alpha = 1/sqrt(2)
  141. //without using floating point operations
  142. //Downside: alpha CAN't be changed.
  143. typedef boost::intrusive::detail::h_alpha_sqrt2_t h_alpha_t;
  144. typedef boost::intrusive::detail::alpha_0_75_by_max_size_t multiply_by_alpha_t;
  145. alpha_holder()
  146. : max_tree_size_()
  147. {}
  148. float get_alpha() const
  149. { return 0.70710677f; }
  150. void set_alpha(float)
  151. { //alpha CAN't be changed.
  152. BOOST_INTRUSIVE_INVARIANT_ASSERT(0);
  153. }
  154. h_alpha_t get_h_alpha_t() const
  155. { return h_alpha_t(); }
  156. multiply_by_alpha_t get_multiply_by_alpha_t() const
  157. { return multiply_by_alpha_t(); }
  158. SizeType max_tree_size_;
  159. };
  160. } //namespace detail{
  161. struct sgtree_defaults
  162. : bstree_defaults
  163. {
  164. static const bool floating_point = true;
  165. };
  166. /// @endcond
  167. //! The class template sgtree is an intrusive scapegoat tree container, that
  168. //! is used to construct intrusive sg_set and sg_multiset containers.
  169. //! The no-throw guarantee holds only, if the value_compare object
  170. //! doesn't throw.
  171. //!
  172. //! The template parameter \c T is the type to be managed by the container.
  173. //! The user can specify additional options and if no options are provided
  174. //! default options are used.
  175. //!
  176. //! The container supports the following options:
  177. //! \c base_hook<>/member_hook<>/value_traits<>,
  178. //! \c floating_point<>, \c size_type<> and
  179. //! \c compare<>.
  180. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
  181. template<class T, class ...Options>
  182. #else
  183. template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyComp, class SizeType, bool FloatingPoint, typename HeaderHolder>
  184. #endif
  185. class sgtree_impl
  186. /// @cond
  187. : public bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, true, SgTreeAlgorithms, HeaderHolder>
  188. , public detail::alpha_holder<FloatingPoint, SizeType>
  189. /// @endcond
  190. {
  191. public:
  192. typedef ValueTraits value_traits;
  193. /// @cond
  194. typedef bstree_impl< ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType
  195. , true, SgTreeAlgorithms, HeaderHolder> tree_type;
  196. typedef tree_type implementation_defined;
  197. /// @endcond
  198. typedef typename implementation_defined::pointer pointer;
  199. typedef typename implementation_defined::const_pointer const_pointer;
  200. typedef typename implementation_defined::value_type value_type;
  201. typedef typename implementation_defined::key_type key_type;
  202. typedef typename implementation_defined::key_of_value key_of_value;
  203. typedef typename implementation_defined::reference reference;
  204. typedef typename implementation_defined::const_reference const_reference;
  205. typedef typename implementation_defined::difference_type difference_type;
  206. typedef typename implementation_defined::size_type size_type;
  207. typedef typename implementation_defined::value_compare value_compare;
  208. typedef typename implementation_defined::key_compare key_compare;
  209. typedef typename implementation_defined::iterator iterator;
  210. typedef typename implementation_defined::const_iterator const_iterator;
  211. typedef typename implementation_defined::reverse_iterator reverse_iterator;
  212. typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator;
  213. typedef typename implementation_defined::node_traits node_traits;
  214. typedef typename implementation_defined::node node;
  215. typedef typename implementation_defined::node_ptr node_ptr;
  216. typedef typename implementation_defined::const_node_ptr const_node_ptr;
  217. typedef BOOST_INTRUSIVE_IMPDEF(sgtree_algorithms<node_traits>) node_algorithms;
  218. static const bool constant_time_size = implementation_defined::constant_time_size;
  219. static const bool floating_point = FloatingPoint;
  220. static const bool stateful_value_traits = implementation_defined::stateful_value_traits;
  221. /// @cond
  222. private:
  223. //noncopyable
  224. typedef detail::alpha_holder<FloatingPoint, SizeType> alpha_traits;
  225. typedef typename alpha_traits::h_alpha_t h_alpha_t;
  226. typedef typename alpha_traits::multiply_by_alpha_t multiply_by_alpha_t;
  227. BOOST_MOVABLE_BUT_NOT_COPYABLE(sgtree_impl)
  228. BOOST_STATIC_ASSERT(((int)value_traits::link_mode != (int)auto_unlink));
  229. enum { safemode_or_autounlink =
  230. (int)value_traits::link_mode == (int)auto_unlink ||
  231. (int)value_traits::link_mode == (int)safe_link };
  232. /// @endcond
  233. public:
  234. typedef BOOST_INTRUSIVE_IMPDEF(typename node_algorithms::insert_commit_data) insert_commit_data;
  235. //! @copydoc ::boost::intrusive::bstree::bstree()
  236. sgtree_impl()
  237. : tree_type()
  238. {}
  239. //! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
  240. explicit sgtree_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
  241. : tree_type(cmp, v_traits)
  242. {}
  243. //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const key_compare &,const value_traits &)
  244. template<class Iterator>
  245. sgtree_impl( bool unique, Iterator b, Iterator e
  246. , const key_compare &cmp = key_compare()
  247. , const value_traits &v_traits = value_traits())
  248. : tree_type(cmp, v_traits)
  249. {
  250. if(unique)
  251. this->insert_unique(b, e);
  252. else
  253. this->insert_equal(b, e);
  254. }
  255. //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&)
  256. sgtree_impl(BOOST_RV_REF(sgtree_impl) x)
  257. : tree_type(BOOST_MOVE_BASE(tree_type, x)), alpha_traits(x.get_alpha_traits())
  258. { ::boost::adl_move_swap(this->get_alpha_traits(), x.get_alpha_traits()); }
  259. //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&)
  260. sgtree_impl& operator=(BOOST_RV_REF(sgtree_impl) x)
  261. {
  262. this->get_alpha_traits() = x.get_alpha_traits();
  263. return static_cast<sgtree_impl&>(tree_type::operator=(BOOST_MOVE_BASE(tree_type, x)));
  264. }
  265. /// @cond
  266. private:
  267. const alpha_traits &get_alpha_traits() const
  268. { return *this; }
  269. alpha_traits &get_alpha_traits()
  270. { return *this; }
  271. h_alpha_t get_h_alpha_func() const
  272. { return this->get_alpha_traits().get_h_alpha_t(); }
  273. multiply_by_alpha_t get_alpha_by_max_size_func() const
  274. { return this->get_alpha_traits().get_multiply_by_alpha_t(); }
  275. /// @endcond
  276. public:
  277. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  278. //! @copydoc ::boost::intrusive::bstree::~bstree()
  279. ~sgtree_impl();
  280. //! @copydoc ::boost::intrusive::bstree::begin()
  281. iterator begin();
  282. //! @copydoc ::boost::intrusive::bstree::begin()const
  283. const_iterator begin() const;
  284. //! @copydoc ::boost::intrusive::bstree::cbegin()const
  285. const_iterator cbegin() const;
  286. //! @copydoc ::boost::intrusive::bstree::end()
  287. iterator end();
  288. //! @copydoc ::boost::intrusive::bstree::end()const
  289. const_iterator end() const;
  290. //! @copydoc ::boost::intrusive::bstree::cend()const
  291. const_iterator cend() const;
  292. //! @copydoc ::boost::intrusive::bstree::rbegin()
  293. reverse_iterator rbegin();
  294. //! @copydoc ::boost::intrusive::bstree::rbegin()const
  295. const_reverse_iterator rbegin() const;
  296. //! @copydoc ::boost::intrusive::bstree::crbegin()const
  297. const_reverse_iterator crbegin() const;
  298. //! @copydoc ::boost::intrusive::bstree::rend()
  299. reverse_iterator rend();
  300. //! @copydoc ::boost::intrusive::bstree::rend()const
  301. const_reverse_iterator rend() const;
  302. //! @copydoc ::boost::intrusive::bstree::crend()const
  303. const_reverse_iterator crend() const;
  304. //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator)
  305. static sgtree_impl &container_from_end_iterator(iterator end_iterator);
  306. //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator)
  307. static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator);
  308. //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator)
  309. static sgtree_impl &container_from_iterator(iterator it);
  310. //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator)
  311. static const sgtree_impl &container_from_iterator(const_iterator it);
  312. //! @copydoc ::boost::intrusive::bstree::key_comp()const
  313. key_compare key_comp() const;
  314. //! @copydoc ::boost::intrusive::bstree::value_comp()const
  315. value_compare value_comp() const;
  316. //! @copydoc ::boost::intrusive::bstree::empty()const
  317. bool empty() const;
  318. //! @copydoc ::boost::intrusive::bstree::size()const
  319. size_type size() const;
  320. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  321. //! @copydoc ::boost::intrusive::bstree::swap
  322. void swap(sgtree_impl& other)
  323. {
  324. //This can throw
  325. this->tree_type::swap(static_cast<tree_type&>(other));
  326. ::boost::adl_move_swap(this->get_alpha_traits(), other.get_alpha_traits());
  327. }
  328. //! @copydoc ::boost::intrusive::bstree::clone_from(const bstree&,Cloner,Disposer)
  329. //! Additional notes: it also copies the alpha factor from the source container.
  330. template <class Cloner, class Disposer>
  331. void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer)
  332. {
  333. tree_type::clone_from(src, cloner, disposer);
  334. this->get_alpha_traits() = src.get_alpha_traits();
  335. }
  336. //! @copydoc ::boost::intrusive::bstree::clone_from(bstree&&,Cloner,Disposer)
  337. //! Additional notes: it also copies the alpha factor from the source container.
  338. template <class Cloner, class Disposer>
  339. void clone_from(BOOST_RV_REF(sgtree_impl) src, Cloner cloner, Disposer disposer)
  340. {
  341. tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner, disposer);
  342. this->get_alpha_traits() = ::boost::move(src.get_alpha_traits());
  343. }
  344. //! @copydoc ::boost::intrusive::bstree::insert_equal(reference)
  345. iterator insert_equal(reference value)
  346. {
  347. node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
  348. if(safemode_or_autounlink)
  349. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
  350. std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
  351. node_ptr p = node_algorithms::insert_equal_upper_bound
  352. (this->tree_type::header_ptr(), to_insert, this->key_node_comp(this->key_comp())
  353. , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size);
  354. this->tree_type::sz_traits().increment();
  355. this->max_tree_size_ = (size_type)max_tree_size;
  356. return iterator(p, this->priv_value_traits_ptr());
  357. }
  358. //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference)
  359. iterator insert_equal(const_iterator hint, reference value)
  360. {
  361. node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
  362. if(safemode_or_autounlink)
  363. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
  364. std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
  365. node_ptr p = node_algorithms::insert_equal
  366. ( this->tree_type::header_ptr(), hint.pointed_node(), to_insert, this->key_node_comp(this->key_comp())
  367. , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size);
  368. this->tree_type::sz_traits().increment();
  369. this->max_tree_size_ = (size_type)max_tree_size;
  370. return iterator(p, this->priv_value_traits_ptr());
  371. }
  372. //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator)
  373. template<class Iterator>
  374. void insert_equal(Iterator b, Iterator e)
  375. {
  376. iterator iend(this->end());
  377. for (; b != e; ++b)
  378. this->insert_equal(iend, *b);
  379. }
  380. //! @copydoc ::boost::intrusive::bstree::insert_unique(reference)
  381. std::pair<iterator, bool> insert_unique(reference value)
  382. {
  383. insert_commit_data commit_data;
  384. std::pair<iterator, bool> ret = this->insert_unique_check
  385. (key_of_value()(value), this->key_comp(), commit_data);
  386. if(!ret.second)
  387. return ret;
  388. return std::pair<iterator, bool> (this->insert_unique_commit(value, commit_data), true);
  389. }
  390. //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference)
  391. iterator insert_unique(const_iterator hint, reference value)
  392. {
  393. insert_commit_data commit_data;
  394. std::pair<iterator, bool> ret = this->insert_unique_check
  395. (hint, key_of_value()(value), this->key_comp(), commit_data);
  396. if(!ret.second)
  397. return ret.first;
  398. return this->insert_unique_commit(value, commit_data);
  399. }
  400. //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
  401. template<class KeyType, class KeyTypeKeyCompare>
  402. BOOST_INTRUSIVE_DOC1ST(std::pair<iterator BOOST_INTRUSIVE_I bool>
  403. , typename detail::disable_if_convertible
  404. <KeyType BOOST_INTRUSIVE_I const_iterator BOOST_INTRUSIVE_I
  405. std::pair<iterator BOOST_INTRUSIVE_I bool> >::type)
  406. insert_unique_check
  407. (const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data)
  408. {
  409. std::pair<node_ptr, bool> ret =
  410. node_algorithms::insert_unique_check
  411. (this->tree_type::header_ptr(), key, this->key_node_comp(comp), commit_data);
  412. return std::pair<iterator, bool>(iterator(ret.first, this->priv_value_traits_ptr()), ret.second);
  413. }
  414. //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
  415. template<class KeyType, class KeyTypeKeyCompare>
  416. std::pair<iterator, bool> insert_unique_check
  417. (const_iterator hint, const KeyType &key
  418. ,KeyTypeKeyCompare comp, insert_commit_data &commit_data)
  419. {
  420. std::pair<node_ptr, bool> ret =
  421. node_algorithms::insert_unique_check
  422. (this->tree_type::header_ptr(), hint.pointed_node(), key, this->key_node_comp(comp), commit_data);
  423. return std::pair<iterator, bool>(iterator(ret.first, this->priv_value_traits_ptr()), ret.second);
  424. }
  425. //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const key_type&,insert_commit_data&)
  426. std::pair<iterator, bool> insert_unique_check
  427. (const key_type &key, insert_commit_data &commit_data)
  428. { return this->insert_unique_check(key, this->key_comp(), commit_data); }
  429. //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
  430. std::pair<iterator, bool> insert_unique_check
  431. (const_iterator hint, const key_type &key, insert_commit_data &commit_data)
  432. { return this->insert_unique_check(hint, key, this->key_comp(), commit_data); }
  433. //! @copydoc ::boost::intrusive::bstree::insert_unique_commit
  434. iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
  435. {
  436. node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
  437. if(safemode_or_autounlink)
  438. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
  439. std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
  440. node_algorithms::insert_unique_commit
  441. ( this->tree_type::header_ptr(), to_insert, commit_data
  442. , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size);
  443. this->tree_type::sz_traits().increment();
  444. this->max_tree_size_ = (size_type)max_tree_size;
  445. return iterator(to_insert, this->priv_value_traits_ptr());
  446. }
  447. //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator)
  448. template<class Iterator>
  449. void insert_unique(Iterator b, Iterator e)
  450. {
  451. if(this->empty()){
  452. iterator iend(this->end());
  453. for (; b != e; ++b)
  454. this->insert_unique(iend, *b);
  455. }
  456. else{
  457. for (; b != e; ++b)
  458. this->insert_unique(*b);
  459. }
  460. }
  461. //! @copydoc ::boost::intrusive::bstree::insert_before
  462. iterator insert_before(const_iterator pos, reference value)
  463. {
  464. node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
  465. if(safemode_or_autounlink)
  466. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
  467. std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
  468. node_ptr p = node_algorithms::insert_before
  469. ( this->tree_type::header_ptr(), pos.pointed_node(), to_insert
  470. , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size);
  471. this->tree_type::sz_traits().increment();
  472. this->max_tree_size_ = (size_type)max_tree_size;
  473. return iterator(p, this->priv_value_traits_ptr());
  474. }
  475. //! @copydoc ::boost::intrusive::bstree::push_back
  476. void push_back(reference value)
  477. {
  478. node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
  479. if(safemode_or_autounlink)
  480. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
  481. std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
  482. node_algorithms::push_back
  483. ( this->tree_type::header_ptr(), to_insert
  484. , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size);
  485. this->tree_type::sz_traits().increment();
  486. this->max_tree_size_ = (size_type)max_tree_size;
  487. }
  488. //! @copydoc ::boost::intrusive::bstree::push_front
  489. void push_front(reference value)
  490. {
  491. node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
  492. if(safemode_or_autounlink)
  493. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
  494. std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
  495. node_algorithms::push_front
  496. ( this->tree_type::header_ptr(), to_insert
  497. , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size);
  498. this->tree_type::sz_traits().increment();
  499. this->max_tree_size_ = (size_type)max_tree_size;
  500. }
  501. //! @copydoc ::boost::intrusive::bstree::erase(const_iterator)
  502. iterator erase(const_iterator i)
  503. {
  504. const_iterator ret(i);
  505. ++ret;
  506. node_ptr to_erase(i.pointed_node());
  507. if(safemode_or_autounlink)
  508. BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase));
  509. std::size_t max_tree_size = this->max_tree_size_;
  510. node_algorithms::erase
  511. ( this->tree_type::header_ptr(), to_erase, (std::size_t)this->size()
  512. , max_tree_size, this->get_alpha_by_max_size_func());
  513. this->max_tree_size_ = (size_type)max_tree_size;
  514. this->tree_type::sz_traits().decrement();
  515. if(safemode_or_autounlink)
  516. node_algorithms::init(to_erase);
  517. return ret.unconst();
  518. }
  519. //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator)
  520. iterator erase(const_iterator b, const_iterator e)
  521. { size_type n; return private_erase(b, e, n); }
  522. //! @copydoc ::boost::intrusive::bstree::erase(const key_type &)
  523. size_type erase(const key_type &key)
  524. { return this->erase(key, this->key_comp()); }
  525. //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyTypeKeyCompare)
  526. template<class KeyType, class KeyTypeKeyCompare>
  527. BOOST_INTRUSIVE_DOC1ST(size_type
  528. , typename detail::disable_if_convertible<KeyTypeKeyCompare BOOST_INTRUSIVE_I const_iterator BOOST_INTRUSIVE_I size_type>::type)
  529. erase(const KeyType& key, KeyTypeKeyCompare comp)
  530. {
  531. std::pair<iterator,iterator> p = this->equal_range(key, comp);
  532. size_type n;
  533. private_erase(p.first, p.second, n);
  534. return n;
  535. }
  536. //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer)
  537. template<class Disposer>
  538. iterator erase_and_dispose(const_iterator i, Disposer disposer)
  539. {
  540. node_ptr to_erase(i.pointed_node());
  541. iterator ret(this->erase(i));
  542. disposer(this->get_value_traits().to_value_ptr(to_erase));
  543. return ret;
  544. }
  545. #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
  546. template<class Disposer>
  547. iterator erase_and_dispose(iterator i, Disposer disposer)
  548. { return this->erase_and_dispose(const_iterator(i), disposer); }
  549. #endif
  550. //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer)
  551. template<class Disposer>
  552. iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer)
  553. { size_type n; return private_erase(b, e, n, disposer); }
  554. //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const key_type &, Disposer)
  555. template<class Disposer>
  556. size_type erase_and_dispose(const key_type &key, Disposer disposer)
  557. {
  558. std::pair<iterator,iterator> p = this->equal_range(key);
  559. size_type n;
  560. private_erase(p.first, p.second, n, disposer);
  561. return n;
  562. }
  563. //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyTypeKeyCompare,Disposer)
  564. template<class KeyType, class KeyTypeKeyCompare, class Disposer>
  565. BOOST_INTRUSIVE_DOC1ST(size_type
  566. , typename detail::disable_if_convertible<KeyTypeKeyCompare BOOST_INTRUSIVE_I const_iterator BOOST_INTRUSIVE_I size_type>::type)
  567. erase_and_dispose(const KeyType& key, KeyTypeKeyCompare comp, Disposer disposer)
  568. {
  569. std::pair<iterator,iterator> p = this->equal_range(key, comp);
  570. size_type n;
  571. private_erase(p.first, p.second, n, disposer);
  572. return n;
  573. }
  574. //! @copydoc ::boost::intrusive::bstree::clear
  575. void clear()
  576. {
  577. tree_type::clear();
  578. this->max_tree_size_ = 0;
  579. }
  580. //! @copydoc ::boost::intrusive::bstree::clear_and_dispose
  581. template<class Disposer>
  582. void clear_and_dispose(Disposer disposer)
  583. {
  584. tree_type::clear_and_dispose(disposer);
  585. this->max_tree_size_ = 0;
  586. }
  587. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  588. //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const
  589. size_type count(const key_type &key) const;
  590. //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyTypeKeyCompare)const
  591. template<class KeyType, class KeyTypeKeyCompare>
  592. size_type count(const KeyType& key, KeyTypeKeyCompare comp) const;
  593. //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)
  594. iterator lower_bound(const key_type &key);
  595. //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)
  596. template<class KeyType, class KeyTypeKeyCompare>
  597. iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp);
  598. //! @copydoc ::boost::intrusive::bstree::lower_bound(const key_type &)const
  599. const_iterator lower_bound(const key_type &key) const;
  600. //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyTypeKeyCompare)const
  601. template<class KeyType, class KeyTypeKeyCompare>
  602. const_iterator lower_bound(const KeyType& key, KeyTypeKeyCompare comp) const;
  603. //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)
  604. iterator upper_bound(const key_type &key);
  605. //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)
  606. template<class KeyType, class KeyTypeKeyCompare>
  607. iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp);
  608. //! @copydoc ::boost::intrusive::bstree::upper_bound(const key_type &)const
  609. const_iterator upper_bound(const key_type &key) const;
  610. //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyTypeKeyCompare)const
  611. template<class KeyType, class KeyTypeKeyCompare>
  612. const_iterator upper_bound(const KeyType& key, KeyTypeKeyCompare comp) const;
  613. //! @copydoc ::boost::intrusive::bstree::find(const key_type &)
  614. iterator find(const key_type &key);
  615. //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)
  616. template<class KeyType, class KeyTypeKeyCompare>
  617. iterator find(const KeyType& key, KeyTypeKeyCompare comp);
  618. //! @copydoc ::boost::intrusive::bstree::find(const key_type &)const
  619. const_iterator find(const key_type &key) const;
  620. //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyTypeKeyCompare)const
  621. template<class KeyType, class KeyTypeKeyCompare>
  622. const_iterator find(const KeyType& key, KeyTypeKeyCompare comp) const;
  623. //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)
  624. std::pair<iterator,iterator> equal_range(const key_type &key);
  625. //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)
  626. template<class KeyType, class KeyTypeKeyCompare>
  627. std::pair<iterator,iterator> equal_range(const KeyType& key, KeyTypeKeyCompare comp);
  628. //! @copydoc ::boost::intrusive::bstree::equal_range(const key_type &)const
  629. std::pair<const_iterator, const_iterator>
  630. equal_range(const key_type &key) const;
  631. //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyTypeKeyCompare)const
  632. template<class KeyType, class KeyTypeKeyCompare>
  633. std::pair<const_iterator, const_iterator>
  634. equal_range(const KeyType& key, KeyTypeKeyCompare comp) const;
  635. //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)
  636. std::pair<iterator,iterator> bounded_range
  637. (const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed);
  638. //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)
  639. template<class KeyType, class KeyTypeKeyCompare>
  640. std::pair<iterator,iterator> bounded_range
  641. (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed);
  642. //! @copydoc ::boost::intrusive::bstree::bounded_range(const key_type &,const key_type &,bool,bool)const
  643. std::pair<const_iterator, const_iterator>
  644. bounded_range(const key_type &lower_key, const key_type &upper_key, bool left_closed, bool right_closed) const;
  645. //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyTypeKeyCompare,bool,bool)const
  646. template<class KeyType, class KeyTypeKeyCompare>
  647. std::pair<const_iterator, const_iterator> bounded_range
  648. (const KeyType& lower_key, const KeyType& upper_key, KeyTypeKeyCompare comp, bool left_closed, bool right_closed) const;
  649. //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference)
  650. static iterator s_iterator_to(reference value);
  651. //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference)
  652. static const_iterator s_iterator_to(const_reference value);
  653. //! @copydoc ::boost::intrusive::bstree::iterator_to(reference)
  654. iterator iterator_to(reference value);
  655. //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const
  656. const_iterator iterator_to(const_reference value) const;
  657. //! @copydoc ::boost::intrusive::bstree::init_node(reference)
  658. static void init_node(reference value);
  659. //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance
  660. pointer unlink_leftmost_without_rebalance();
  661. //! @copydoc ::boost::intrusive::bstree::replace_node
  662. void replace_node(iterator replace_this, reference with_this);
  663. //! @copydoc ::boost::intrusive::bstree::remove_node
  664. void remove_node(reference value);
  665. //! @copydoc ::boost::intrusive::bstree::rebalance
  666. void rebalance();
  667. //! @copydoc ::boost::intrusive::bstree::rebalance_subtree
  668. iterator rebalance_subtree(iterator root);
  669. friend bool operator< (const sgtree_impl &x, const sgtree_impl &y);
  670. friend bool operator==(const sgtree_impl &x, const sgtree_impl &y);
  671. friend bool operator!= (const sgtree_impl &x, const sgtree_impl &y);
  672. friend bool operator>(const sgtree_impl &x, const sgtree_impl &y);
  673. friend bool operator<=(const sgtree_impl &x, const sgtree_impl &y);
  674. friend bool operator>=(const sgtree_impl &x, const sgtree_impl &y);
  675. friend void swap(sgtree_impl &x, sgtree_impl &y);
  676. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  677. //! <b>Returns</b>: The balance factor (alpha) used in this tree
  678. //!
  679. //! <b>Throws</b>: Nothing.
  680. //!
  681. //! <b>Complexity</b>: Constant.
  682. float balance_factor() const
  683. { return this->get_alpha_traits().get_alpha(); }
  684. //! <b>Requires</b>: new_alpha must be a value between 0.5 and 1.0
  685. //!
  686. //! <b>Effects</b>: Establishes a new balance factor (alpha) and rebalances
  687. //! the tree if the new balance factor is stricter (less) than the old factor.
  688. //!
  689. //! <b>Throws</b>: Nothing.
  690. //!
  691. //! <b>Complexity</b>: Linear to the elements in the subtree.
  692. void balance_factor(float new_alpha)
  693. {
  694. //The alpha factor CAN't be changed if the fixed, floating operation-less
  695. //1/sqrt(2) alpha factor option is activated
  696. BOOST_STATIC_ASSERT((floating_point));
  697. BOOST_INTRUSIVE_INVARIANT_ASSERT((new_alpha > 0.5f && new_alpha < 1.0f));
  698. if(new_alpha >= 0.5f && new_alpha < 1.0f){
  699. float old_alpha = this->get_alpha_traits().get_alpha();
  700. this->get_alpha_traits().set_alpha(new_alpha);
  701. if(new_alpha < old_alpha){
  702. this->max_tree_size_ = this->size();
  703. this->rebalance();
  704. }
  705. }
  706. }
  707. /// @cond
  708. private:
  709. template<class Disposer>
  710. iterator private_erase(const_iterator b, const_iterator e, size_type &n, Disposer disposer)
  711. {
  712. for(n = 0; b != e; ++n)
  713. this->erase_and_dispose(b++, disposer);
  714. return b.unconst();
  715. }
  716. iterator private_erase(const_iterator b, const_iterator e, size_type &n)
  717. {
  718. for(n = 0; b != e; ++n)
  719. this->erase(b++);
  720. return b.unconst();
  721. }
  722. /// @endcond
  723. };
  724. //! Helper metafunction to define a \c sgtree that yields to the same type when the
  725. //! same options (either explicitly or implicitly) are used.
  726. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  727. template<class T, class ...Options>
  728. #else
  729. template<class T, class O1 = void, class O2 = void
  730. , class O3 = void, class O4 = void
  731. , class O5 = void, class O6 = void>
  732. #endif
  733. struct make_sgtree
  734. {
  735. /// @cond
  736. typedef typename pack_options
  737. < sgtree_defaults,
  738. #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  739. O1, O2, O3, O4, O5, O6
  740. #else
  741. Options...
  742. #endif
  743. >::type packed_options;
  744. typedef typename detail::get_value_traits
  745. <T, typename packed_options::proto_value_traits>::type value_traits;
  746. typedef sgtree_impl
  747. < value_traits
  748. , typename packed_options::key_of_value
  749. , typename packed_options::compare
  750. , typename packed_options::size_type
  751. , packed_options::floating_point
  752. , typename packed_options::header_holder_type
  753. > implementation_defined;
  754. /// @endcond
  755. typedef implementation_defined type;
  756. };
  757. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  758. #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  759. template<class T, class O1, class O2, class O3, class O4, class O5, class O6>
  760. #else
  761. template<class T, class ...Options>
  762. #endif
  763. class sgtree
  764. : public make_sgtree<T,
  765. #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  766. O1, O2, O3, O4, O5, O6
  767. #else
  768. Options...
  769. #endif
  770. >::type
  771. {
  772. typedef typename make_sgtree
  773. <T,
  774. #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
  775. O1, O2, O3, O4, O5, O6
  776. #else
  777. Options...
  778. #endif
  779. >::type Base;
  780. BOOST_MOVABLE_BUT_NOT_COPYABLE(sgtree)
  781. public:
  782. typedef typename Base::key_compare key_compare;
  783. typedef typename Base::value_traits value_traits;
  784. typedef typename Base::iterator iterator;
  785. typedef typename Base::const_iterator const_iterator;
  786. typedef typename Base::reverse_iterator reverse_iterator;
  787. typedef typename Base::const_reverse_iterator const_reverse_iterator;
  788. //Assert if passed value traits are compatible with the type
  789. BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
  790. sgtree()
  791. : Base()
  792. {}
  793. explicit sgtree(const key_compare &cmp, const value_traits &v_traits = value_traits())
  794. : Base(cmp, v_traits)
  795. {}
  796. template<class Iterator>
  797. sgtree( bool unique, Iterator b, Iterator e
  798. , const key_compare &cmp = key_compare()
  799. , const value_traits &v_traits = value_traits())
  800. : Base(unique, b, e, cmp, v_traits)
  801. {}
  802. sgtree(BOOST_RV_REF(sgtree) x)
  803. : Base(BOOST_MOVE_BASE(Base, x))
  804. {}
  805. sgtree& operator=(BOOST_RV_REF(sgtree) x)
  806. { return static_cast<sgtree &>(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); }
  807. template <class Cloner, class Disposer>
  808. void clone_from(const sgtree &src, Cloner cloner, Disposer disposer)
  809. { Base::clone_from(src, cloner, disposer); }
  810. template <class Cloner, class Disposer>
  811. void clone_from(BOOST_RV_REF(sgtree) src, Cloner cloner, Disposer disposer)
  812. { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); }
  813. static sgtree &container_from_end_iterator(iterator end_iterator)
  814. { return static_cast<sgtree &>(Base::container_from_end_iterator(end_iterator)); }
  815. static const sgtree &container_from_end_iterator(const_iterator end_iterator)
  816. { return static_cast<const sgtree &>(Base::container_from_end_iterator(end_iterator)); }
  817. static sgtree &container_from_iterator(iterator it)
  818. { return static_cast<sgtree &>(Base::container_from_iterator(it)); }
  819. static const sgtree &container_from_iterator(const_iterator it)
  820. { return static_cast<const sgtree &>(Base::container_from_iterator(it)); }
  821. };
  822. #endif
  823. } //namespace intrusive
  824. } //namespace boost
  825. #include <boost/intrusive/detail/config_end.hpp>
  826. #endif //BOOST_INTRUSIVE_SGTREE_HPP