| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- // 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 <type_traits>
- #include <utility>
- #include <boost/core/allocator_access.hpp>
- #include <boost/cstdint.hpp>
- #include <boost/iterator/iterator_adaptor.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/heap/heap_merge.hpp>
- #include <boost/heap/policies.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 ) noexcept :
- size_( 0 )
- {}
- size_holder( size_holder&& rhs ) noexcept :
- size_( rhs.size_ )
- {
- rhs.size_ = 0;
- }
- size_holder( size_holder const& rhs ) noexcept :
- size_( rhs.size_ )
- {}
- size_holder& operator=( size_holder&& rhs ) noexcept
- {
- size_ = rhs.size_;
- rhs.size_ = 0;
- return *this;
- }
- size_holder& operator=( size_holder const& rhs ) noexcept
- {
- size_ = rhs.size_;
- return *this;
- }
- SizeType get_size() const noexcept
- {
- return size_;
- }
- void set_size( SizeType size ) noexcept
- {
- size_ = size;
- }
- void decrement() noexcept
- {
- --size_;
- }
- void increment() noexcept
- {
- ++size_;
- }
- void add( SizeType value ) noexcept
- {
- size_ += value;
- }
- void sub( SizeType value ) noexcept
- {
- size_ -= value;
- }
- void swap( size_holder& rhs ) 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 ) noexcept
- {}
- size_holder( size_holder&& ) noexcept
- {}
- size_holder( size_holder const& ) noexcept
- {}
- size_holder& operator=( size_holder&& ) noexcept
- {
- return *this;
- }
- size_holder& operator=( size_holder const& ) noexcept
- {
- return *this;
- }
- size_type get_size() const noexcept
- {
- return 0;
- }
- void set_size( size_type ) noexcept
- {}
- void decrement() noexcept
- {}
- void increment() noexcept
- {}
- void add( SizeType /*value*/ ) noexcept
- {}
- void sub( SizeType /*value*/ ) noexcept
- {}
- void swap( size_holder& /*rhs*/ ) 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 code
- template < 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
- {}
- heap_base( heap_base&& rhs ) noexcept( std::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 ) noexcept( std::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;
- }
- 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;
- }
- T&& make_node( T&& val )
- {
- return std::forward< T >( val );
- }
- template < class... Args >
- internal_type make_node( Args&&... val )
- {
- return internal_type( std::forward< Args >( val )... );
- }
- static T& get_value( internal_type& val ) noexcept
- {
- return val;
- }
- static T const& get_value( internal_type const& val ) noexcept
- {
- return val;
- }
- Cmp const& value_comp( void ) const noexcept
- {
- #ifndef BOOST_MSVC
- return *this;
- #else
- return cmp_;
- #endif
- }
- Cmp const& get_internal_cmp( void ) const noexcept
- {
- return value_comp();
- }
- void swap( heap_base& rhs ) noexcept( std::is_nothrow_move_constructible< Cmp >::value
- && std::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 noexcept
- {
- return 0;
- }
- void set_stability_count( stability_counter_type ) 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
- {
- template < class... Args >
- internal_type( stability_counter_type cnt, Args&&... args ) :
- first( std::forward< Args >( args )... ),
- second( cnt )
- {}
- 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 )
- {}
- heap_base( heap_base&& rhs ) noexcept( std::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 ) noexcept( std::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;
- }
- 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 );
- }
- 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 )... );
- }
- static T& get_value( internal_type& val ) noexcept
- {
- return val.first;
- }
- static T const& get_value( internal_type const& val ) noexcept
- {
- return val.first;
- }
- Cmp const& value_comp( void ) const 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 ) noexcept( std::is_nothrow_move_constructible< Cmp >::value
- && std::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 ) 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
- {
- typedef typename boost::allocator_size_type< Alloc >::type size_type;
- typedef typename boost::allocator_difference_type< Alloc >::type difference_type;
- typedef typename Alloc::value_type& reference;
- typedef typename Alloc::value_type const& const_reference;
- typedef typename boost::allocator_pointer< Alloc >::type pointer;
- typedef typename boost::allocator_const_pointer< Alloc >::type const_pointer;
- };
- }}} // namespace boost::heap::detail
- #endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */
|