stable_heap.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. // boost heap: helper classes for stable priority queues
  2. //
  3. // Copyright (C) 2010 Tim Blechmann
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
  9. #define BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
  10. #include <limits>
  11. #include <stdexcept>
  12. #include <utility>
  13. #include <boost/cstdint.hpp>
  14. #include <boost/throw_exception.hpp>
  15. #include <boost/iterator/iterator_adaptor.hpp>
  16. #include <boost/heap/policies.hpp>
  17. #include <boost/heap/heap_merge.hpp>
  18. namespace boost {
  19. namespace heap {
  20. namespace detail {
  21. template<bool ConstantSize, class SizeType>
  22. struct size_holder
  23. {
  24. static const bool constant_time_size = ConstantSize;
  25. typedef SizeType size_type;
  26. size_holder(void):
  27. size_(0)
  28. {}
  29. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  30. size_holder(size_holder && rhs):
  31. size_(rhs.size_)
  32. {
  33. rhs.size_ = 0;
  34. }
  35. size_holder(size_holder const & rhs):
  36. size_(rhs.size_)
  37. {}
  38. size_holder & operator=(size_holder && rhs)
  39. {
  40. size_ = rhs.size_;
  41. rhs.size_ = 0;
  42. return *this;
  43. }
  44. size_holder & operator=(size_holder const & rhs)
  45. {
  46. size_ = rhs.size_;
  47. return *this;
  48. }
  49. #endif
  50. SizeType get_size() const
  51. { return size_; }
  52. void set_size(SizeType size)
  53. { size_ = size; }
  54. void decrement()
  55. { --size_; }
  56. void increment()
  57. { ++size_; }
  58. void add(SizeType value)
  59. { size_ += value; }
  60. void sub(SizeType value)
  61. { size_ -= value; }
  62. void swap(size_holder & rhs)
  63. { std::swap(size_, rhs.size_); }
  64. SizeType size_;
  65. };
  66. template<class SizeType>
  67. struct size_holder<false, SizeType>
  68. {
  69. static const bool constant_time_size = false;
  70. typedef SizeType size_type;
  71. size_holder(void)
  72. {}
  73. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  74. size_holder(size_holder && rhs)
  75. {}
  76. size_holder(size_holder const & rhs)
  77. {}
  78. size_holder & operator=(size_holder && rhs)
  79. {
  80. return *this;
  81. }
  82. size_holder & operator=(size_holder const & rhs)
  83. {
  84. return *this;
  85. }
  86. #endif
  87. size_type get_size() const
  88. { return 0; }
  89. void set_size(size_type)
  90. {}
  91. void decrement()
  92. {}
  93. void increment()
  94. {}
  95. void add(SizeType value)
  96. {}
  97. void sub(SizeType value)
  98. {}
  99. void swap(size_holder & rhs)
  100. {}
  101. };
  102. // note: MSVC does not implement lookup correctly, we therefore have to place the Cmp object as member inside the
  103. // struct. of course, this prevents EBO and significantly reduces the readability of this code
  104. template <typename T,
  105. typename Cmp,
  106. bool constant_time_size,
  107. typename StabilityCounterType = boost::uintmax_t,
  108. bool stable = false
  109. >
  110. struct heap_base:
  111. #ifndef BOOST_MSVC
  112. Cmp,
  113. #endif
  114. size_holder<constant_time_size, size_t>
  115. {
  116. typedef StabilityCounterType stability_counter_type;
  117. typedef T value_type;
  118. typedef T internal_type;
  119. typedef size_holder<constant_time_size, size_t> size_holder_type;
  120. typedef Cmp value_compare;
  121. typedef Cmp internal_compare;
  122. static const bool is_stable = stable;
  123. #ifdef BOOST_MSVC
  124. Cmp cmp_;
  125. #endif
  126. heap_base (Cmp const & cmp = Cmp()):
  127. #ifndef BOOST_MSVC
  128. Cmp(cmp)
  129. #else
  130. cmp_(cmp)
  131. #endif
  132. {}
  133. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  134. heap_base(heap_base && rhs):
  135. #ifndef BOOST_MSVC
  136. Cmp(std::move(static_cast<Cmp&>(rhs))),
  137. #else
  138. cmp_(std::move(rhs.cmp_)),
  139. #endif
  140. size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))
  141. {}
  142. heap_base(heap_base const & rhs):
  143. #ifndef BOOST_MSVC
  144. Cmp(static_cast<Cmp const &>(rhs)),
  145. #else
  146. cmp_(rhs.value_comp()),
  147. #endif
  148. size_holder_type(static_cast<size_holder_type const &>(rhs))
  149. {}
  150. heap_base & operator=(heap_base && rhs)
  151. {
  152. value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
  153. size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
  154. return *this;
  155. }
  156. heap_base & operator=(heap_base const & rhs)
  157. {
  158. value_comp_ref().operator=(rhs.value_comp());
  159. size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
  160. return *this;
  161. }
  162. #endif
  163. bool operator()(internal_type const & lhs, internal_type const & rhs) const
  164. {
  165. return value_comp().operator()(lhs, rhs);
  166. }
  167. internal_type make_node(T const & val)
  168. {
  169. return val;
  170. }
  171. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  172. T && make_node(T && val)
  173. {
  174. return std::forward<T>(val);
  175. }
  176. #endif
  177. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  178. template <class... Args>
  179. internal_type make_node(Args && ... val)
  180. {
  181. return internal_type(std::forward<Args>(val)...);
  182. }
  183. #endif
  184. static T & get_value(internal_type & val)
  185. {
  186. return val;
  187. }
  188. static T const & get_value(internal_type const & val)
  189. {
  190. return val;
  191. }
  192. Cmp const & value_comp(void) const
  193. {
  194. #ifndef BOOST_MSVC
  195. return *this;
  196. #else
  197. return cmp_;
  198. #endif
  199. }
  200. Cmp const & get_internal_cmp(void) const
  201. {
  202. return value_comp();
  203. }
  204. void swap(heap_base & rhs)
  205. {
  206. std::swap(value_comp_ref(), rhs.value_comp_ref());
  207. size_holder<constant_time_size, size_t>::swap(rhs);
  208. }
  209. stability_counter_type get_stability_count(void) const
  210. {
  211. return 0;
  212. }
  213. void set_stability_count(stability_counter_type)
  214. {}
  215. template <typename Heap1, typename Heap2>
  216. friend struct heap_merge_emulate;
  217. private:
  218. Cmp & value_comp_ref(void)
  219. {
  220. #ifndef BOOST_MSVC
  221. return *this;
  222. #else
  223. return cmp_;
  224. #endif
  225. }
  226. };
  227. template <typename T,
  228. typename Cmp,
  229. bool constant_time_size,
  230. typename StabilityCounterType
  231. >
  232. struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
  233. #ifndef BOOST_MSVC
  234. Cmp,
  235. #endif
  236. size_holder<constant_time_size, size_t>
  237. {
  238. typedef StabilityCounterType stability_counter_type;
  239. typedef T value_type;
  240. struct internal_type
  241. {
  242. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  243. template <class ...Args>
  244. internal_type(stability_counter_type cnt, Args && ... args):
  245. first(std::forward<Args>(args)...), second(cnt)
  246. {}
  247. #endif
  248. internal_type(stability_counter_type const & cnt, T const & value):
  249. first(value), second(cnt)
  250. {}
  251. T first;
  252. stability_counter_type second;
  253. };
  254. typedef size_holder<constant_time_size, size_t> size_holder_type;
  255. typedef Cmp value_compare;
  256. #ifdef BOOST_MSVC
  257. Cmp cmp_;
  258. #endif
  259. heap_base (Cmp const & cmp = Cmp()):
  260. #ifndef BOOST_MSVC
  261. Cmp(cmp),
  262. #else
  263. cmp_(cmp),
  264. #endif
  265. counter_(0)
  266. {}
  267. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  268. heap_base(heap_base && rhs):
  269. #ifndef BOOST_MSVC
  270. Cmp(std::move(static_cast<Cmp&>(rhs))),
  271. #else
  272. cmp_(std::move(rhs.cmp_)),
  273. #endif
  274. size_holder_type(std::move(static_cast<size_holder_type&>(rhs))), counter_(rhs.counter_)
  275. {
  276. rhs.counter_ = 0;
  277. }
  278. heap_base(heap_base const & rhs):
  279. #ifndef BOOST_MSVC
  280. Cmp(static_cast<Cmp const&>(rhs)),
  281. #else
  282. cmp_(rhs.value_comp()),
  283. #endif
  284. size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)
  285. {}
  286. heap_base & operator=(heap_base && rhs)
  287. {
  288. value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
  289. size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
  290. counter_ = rhs.counter_;
  291. rhs.counter_ = 0;
  292. return *this;
  293. }
  294. heap_base & operator=(heap_base const & rhs)
  295. {
  296. value_comp_ref().operator=(rhs.value_comp());
  297. size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
  298. counter_ = rhs.counter_;
  299. return *this;
  300. }
  301. #endif
  302. bool operator()(internal_type const & lhs, internal_type const & rhs) const
  303. {
  304. return get_internal_cmp()(lhs, rhs);
  305. }
  306. bool operator()(T const & lhs, T const & rhs) const
  307. {
  308. return value_comp()(lhs, rhs);
  309. }
  310. internal_type make_node(T const & val)
  311. {
  312. stability_counter_type count = ++counter_;
  313. if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
  314. BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
  315. return internal_type(count, val);
  316. }
  317. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  318. template <class... Args>
  319. internal_type make_node(Args&&... args)
  320. {
  321. stability_counter_type count = ++counter_;
  322. if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
  323. BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
  324. return internal_type (count, std::forward<Args>(args)...);
  325. }
  326. #endif
  327. static T & get_value(internal_type & val)
  328. {
  329. return val.first;
  330. }
  331. static T const & get_value(internal_type const & val)
  332. {
  333. return val.first;
  334. }
  335. Cmp const & value_comp(void) const
  336. {
  337. #ifndef BOOST_MSVC
  338. return *this;
  339. #else
  340. return cmp_;
  341. #endif
  342. }
  343. struct internal_compare:
  344. Cmp
  345. {
  346. internal_compare(Cmp const & cmp = Cmp()):
  347. Cmp(cmp)
  348. {}
  349. bool operator()(internal_type const & lhs, internal_type const & rhs) const
  350. {
  351. if (Cmp::operator()(lhs.first, rhs.first))
  352. return true;
  353. if (Cmp::operator()(rhs.first, lhs.first))
  354. return false;
  355. return lhs.second > rhs.second;
  356. }
  357. };
  358. internal_compare get_internal_cmp(void) const
  359. {
  360. return internal_compare(value_comp());
  361. }
  362. void swap(heap_base & rhs)
  363. {
  364. #ifndef BOOST_MSVC
  365. std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
  366. #else
  367. std::swap(cmp_, rhs.cmp_);
  368. #endif
  369. std::swap(counter_, rhs.counter_);
  370. size_holder<constant_time_size, size_t>::swap(rhs);
  371. }
  372. stability_counter_type get_stability_count(void) const
  373. {
  374. return counter_;
  375. }
  376. void set_stability_count(stability_counter_type new_count)
  377. {
  378. counter_ = new_count;
  379. }
  380. template <typename Heap1, typename Heap2>
  381. friend struct heap_merge_emulate;
  382. private:
  383. Cmp & value_comp_ref(void)
  384. {
  385. #ifndef BOOST_MSVC
  386. return *this;
  387. #else
  388. return cmp_;
  389. #endif
  390. }
  391. stability_counter_type counter_;
  392. };
  393. template <typename node_pointer,
  394. typename extractor,
  395. typename reference
  396. >
  397. struct node_handle
  398. {
  399. explicit node_handle(node_pointer n = 0):
  400. node_(n)
  401. {}
  402. reference operator*() const
  403. {
  404. return extractor::get_value(node_->value);
  405. }
  406. bool operator==(node_handle const & rhs) const
  407. {
  408. return node_ == rhs.node_;
  409. }
  410. bool operator!=(node_handle const & rhs) const
  411. {
  412. return node_ != rhs.node_;
  413. }
  414. node_pointer node_;
  415. };
  416. template <typename value_type,
  417. typename internal_type,
  418. typename extractor
  419. >
  420. struct value_extractor
  421. {
  422. value_type const & operator()(internal_type const & data) const
  423. {
  424. return extractor::get_value(data);
  425. }
  426. };
  427. template <typename T,
  428. typename ContainerIterator,
  429. typename Extractor>
  430. class stable_heap_iterator:
  431. public boost::iterator_adaptor<stable_heap_iterator<T, ContainerIterator, Extractor>,
  432. ContainerIterator,
  433. T const,
  434. boost::random_access_traversal_tag>
  435. {
  436. typedef boost::iterator_adaptor<stable_heap_iterator,
  437. ContainerIterator,
  438. T const,
  439. boost::random_access_traversal_tag> super_t;
  440. public:
  441. stable_heap_iterator(void):
  442. super_t(0)
  443. {}
  444. explicit stable_heap_iterator(ContainerIterator const & it):
  445. super_t(it)
  446. {}
  447. private:
  448. friend class boost::iterator_core_access;
  449. T const & dereference() const
  450. {
  451. return Extractor::get_value(*super_t::base());
  452. }
  453. };
  454. template <typename T, typename Parspec, bool constant_time_size>
  455. struct make_heap_base
  456. {
  457. typedef typename parameter::binding<Parspec, tag::compare, std::less<T> >::type compare_argument;
  458. typedef typename parameter::binding<Parspec, tag::allocator, std::allocator<T> >::type allocator_argument;
  459. typedef typename parameter::binding<Parspec, tag::stability_counter_type, boost::uintmax_t >::type stability_counter_type;
  460. static const bool is_stable = extract_stable<Parspec>::value;
  461. typedef heap_base<T, compare_argument, constant_time_size, stability_counter_type, is_stable> type;
  462. };
  463. template <typename Alloc>
  464. struct extract_allocator_types
  465. {
  466. typedef typename Alloc::size_type size_type;
  467. typedef typename Alloc::difference_type difference_type;
  468. typedef typename Alloc::reference reference;
  469. typedef typename Alloc::const_reference const_reference;
  470. typedef typename Alloc::pointer pointer;
  471. typedef typename Alloc::const_pointer const_pointer;
  472. };
  473. } /* namespace detail */
  474. } /* namespace heap */
  475. } /* namespace boost */
  476. #endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */