| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 | // 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 <limits>#include <stdexcept>#include <utility>#include <boost/cstdint.hpp>#include <boost/throw_exception.hpp>#include <boost/iterator/iterator_adaptor.hpp>#include <boost/heap/policies.hpp>#include <boost/heap/heap_merge.hpp>#include <boost/type_traits/is_nothrow_move_constructible.hpp>#include <boost/type_traits/is_nothrow_move_assignable.hpp>namespace boost  {namespace heap   {namespace detail {template<bool ConstantSize, class SizeType>struct size_holder{    static const bool constant_time_size = ConstantSize;    typedef SizeType  size_type;    size_holder(void) BOOST_NOEXCEPT:        size_(0)    {}#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES    size_holder(size_holder && rhs) BOOST_NOEXCEPT:        size_(rhs.size_)    {        rhs.size_ = 0;    }    size_holder(size_holder const & rhs) BOOST_NOEXCEPT:        size_(rhs.size_)    {}    size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT    {        size_ = rhs.size_;        rhs.size_ = 0;        return *this;    }    size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT    {        size_ = rhs.size_;        return *this;    }#endif    SizeType get_size() const BOOST_NOEXCEPT    {  return size_;  }    void set_size(SizeType size) BOOST_NOEXCEPT    {  size_ = size; }    void decrement() BOOST_NOEXCEPT    {  --size_; }    void increment() BOOST_NOEXCEPT    {  ++size_; }    void add(SizeType value) BOOST_NOEXCEPT    {  size_ += value; }    void sub(SizeType value) BOOST_NOEXCEPT    {  size_ -= value; }    void swap(size_holder & rhs) BOOST_NOEXCEPT    {  std::swap(size_, rhs.size_); }    SizeType size_;};template<class SizeType>struct size_holder<false, SizeType>{    static const bool constant_time_size = false;    typedef SizeType  size_type;    size_holder(void) BOOST_NOEXCEPT    {}#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES    size_holder(size_holder && rhs) BOOST_NOEXCEPT    {}    size_holder(size_holder const & rhs) BOOST_NOEXCEPT    {}    size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT    {        return *this;    }    size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT    {        return *this;    }#endif    size_type get_size() const BOOST_NOEXCEPT    {  return 0;  }    void set_size(size_type) BOOST_NOEXCEPT    {}    void decrement() BOOST_NOEXCEPT    {}    void increment() BOOST_NOEXCEPT    {}    void add(SizeType /*value*/) BOOST_NOEXCEPT    {}    void sub(SizeType /*value*/) BOOST_NOEXCEPT    {}    void swap(size_holder & /*rhs*/) BOOST_NOEXCEPT    {}};// note: MSVC does not implement lookup correctly, we therefore have to place the Cmp object as member inside the//       struct. of course, this prevents EBO and significantly reduces the readability of this codetemplate <typename T,          typename Cmp,          bool constant_time_size,          typename StabilityCounterType = boost::uintmax_t,          bool stable = false         >struct heap_base:#ifndef BOOST_MSVC    Cmp,#endif    size_holder<constant_time_size, size_t>{    typedef StabilityCounterType stability_counter_type;    typedef T value_type;    typedef T internal_type;    typedef size_holder<constant_time_size, size_t> size_holder_type;    typedef Cmp value_compare;    typedef Cmp internal_compare;    static const bool is_stable = stable;#ifdef BOOST_MSVC    Cmp cmp_;#endif    heap_base (Cmp const & cmp = Cmp()):#ifndef BOOST_MSVC        Cmp(cmp)#else        cmp_(cmp)#endif    {}#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES    heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):#ifndef BOOST_MSVC        Cmp(std::move(static_cast<Cmp&>(rhs))),#endif        size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))#ifdef BOOST_MSVC        , cmp_(std::move(rhs.cmp_))#endif    {}    heap_base(heap_base const & rhs):#ifndef BOOST_MSVC        Cmp(static_cast<Cmp const &>(rhs)),#endif        size_holder_type(static_cast<size_holder_type const &>(rhs))#ifdef BOOST_MSVC        , cmp_(rhs.value_comp())#endif    {}    heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)    {        value_comp_ref().operator=(std::move(rhs.value_comp_ref()));        size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));        return *this;    }    heap_base & operator=(heap_base const & rhs)    {        value_comp_ref().operator=(rhs.value_comp());        size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));        return *this;    }#endif    bool operator()(internal_type const & lhs, internal_type const & rhs) const    {        return value_comp().operator()(lhs, rhs);    }    internal_type make_node(T const & val)    {        return val;    }#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES    T && make_node(T && val)    {        return std::forward<T>(val);    }#endif#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)    template <class... Args>    internal_type make_node(Args && ... val)    {        return internal_type(std::forward<Args>(val)...);    }#endif    static T & get_value(internal_type & val) BOOST_NOEXCEPT    {        return val;    }    static T const & get_value(internal_type const & val) BOOST_NOEXCEPT    {        return val;    }    Cmp const & value_comp(void) const BOOST_NOEXCEPT    {#ifndef BOOST_MSVC        return *this;#else        return cmp_;#endif    }    Cmp const & get_internal_cmp(void) const BOOST_NOEXCEPT    {        return value_comp();    }    void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)    {        std::swap(value_comp_ref(), rhs.value_comp_ref());        size_holder<constant_time_size, size_t>::swap(rhs);    }    stability_counter_type get_stability_count(void) const BOOST_NOEXCEPT    {        return 0;    }    void set_stability_count(stability_counter_type) BOOST_NOEXCEPT    {}    template <typename Heap1, typename Heap2>    friend struct heap_merge_emulate;private:    Cmp & value_comp_ref(void)    {#ifndef BOOST_MSVC        return *this;#else        return cmp_;#endif    }};template <typename T,          typename Cmp,          bool constant_time_size,          typename StabilityCounterType         >struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:#ifndef BOOST_MSVC    Cmp,#endif    size_holder<constant_time_size, size_t>{    typedef StabilityCounterType stability_counter_type;    typedef T value_type;    struct internal_type    {#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)        template <class ...Args>        internal_type(stability_counter_type cnt, Args && ... args):            first(std::forward<Args>(args)...), second(cnt)        {}#endif        internal_type(stability_counter_type const & cnt, T const & value):            first(value), second(cnt)        {}        T first;        stability_counter_type second;    };    typedef size_holder<constant_time_size, size_t> size_holder_type;    typedef Cmp value_compare;#ifdef BOOST_MSVC    Cmp cmp_;#endif    heap_base (Cmp const & cmp = Cmp()):#ifndef BOOST_MSVC        Cmp(cmp),#else        cmp_(cmp),#endif        counter_(0)    {}#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES    heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):#ifndef BOOST_MSVC        Cmp(std::move(static_cast<Cmp&>(rhs))),#else        cmp_(std::move(rhs.cmp_)),#endif        size_holder_type(std::move(static_cast<size_holder_type&>(rhs))), counter_(rhs.counter_)    {        rhs.counter_ = 0;    }    heap_base(heap_base const & rhs):#ifndef BOOST_MSVC        Cmp(static_cast<Cmp const&>(rhs)),#else        cmp_(rhs.value_comp()),#endif        size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)    {}    heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)    {        value_comp_ref().operator=(std::move(rhs.value_comp_ref()));        size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));        counter_ = rhs.counter_;        rhs.counter_ = 0;        return *this;    }    heap_base & operator=(heap_base const & rhs)    {        value_comp_ref().operator=(rhs.value_comp());        size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));        counter_ = rhs.counter_;        return *this;    }#endif    bool operator()(internal_type const & lhs, internal_type const & rhs) const    {        return get_internal_cmp()(lhs, rhs);    }    bool operator()(T const & lhs, T const & rhs) const    {        return value_comp()(lhs, rhs);    }    internal_type make_node(T const & val)    {        stability_counter_type count = ++counter_;        if (counter_ == (std::numeric_limits<stability_counter_type>::max)())            BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));        return internal_type(count, val);    }#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)    template <class... Args>    internal_type make_node(Args&&... args)    {        stability_counter_type count = ++counter_;        if (counter_ == (std::numeric_limits<stability_counter_type>::max)())            BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));        return internal_type (count, std::forward<Args>(args)...);    }#endif    static T & get_value(internal_type & val) BOOST_NOEXCEPT    {        return val.first;    }    static T const & get_value(internal_type const & val) BOOST_NOEXCEPT    {        return val.first;    }    Cmp const & value_comp(void) const BOOST_NOEXCEPT    {#ifndef BOOST_MSVC        return *this;#else        return cmp_;#endif    }    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(value_comp());    }    void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)    {#ifndef BOOST_MSVC        std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));#else        std::swap(cmp_, rhs.cmp_);#endif        std::swap(counter_, rhs.counter_);        size_holder<constant_time_size, size_t>::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 <typename Heap1, typename Heap2>    friend struct heap_merge_emulate;private:    Cmp & value_comp_ref(void) BOOST_NOEXCEPT    {#ifndef BOOST_MSVC        return *this;#else        return cmp_;#endif    }    stability_counter_type counter_;};template <typename node_pointer,          typename extractor,          typename reference         >struct node_handle{    explicit node_handle(node_pointer n = 0):        node_(n)    {}    reference operator*() const    {        return extractor::get_value(node_->value);    }    bool operator==(node_handle const & rhs) const    {        return node_ == rhs.node_;    }    bool operator!=(node_handle const & rhs) const    {        return node_ != rhs.node_;    }    node_pointer node_;};template <typename value_type,          typename internal_type,          typename extractor         >struct value_extractor{    value_type const & operator()(internal_type const & data) const    {        return extractor::get_value(data);    }};template <typename T,          typename ContainerIterator,          typename Extractor>class stable_heap_iterator:    public boost::iterator_adaptor<stable_heap_iterator<T, ContainerIterator, Extractor>,                                   ContainerIterator,                                   T const,                                   boost::random_access_traversal_tag>{    typedef boost::iterator_adaptor<stable_heap_iterator,                                    ContainerIterator,                                    T const,                                    boost::random_access_traversal_tag> 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 <typename T, typename Parspec, bool constant_time_size>struct make_heap_base{    typedef typename parameter::binding<Parspec, tag::compare, std::less<T> >::type compare_argument;    typedef typename parameter::binding<Parspec, tag::allocator, std::allocator<T> >::type allocator_argument;    typedef typename parameter::binding<Parspec, tag::stability_counter_type, boost::uintmax_t >::type stability_counter_type;    static const bool is_stable = extract_stable<Parspec>::value;    typedef heap_base<T, compare_argument, constant_time_size, stability_counter_type, is_stable> type;};template <typename Alloc>struct extract_allocator_types{#ifdef BOOST_NO_CXX11_ALLOCATOR    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;#else    typedef std::allocator_traits<Alloc> traits;    typedef typename traits::size_type size_type;    typedef typename traits::difference_type difference_type;    typedef typename Alloc::value_type& reference;    typedef typename Alloc::value_type const& const_reference;    typedef typename traits::pointer pointer;    typedef typename traits::const_pointer const_pointer;#endif};} /* namespace detail */} /* namespace heap */} /* namespace boost */#endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */
 |