23

Does anyone know why std::queue, std::stack, and std::priority_queue don't provide a clear() member function? I have to fake one like this:

std::queue<int> q;
// time passes...
q = std::queue<int>();  // equivalent to clear()

IIRC, clear() is provided by everything that could serve as the underlying container. Is there a good reason to not have the container adaptors provide it?

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125

6 Answers6

19

Well, I think this is because clear was not considered a valid operation on a queue, a priority_queue or a stack (by the way, deque is not and adaptor but a container).

The only reason to use the container adaptor queue instead of the container deque is to make it clear that you are performing only queue operations, and no other operations. (from the sgi page on queue)

So when using a queue, all you can do is push/pop elements; clearing the queue can be seen as a violation of the FIFO concept. Consequently, if you need to clear your queue, maybe it's not really a queue and you should better use a deque.

However, this conception of things is a little narrow-minded, and I think clearing the queue as you do is fair enough.

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
11

Deque has clear(). See, e.g., http://www.cplusplus.com/reference/stl/deque/clear.html.

However, queue does not. But why would you choose queue over deque, anyway?

The only reason to use the container adaptor queue instead of the container deque is to make it clear that you are performing only queue operations, and no other operations.

(http://www.sgi.com/tech/stl/queue.html)

So I guess clear() is not a queue operation, then.

Reunanen
  • 7,921
  • 2
  • 35
  • 57
2

I'd say it's because container adaptors are not containers.

MSN
  • 53,214
  • 7
  • 75
  • 105
1

You CAN clear queues (and std::stack and priority_queue), as long as you inherit from it. The container is intentionally left protected to allow this.

#include <queue>

using namespace std;

class clearable_queue : public queue<int>
{
public:
  void clear()
    {
      // the container 'c' in queues is intentionally left protected
      c.clear();
    }
};   

int main(int argc, char** argv)
{
  clearable_queue a;
  a.clear();
}
codelogic
  • 71,764
  • 9
  • 59
  • 54
  • 4
    you should not inherit publicly from standard containers, even if you do not add instance variables: deleting the derived class through a base class pointer without a virtual destructor will result in undefined behavior (it is **not** guaranteed to call the base class destructor). – Stephen Lin Mar 12 '13 at 22:17
-1

I think it depends on the implementation - until recently Microsoft STL didn't have clear on several containers. (it does now, eg this quick google result)

However, clear() is often simply a call to erase(begin(), end()), so implement your own equivalent and use that instead.

I think the standard refers to clear as erasing over an iterator range, so the above is what most implementations will provide. (eg Dinkumware's)

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
-2

std::queue, std::deque, and std::priority_queue are container adaptors and only provide a small number of methods to access the underlying container.

You can clear the underlying container, so long as you can access it. To do this, create the underlying container to pass in to the apadptor constructor. For example:

std::deque< int > d;
std::queue< int > q( d );

... time passes ...

d.clear();

Edit: additional info

I should also have warned you to tread carefully here as calling methods on the underlying container may break assumptions made by the adaptor. In that respect, the way you are currently clearng the queue seems preferable.

Daniel Paull
  • 6,797
  • 3
  • 32
  • 41
  • 1
    Daniel, this is not correct, the constructor argument to the queue is only used for _initializing_ the queue, not for passing a reference to the actual container. In other words, 'q' will be initialized with 'd's contents, but clearing 'd' won't affect 'q'. – codelogic Jan 29 '09 at 23:33
  • Interesting - the constructors I looked at didn't take a const reference to the collection... – Daniel Paull Jan 30 '09 at 04:34
  • 1
    Try again - you're right. The adaptors hold a collection be value, not reference and the constructors of the adaptors take a const reference to a collection for initialisation. Interestingly, in VS2008, the "c" member of queue is public! It is protected in priority_queue. – Daniel Paull Jan 30 '09 at 05:12