Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't std::priority_queue have a clear() member function

Tags:

c++

c++11

stl

I was doing some hacking today and found out that std::priority_queue does not have a clear() member function. Are there any technical reasons as to why the standards committee may have left this out?

To be clear, I am aware that it is easy to work around this via assignment:

oldPQ = std::priority_queue<int>{};

This solution is less desirable because:

  1. It requires you to repeat the type - this does not continue to work under maintenance. As @chris pointed out below, you can simplify this if you're using the default constructor, but if you have a custom comparator, this may not be possible.
  2. std::priority_queue cannot be used in a templated function that expects a clear() member function.
  3. It is generally undesirable that it does not meet the common interface provided by the other containers. In particular, everything from std::forward_list to std::unordered_map to std::string has clear(). The only other exceptions I note are std::array, for which the semantics would not make sense, and std::stack and std::queue, for which the semantics are more questionable when std::deque works without any extra effort.

One item that looks like an issue, but in practice needn't be: Because the internal container used for std::priority_queue is templated and may not have a clear() member function of its own, this creates an interesting problem, in particular it raises the question of backward compatibility. This is a non-issue because:

  1. For internal containers that do not provide clear(), as long as nobody attempts to invoke std::priority_queue::clear(), the code will continue to compile.
  2. It may still be possible with SFINAE to provide the new interface (the clear member) by calling clear() on the internal container when it's available and by repeatedly popping if it is not.

It is my opinion that this is a defect in the C++ standard. Assuming a technical discussion does not provide a strong case for why this method is omitted, I intend to pursue the creation of a standards proposal.

Edit:

Seems this is being handled in-committee (note the last post): https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-discussion/clear/std-discussion/_mYobAFBOrM/ty-2347w1T4J

http://wg21.cmeerw.net/lwg/issue2194

like image 427
Mark Avatar asked Oct 03 '13 18:10

Mark


People also ask

Can you clear a priority queue C++?

priority_queue doesn't have a clear method. It may be that this is for interface simplicity, or because it there may be situations in which elements must be destroyed in priority-order, making a generic clear function unsafe.

What is the difference between set and priority_queue?

The priority queue only offers access to the largest element, while the set gives you a complete ordering of all elements. This weaker interface means that implementations may be more efficient (e.g. you can store the actual queue data in a vector , which may have better performance on account of its memory locality).

What is std :: priority_queue?

std::priority_queue A priority queue is a container adaptor that provides constant time lookup of the largest (by default) element, at the expense of logarithmic insertion and extraction.

How do you clear the queue in C++?

Remove Item from a C++ QueueThe pop() method is used to remove an item from a queue in C++. The pop() function removes the item at the first position in the queues, because queues use the first-in, first-out data structure.


1 Answers

The specification of container adaptors is known to be overly pedantic: since the "abstract" spec of the corresponding data structure (from some book on abstract algorithms and data structures) does not include operation clear for canonical priority queues or stacks, it is not provided in the adaptor. This indeed often makes it quite inconvenient to use these adaptors in practice.

The good news though is that the inner container member is declared inside the adaptor as a protected member of the adapter, named c. This is probably done specifically for you to be able to easily implement your own version of the adaptor: by inheriting from the standard adaptor and adding whatever member functions you want to add, including clear.

As for comparing these adaptors' interfaces with standard container interfaces... I don't think it is a valid comparison. These adaptors have never been intended to be compatible with containers in terms of interface. Quite the opposite, the purpose of these adaptors was largely to restrict the public interface of the data structure and force it into the narrow bounds of what is allowed by its canonical abstract definition.

For example, you are not allowed to iterate over the canonical stack. Stack, by definition, is not "iterable". The fact that stack adaptor disables iteration interface is a good thing. But the absence of clear certainly feels too pedantic, since it has a great practical value without looking like a big violation of the canonical interface.

like image 154
AnT Avatar answered Oct 12 '22 13:10

AnT