1 // boost heap: helper classes for stable priority queues
3 // Copyright (C) 2010 Tim Blechmann
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)
9 #ifndef BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
10 #define BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
16 #include <boost/cstdint.hpp>
17 #include <boost/throw_exception.hpp>
18 #include <boost/iterator/iterator_adaptor.hpp>
20 #include <boost/heap/policies.hpp>
21 #include <boost/heap/heap_merge.hpp>
23 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
24 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
30 template<bool ConstantSize, class SizeType>
33 static const bool constant_time_size = ConstantSize;
34 typedef SizeType size_type;
36 size_holder(void) BOOST_NOEXCEPT:
40 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
41 size_holder(size_holder && rhs) BOOST_NOEXCEPT:
47 size_holder(size_holder const & rhs) BOOST_NOEXCEPT:
51 size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT
58 size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT
65 SizeType get_size() const BOOST_NOEXCEPT
68 void set_size(SizeType size) BOOST_NOEXCEPT
71 void decrement() BOOST_NOEXCEPT
74 void increment() BOOST_NOEXCEPT
77 void add(SizeType value) BOOST_NOEXCEPT
80 void sub(SizeType value) BOOST_NOEXCEPT
83 void swap(size_holder & rhs) BOOST_NOEXCEPT
84 { std::swap(size_, rhs.size_); }
89 template<class SizeType>
90 struct size_holder<false, SizeType>
92 static const bool constant_time_size = false;
93 typedef SizeType size_type;
95 size_holder(void) BOOST_NOEXCEPT
98 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
99 size_holder(size_holder && rhs) BOOST_NOEXCEPT
102 size_holder(size_holder const & rhs) BOOST_NOEXCEPT
105 size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT
110 size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT
116 size_type get_size() const BOOST_NOEXCEPT
119 void set_size(size_type) BOOST_NOEXCEPT
122 void decrement() BOOST_NOEXCEPT
125 void increment() BOOST_NOEXCEPT
128 void add(SizeType /*value*/) BOOST_NOEXCEPT
131 void sub(SizeType /*value*/) BOOST_NOEXCEPT
134 void swap(size_holder & /*rhs*/) BOOST_NOEXCEPT
138 // note: MSVC does not implement lookup correctly, we therefore have to place the Cmp object as member inside the
139 // struct. of course, this prevents EBO and significantly reduces the readability of this code
140 template <typename T,
142 bool constant_time_size,
143 typename StabilityCounterType = boost::uintmax_t,
150 size_holder<constant_time_size, size_t>
152 typedef StabilityCounterType stability_counter_type;
153 typedef T value_type;
154 typedef T internal_type;
155 typedef size_holder<constant_time_size, size_t> size_holder_type;
156 typedef Cmp value_compare;
157 typedef Cmp internal_compare;
158 static const bool is_stable = stable;
164 heap_base (Cmp const & cmp = Cmp()):
172 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
173 heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):
175 Cmp(std::move(static_cast<Cmp&>(rhs))),
177 cmp_(std::move(rhs.cmp_)),
179 size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))
182 heap_base(heap_base const & rhs):
184 Cmp(static_cast<Cmp const &>(rhs)),
186 cmp_(rhs.value_comp()),
188 size_holder_type(static_cast<size_holder_type const &>(rhs))
191 heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
193 value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
194 size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
198 heap_base & operator=(heap_base const & rhs)
200 value_comp_ref().operator=(rhs.value_comp());
201 size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
206 bool operator()(internal_type const & lhs, internal_type const & rhs) const
208 return value_comp().operator()(lhs, rhs);
211 internal_type make_node(T const & val)
216 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
217 T && make_node(T && val)
219 return std::forward<T>(val);
223 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
224 template <class... Args>
225 internal_type make_node(Args && ... val)
227 return internal_type(std::forward<Args>(val)...);
231 static T & get_value(internal_type & val) BOOST_NOEXCEPT
236 static T const & get_value(internal_type const & val) BOOST_NOEXCEPT
241 Cmp const & value_comp(void) const BOOST_NOEXCEPT
250 Cmp const & get_internal_cmp(void) const BOOST_NOEXCEPT
255 void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)
257 std::swap(value_comp_ref(), rhs.value_comp_ref());
258 size_holder<constant_time_size, size_t>::swap(rhs);
261 stability_counter_type get_stability_count(void) const BOOST_NOEXCEPT
266 void set_stability_count(stability_counter_type) BOOST_NOEXCEPT
269 template <typename Heap1, typename Heap2>
270 friend struct heap_merge_emulate;
273 Cmp & value_comp_ref(void)
284 template <typename T,
286 bool constant_time_size,
287 typename StabilityCounterType
289 struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
293 size_holder<constant_time_size, size_t>
295 typedef StabilityCounterType stability_counter_type;
296 typedef T value_type;
300 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
301 template <class ...Args>
302 internal_type(stability_counter_type cnt, Args && ... args):
303 first(std::forward<Args>(args)...), second(cnt)
307 internal_type(stability_counter_type const & cnt, T const & value):
308 first(value), second(cnt)
312 stability_counter_type second;
315 typedef size_holder<constant_time_size, size_t> size_holder_type;
316 typedef Cmp value_compare;
322 heap_base (Cmp const & cmp = Cmp()):
331 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
332 heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):
334 Cmp(std::move(static_cast<Cmp&>(rhs))),
336 cmp_(std::move(rhs.cmp_)),
338 size_holder_type(std::move(static_cast<size_holder_type&>(rhs))), counter_(rhs.counter_)
343 heap_base(heap_base const & rhs):
345 Cmp(static_cast<Cmp const&>(rhs)),
347 cmp_(rhs.value_comp()),
349 size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)
352 heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
354 value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
355 size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
357 counter_ = rhs.counter_;
362 heap_base & operator=(heap_base const & rhs)
364 value_comp_ref().operator=(rhs.value_comp());
365 size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
367 counter_ = rhs.counter_;
372 bool operator()(internal_type const & lhs, internal_type const & rhs) const
374 return get_internal_cmp()(lhs, rhs);
377 bool operator()(T const & lhs, T const & rhs) const
379 return value_comp()(lhs, rhs);
382 internal_type make_node(T const & val)
384 stability_counter_type count = ++counter_;
385 if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
386 BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
387 return internal_type(count, val);
390 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
391 template <class... Args>
392 internal_type make_node(Args&&... args)
394 stability_counter_type count = ++counter_;
395 if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
396 BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
397 return internal_type (count, std::forward<Args>(args)...);
401 static T & get_value(internal_type & val) BOOST_NOEXCEPT
406 static T const & get_value(internal_type const & val) BOOST_NOEXCEPT
411 Cmp const & value_comp(void) const BOOST_NOEXCEPT
420 struct internal_compare:
423 internal_compare(Cmp const & cmp = Cmp()):
427 bool operator()(internal_type const & lhs, internal_type const & rhs) const
429 if (Cmp::operator()(lhs.first, rhs.first))
432 if (Cmp::operator()(rhs.first, lhs.first))
435 return lhs.second > rhs.second;
439 internal_compare get_internal_cmp(void) const
441 return internal_compare(value_comp());
444 void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)
447 std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
449 std::swap(cmp_, rhs.cmp_);
451 std::swap(counter_, rhs.counter_);
452 size_holder<constant_time_size, size_t>::swap(rhs);
455 stability_counter_type get_stability_count(void) const
460 void set_stability_count(stability_counter_type new_count)
462 counter_ = new_count;
465 template <typename Heap1, typename Heap2>
466 friend struct heap_merge_emulate;
469 Cmp & value_comp_ref(void) BOOST_NOEXCEPT
478 stability_counter_type counter_;
481 template <typename node_pointer,
487 explicit node_handle(node_pointer n = 0):
491 reference operator*() const
493 return extractor::get_value(node_->value);
496 bool operator==(node_handle const & rhs) const
498 return node_ == rhs.node_;
501 bool operator!=(node_handle const & rhs) const
503 return node_ != rhs.node_;
509 template <typename value_type,
510 typename internal_type,
513 struct value_extractor
515 value_type const & operator()(internal_type const & data) const
517 return extractor::get_value(data);
521 template <typename T,
522 typename ContainerIterator,
524 class stable_heap_iterator:
525 public boost::iterator_adaptor<stable_heap_iterator<T, ContainerIterator, Extractor>,
528 boost::random_access_traversal_tag>
530 typedef boost::iterator_adaptor<stable_heap_iterator,
533 boost::random_access_traversal_tag> super_t;
536 stable_heap_iterator(void):
540 explicit stable_heap_iterator(ContainerIterator const & it):
545 friend class boost::iterator_core_access;
547 T const & dereference() const
549 return Extractor::get_value(*super_t::base());
553 template <typename T, typename Parspec, bool constant_time_size>
554 struct make_heap_base
556 typedef typename parameter::binding<Parspec, tag::compare, std::less<T> >::type compare_argument;
557 typedef typename parameter::binding<Parspec, tag::allocator, std::allocator<T> >::type allocator_argument;
558 typedef typename parameter::binding<Parspec, tag::stability_counter_type, boost::uintmax_t >::type stability_counter_type;
560 static const bool is_stable = extract_stable<Parspec>::value;
562 typedef heap_base<T, compare_argument, constant_time_size, stability_counter_type, is_stable> type;
566 template <typename Alloc>
567 struct extract_allocator_types
569 typedef typename Alloc::size_type size_type;
570 typedef typename Alloc::difference_type difference_type;
571 typedef typename Alloc::reference reference;
572 typedef typename Alloc::const_reference const_reference;
573 typedef typename Alloc::pointer pointer;
574 typedef typename Alloc::const_pointer const_pointer;
578 } /* namespace detail */
579 } /* namespace heap */
580 } /* namespace boost */
582 #endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */