Minimal working example.
#include <cassert>
#include <list>
#include <queue>
//#define USE_PQ
struct MyClass
{
const char* str;
MyClass(const char* _str) : str(_str) {}
MyClass(MyClass&& src) { str = src.str; src.str = nullptr; }
MyClass(const MyClass&) = delete;
};
struct cmp_func
{
bool operator() (const MyClass&, const MyClass&) const
{
return true;
}
};
typedef std::priority_queue<MyClass, std::vector<MyClass>, cmp_func> pq_type;
#ifdef USE_PQ
MyClass remove_front(pq_type& l)
{
MyClass moved = std::move(l.top());
// error from the above line:
// use of deleted function ‘MyClass::MyClass(const MyClass&)’
l.pop();
return std::move(moved);
}
#else
MyClass remove_front(std::list<MyClass>& l)
{
MyClass moved = std::move(l.front());
l.erase(l.begin());
return std::move(moved);
}
#endif
int main()
{
const char* hello_str = "Hello World!";
MyClass first(hello_str);
#ifdef USE_PQ
pq_type l;
l.push(std::move(first));
MyClass moved = remove_front(l);
#else
std::list<MyClass> l;
l.push_back(std::move(first));
MyClass moved = remove_front(l);
#endif
assert(moved.str);
assert(!first.str);
return 0;
}
So this works. Now remove the comment signs from line 4 and it says that copy constructors would be needed (mine is deleted). Also, it misses operator=
. Questions:
Note: You can also use boost's priority_queue for your answer, but I got the same error with it.
Suitable underlying container classes for priority_queue include deque Class and the default vector Class or any other sequence container that supports the operations of front , push_back , and pop_back and a random-access iterator.
Access Element from the Priority Queue We access the top element of the priority_queue using the top() method. In the above example, we have inserted elements into priority_queue in the following order: 1, 20, 7.
In C++, the default STL (Standard Template Library) priority queue is Max priority queue (returns the largest element).
A descending order priority queue gives the highest priority to the highest number in that queue. For example, you have six numbers in the priority queue that are 4, 8, 12, 45, 35, 20. Firstly, you will arrange these numbers in ascending order. The new list is as follows: 45, 35, 20, 12, 8, 4.
Depending on what type you want to store in the priority queue, an alternative to Angew's solution, that avoids the const_cast
and removes some of the opportunities for shooting oneself in the foot, would be to wrap the element type as follows:
struct Item {
mutable MyClass element;
int priority; // Could be any less-than-comparable type.
// Must not touch "element".
bool operator<(const Item& i) const { return priority < i.priority; }
};
Moving the element out of the queue would then be done as such:
MyClass moved = std::move(l.top().element);
l.pop();
That way, there are no special requirements on the move semantics of MyClass
to preserve the order relation on the invalidated object, and there will be no section of code where invariants of the priority queue are invalidated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With