I'm trying to write a Priority Queue/Heap implementation which allows for iteration, deletion of elements, changes to the keys and values during iteration, and finding all elements with a certain key. std::priority_queue
does not support iteration and boost::heap
does not support changes to keys and values during iteration. I also tried using std::multimap
, but it also has problems with changing values during iteration.
My queue is stored as a std::vector
of std::pairs<double, T>
. I thought I could use std::sort
and std::equal_range
functions without defining my own comparator because std::pair
automatically overloads the <
operator. Also, this question suggests that using std::equal_range
with containers of pairs is possible, but I'm getting the following compiler errors for std::equal_range
.
'bool std::operator <(const std::vector<_Ty,_Ax> &,const std::vector<_Ty,_Ax> &)' : could not deduce template argument for 'const std::vector<_Ty,_Ax> &' from 'const double'
and
binary '<' : no global operator found which takes type 'std::pair<_Ty1,_Ty2>' (or there is no acceptable conversion)
My guess is that this has something to do with using a template, but in that case, I would also expect std::sort
to fail.
To summarize
Why is the automatic overloading of
std::pair
<
not working forstd::equal_range
?Do I need to define a comparator for my priority queue?
My implementation is as follows
Test
int main()
{
PriorityQueue<double> queue;
queue.push(1, 1);
queue.remove(0);
queue.cleanup(); //This call throws the error when it calls std::equal_range
}
Header
#include <vector>
#include <utility>
#include <algorithm>
template<typename T>
class PriorityQueue
{
T item;
typedef typename std::vector<std::pair<double, T>>::iterator It;
private:
std::vector<std::pair<double, T>> queue;
bool isSorted;
bool hasRemoved;
void sort(){
std::sort(queue.begin(), queue.end());
};
public:
PriorityQueue():isSorted(true), hasRemoved(false){};
void push(double cost, T val)
{
isSorted = false;
queue.push_back(std::make_pair(cost, val));
};
void remove(int i)
{
hasRemoved = true;
isSorted = false;
queue[i].first = DBL_MAX; //Pushes element to end of list
};
void cleanup()
{
if(!isSorted) sort();
if(hasRemoved)
{
std::pair<It, It> remove = std::equal_range(queue.begin(), queue.end(), DBL_MAX); // This line throws the error
queue.erase(remove.first, remove.second);
}
};
};