[RESOLVED] How to use a derived function for std::priority_queue Compare
I have a template class that contains a std::priority_queue and would like for the user of this class to be able to pass in the functor object that is used for comparison. Here is the code I have but it is not working. I kind of didn't think it would be thought I would give it a try. Maybe I am going about this the wrong way.
Code:
template <typename T>
class ProcessingQueue {
public:
class Comparer
{
public:
virtual bool operator()(T* obj1, T* obj2) {
return true;
}
};
.
.
.
void push(T* element);
virtual void processElement(T* element) = 0;
.
.
.
private:
std::priority_queue<T*, std::vector<T*>, Comparer> m_vector;
.
.
.
}
This class creates and manages a thread that takes elements that are put on the queue and processes them. I had this working fine using a vector but want to convert it to a priority_queue to allow elements to be processed based on a user defined priority.
My initial thought was to create the Comparer class to provide as the thrid template parameter to priority_queue and let users derive a specific Comparer for there type implementing an appropriate operator() overload. This did not work and after digging into it a little more I understand why.
Am I going about this the wrong way?
Can someone help with how to go about this?
Please let me know if more information is needed. I tried to only post relevant code.
Thanks.
Re: How to use a derived function for std::priority_queue Compare
There could well be a problem in that your Compare class's operator () always returns true.
Re: How to use a derived function for std::priority_queue Compare
Are you expecting the user to be specifying the comparison method at compile time, or run time?
Re: How to use a derived function for std::priority_queue Compare
I was expecting the user to supply the comparison function at compile time. My theory was that they would derive a class from Comparer and override operator().
Either was is probably okay as the requirements for usage of this class are not well defined so actually which ever would be the best approach (if one is better than the other).
Thanks.
Re: [RESOLVED] How to use a derived function for std::priority_queue Compare
I figured it out.
I ended up adding a template parameter to ProcessingQueue and using that as the thrid template parameter to std::priority_queue.
I created a default Comparer with the signature bool Comparer(void*, void*) that always returns false and used it as a default for ProcessingQueue's additional template parameter so users do no need to provide a comparer function but they can and if they do it is passed on to priority_queue.
Lindley,
I'd interested in knowing what you had in mind about supplying the compare at runtime. If you see this message.
Thanks.
Re: [RESOLVED] How to use a derived function for std::priority_queue Compare
Quote:
Originally Posted by
Yadrif
Lindley,
I'd interested in knowing what you had in mind about supplying the compare at runtime. If you see this message.
Well, the priority_queue constructor optionally takes a functor to be used for comparison. You could simply require such a thing to be passed into the constructor of ProcessingQueue, and then hand it off to the STL queue in the initializer list.
Granted, I'm not entirely positive that handing it an object derived from the templated type will work properly. There may be slicing if the STL implementation doesn't anticipate that possibility. You could test this by making the base class's function operator be pure virtual, and see if the thing still compiles.
Even if that doesn't work, making the comparison type be a boost::function<bool (T, T)> will certainly work.
Re: [RESOLVED] How to use a derived function for std::priority_queue Compare
Instead of using void * (very C like solution), you could ty something like this.
Code:
#include <queue>
#include <functional>
// Comparer base class.
template <typename T>
class Comparer_Base
{
public:
virtual bool operator()(T* obj1, T* obj2)
{
return std::less<T>()(*obj1, *obj2); // Call the standard function.
}
};
// Processing queue class.
template <typename T, typename Comparer = Comparer_Base<T>>
class ProcessingQueue {
public:
void push(T* element)
{
m_vector.push(element);
}
virtual void processElement(T* element) = 0;
private:
std::priority_queue<T*, std::vector<T*>, Comparer> m_vector;
};
// Derived comparer class.
template <typename T>
class Greater : Comparer_Base<T>
{
public:
bool operator()(T *obj1, T* obj2) {
return (*obj1 > *obj2);
}
};
// Derived ProcessingQueue
class NormalQueue : public ProcessingQueue<int>
{
public:
void processElement(int* element) {
}
};
// Derived ProcessingQueue
class GreaterQueue : public ProcessingQueue<int, Greater<int> >
{
public:
void processElement(int* element) {
}
};
int main()
{
NormalQueue nq;
GreaterQueue gq;
int i, j;
nq.push(&i);
nq.push(&j);
gq.push(&i);
gq.push(&j);
}