// boost heap: helper classes for stable priority queues // // Copyright (C) 2010 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_HEAP_DETAIL_STABLE_HEAP_HPP #define BOOST_HEAP_DETAIL_STABLE_HEAP_HPP #include #include #include #include #include #include #include #include namespace boost { namespace heap { namespace detail { template struct size_holder { static const bool constant_time_size = ConstantSize; typedef SizeType size_type; size_holder(void): size_(0) {} #ifdef BOOST_HAS_RVALUE_REFS size_holder(size_holder && rhs): size_(rhs.size_) { rhs.size_ = 0; } size_holder(size_holder const & rhs): size_(rhs.size_) {} size_holder & operator=(size_holder && rhs) { size_ = rhs.size_; rhs.size_ = 0; return *this; } size_holder & operator=(size_holder const & rhs) { size_ = rhs.size_; return *this; } #endif SizeType get_size() const { return size_; } void set_size(SizeType size) { size_ = size; } void decrement() { --size_; } void increment() { ++size_; } void add(SizeType value) { size_ += value; } void sub(SizeType value) { size_ -= value; } void swap(size_holder & rhs) { std::swap(size_, rhs.size_); } SizeType size_; }; template struct size_holder { static const bool constant_time_size = false; typedef SizeType size_type; size_holder(void) {} #ifdef BOOST_HAS_RVALUE_REFS size_holder(size_holder && rhs) {} size_holder(size_holder const & rhs) {} size_holder & operator=(size_holder && rhs) { return *this; } size_holder & operator=(size_holder const & rhs) { return *this; } #endif size_type get_size() const { return 0; } void set_size(size_type) {} void decrement() {} void increment() {} void add(SizeType value) {} void sub(SizeType value) {} void swap(size_holder & rhs) {} }; template struct heap_base: Cmp, size_holder { typedef StabilityCounterType stability_counter_type; typedef T value_type; typedef T internal_type; typedef size_holder size_holder_type; typedef Cmp value_compare; typedef Cmp internal_compare; static const bool is_stable = stable; heap_base (Cmp const & cmp = Cmp()): Cmp(cmp) {} #ifdef BOOST_HAS_RVALUE_REFS heap_base(heap_base && rhs): Cmp(std::move(static_cast(rhs))), size_holder_type(std::move(static_cast(rhs))) {} heap_base(heap_base const & rhs): Cmp(static_cast(rhs)), size_holder_type(static_cast(rhs)) {} heap_base & operator=(heap_base && rhs) { Cmp::operator=(std::move(static_cast(rhs))); size_holder_type::operator=(std::move(static_cast(rhs))); return *this; } heap_base & operator=(heap_base const & rhs) { Cmp::operator=(static_cast(rhs)); size_holder_type::operator=(static_cast(rhs)); return *this; } #endif bool operator()(internal_type const & lhs, internal_type const & rhs) const { return Cmp::operator()(lhs, rhs); } internal_type make_node(T const & val) { return val; } #ifdef BOOST_HAS_RVALUE_REFS T && make_node(T && val) { return std::forward(val); } #endif static T & get_value(internal_type & val) { return val; } static T const & get_value(internal_type const & val) { return val; } Cmp const & value_comp(void) const { return *this; } Cmp const & get_internal_cmp(void) const { return *this; } void swap(heap_base & rhs) { std::swap(static_cast(*this), static_cast(rhs)); size_holder::swap(rhs); } stability_counter_type get_stability_count(void) const { return 0; } void set_stability_count(stability_counter_type) {} template friend struct heap_merge_emulate; }; template struct heap_base: Cmp, size_holder { typedef StabilityCounterType stability_counter_type; typedef T value_type; typedef std::pair internal_type; typedef size_holder size_holder_type; typedef Cmp value_compare; heap_base (Cmp const & cmp = Cmp()): Cmp(cmp), counter_(0) {} #ifdef BOOST_HAS_RVALUE_REFS heap_base(heap_base && rhs): Cmp(std::move(static_cast(rhs))), size_holder_type(std::move(static_cast(rhs))), counter_(rhs.counter_) { rhs.counter_ = 0; } heap_base(heap_base & rhs): Cmp(static_cast(rhs)), size_holder_type(static_cast(rhs)), counter_(rhs.counter_) {} heap_base & operator=(heap_base && rhs) { Cmp::operator=(std::move(static_cast(rhs))); size_holder_type::operator=(std::move(static_cast(rhs))); counter_ = rhs.counter_; rhs.counter_ = 0; return *this; } heap_base & operator=(heap_base const & rhs) { Cmp::operator=(static_cast(rhs)); size_holder_type::operator=(static_cast(rhs)); counter_ = rhs.counter_; return *this; } #endif bool operator()(internal_type const & lhs, internal_type const & rhs) const { internal_compare cmp(get_internal_cmp()); return cmp(lhs, rhs); } bool operator()(T const & lhs, T const & rhs) const { return Cmp::operator()(lhs, rhs); } internal_type make_node(T const & val) { stability_counter_type count = ++counter_; if (counter_ == std::numeric_limits::max()) BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow")); return std::make_pair(val, count); } #if defined(BOOST_HAS_RVALUE_REFS) && !defined(BOOST_NO_VARIADIC_TEMPLATES) template internal_type make_node(Args&&... args) { stability_counter_type count = ++counter_; if (counter_ == std::numeric_limits::max()) BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow")); return std::make_pair(std::forward(args)..., count); } #endif static T & get_value(internal_type & val) { return val.first; } static T const & get_value(internal_type const & val) { return val.first; } Cmp const & value_comp(void) const { return *this; } struct internal_compare: Cmp { internal_compare(Cmp const & cmp = Cmp()): Cmp(cmp) {} bool operator()(internal_type const & lhs, internal_type const & rhs) const { if (Cmp::operator()(lhs.first, rhs.first)) return true; if (Cmp::operator()(rhs.first, lhs.first)) return false; return lhs.second > rhs.second; } }; internal_compare get_internal_cmp(void) const { return internal_compare(*this); } void swap(heap_base & rhs) { std::swap(static_cast(*this), static_cast(rhs)); std::swap(counter_, rhs.counter_); size_holder::swap(rhs); } stability_counter_type get_stability_count(void) const { return counter_; } void set_stability_count(stability_counter_type new_count) { counter_ = new_count; } template friend struct heap_merge_emulate; private: stability_counter_type counter_; }; template struct node_handle { explicit node_handle(node_pointer n = 0): node_(n) {} reference operator*() const { return extractor::get_value(node_->value); } node_pointer node_; }; template struct value_extractor { value_type const & operator()(internal_type const & data) const { return extractor::get_value(data); } }; template class stable_heap_iterator: public boost::iterator_adaptor, ContainerIterator, T const, boost::random_access_traversal_tag> { typedef boost::iterator_adaptor super_t; public: stable_heap_iterator(void): super_t(0) {} explicit stable_heap_iterator(ContainerIterator const & it): super_t(it) {} private: friend class boost::iterator_core_access; T const & dereference() const { return Extractor::get_value(*super_t::base()); } }; template struct make_heap_base { typedef typename parameter::binding >::type compare_argument; typedef typename parameter::binding >::type allocator_argument; typedef typename parameter::binding::type stability_counter_type; static const bool is_stable = extract_stable::value; typedef heap_base type; }; template struct extract_allocator_types { typedef typename Alloc::size_type size_type; typedef typename Alloc::difference_type difference_type; typedef typename Alloc::reference reference; typedef typename Alloc::const_reference const_reference; typedef typename Alloc::pointer pointer; typedef typename Alloc::const_pointer const_pointer; }; } /* namespace detail */ } /* namespace heap */ } /* namespace boost */ #endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */