StoredPriorityQueue.h

Go to the documentation of this file.
00001 #ifndef StoredPriorityQueue_HEADER
00002 #define StoredPriorityQueue_HEADER
00003 
00004 /***************************************************************************
00005  * Benoit Hudson (C) 2007.
00006  ***************************************************************************/
00007 
00008 #include <boost/type_traits/is_empty.hpp>
00009 #include <functional> // std::less
00010 #include <queue> // std::priority_queue
00011 #include <vector> // std::vector
00012 
00013 namespace hudson {
00014 /***************************************************************************
00015  * \file
00016  *
00017  * A priority queue for ordering things, where we store the key separate from
00018  * the item.  This is pretty common usage, and not entirely trivial to do
00019  * using stl's priority_queue.
00020  ***************************************************************************/
00021 
00026 namespace details {
00027 
00028   /************************************************************
00029    * I don't want to pay any storage at all for when
00030    * compare/compute are empty classes (like std::less).
00031    * Hence these four template specializations, which all satisfy
00032    * that they have a public pq_, getCompare(), and getCompute().
00033    ************************************************************/
00034   template <class PQ, class Compare, bool compare_empty, class Compute, bool compute_empty>
00035     struct WrapPQ {
00036       PQ pq_;
00037       Compare compare_;
00038       Compute compute_;
00039 
00040       WrapPQ(const Compare& compare, const Compute& compute)
00041         : compare_(compare), compute_(compute) { }
00042       const Compare& getCompare() const { return compare_; }
00043       const Compute& getCompute() const { return compute_; }
00044     };
00045 
00046   template <class PQ, class Compare, class Compute>
00047     struct WrapPQ<PQ, Compare, true, Compute, false> {
00048       PQ pq_;
00049       Compute compute_;
00050 
00051       WrapPQ(const Compare&, const Compute& compute)
00052         : compute_(compute) { }
00053       Compare getCompare() const { return Compare(); }
00054       const Compute& getCompute() const { return compute_; }
00055     };
00056 
00057   template <class PQ, class Compare, class Compute>
00058     struct WrapPQ<PQ, Compare, false, Compute, true> {
00059       PQ pq_;
00060       Compare compare_;
00061 
00062       WrapPQ(const Compare& compare, const Compute&)
00063         : compare_(compare) { }
00064       const Compare& getCompare() const { return compare_; }
00065       Compute getCompute() const { return Compute(); }
00066     };
00067 
00068   template <class PQ, class Compare, class Compute>
00069     struct WrapPQ<PQ, Compare, true, Compute, true> {
00070       PQ pq_;
00071 
00072       WrapPQ(const Compare&, const Compute&) { }
00073       Compare getCompare() const { return Compare(); }
00074       Compute getCompute() const { return Compute(); }
00075     };
00076 
00077 
00078 } /* end details */
00079 
00080 /***************************************************************************
00081  * A priority queue for ordering things, where we store the key separate from
00082  * the item.  This is pretty common usage, and not entirely trivial to do
00083  * using stl's priority_queue.
00084  *
00085  * Compare and Compute are function objects.  Compare should compare two Keys;
00086  * Compute should take an Item and return a Key.
00087  ***************************************************************************/
00088 template <class Key, class Item, class Compute, class Compare = std::less<Key> >
00089 class StoredPriorityQueue {
00090   typedef pair<Key, Item> ki_pair;
00091 
00093   struct compare_pair : private Compare { /* inherit rather than contain: saves size */
00094     compare_pair(): Compare() { }
00095     compare_pair(const Compare& comp): Compare(comp) { }
00096     bool operator()(const ki_pair& a, const ki_pair& b) const {
00097       return Compare::operator()(a.first, b.first);
00098     }
00099   };
00100 
00107   details::WrapPQ<
00108     std::priority_queue<ki_pair, std::vector<ki_pair>, compare_pair>,
00109     compare_pair, boost::is_empty<compare_pair>::value,
00110     Compute, boost::is_empty<Compute>::value
00111     > q_;
00112 
00113   public:
00119   StoredPriorityQueue(): q_(compare_pair(), Compute()) { }
00120   StoredPriorityQueue(const Compute& ute): q_(compare_pair(), ute) { }
00121   StoredPriorityQueue(const Compare& are): q_(compare_pair(are), Compute()) { }
00122   StoredPriorityQueue(const Compute& ute, const Compare& are): q_(compare_pair(are), ute) { }
00124 
00130   const ki_pair& top_pair() const {
00131     assert(!empty());
00132     return q_.pq_.top();
00133   }
00134 
00135   const Item& top() const { return top_pair().second; }
00137 
00139   void pop() { q_.pq_.pop(); }
00140 
00147   void push(const Key& k, const Item& i) {
00148     q_.pq_.push(make_pair(k, i));
00149   }
00150 
00151   void push(const ki_pair& p) {
00152     q_.pq_.push(p);
00153   }
00154 
00155   void push(const Item& i) {
00156     push(getPriority(i), i);
00157   }
00159 
00161   bool empty() const { return q_.pq_.empty(); }
00162 
00165   bool compare(const Key& a, const Key& b) const {
00166     return q_.getCompare()(a, b);
00167   }
00168   Key getPriority(const Item& i) const {
00169     return q_.getCompute()(i);
00170   }
00172 };
00173 
00174 } // namespace hudson
00175 #endif

Generated on Thu Mar 27 19:04:15 2008 by  doxygen 1.4.6