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