std::stack
and std::queue
are so-called "container adapters", as in they adapt the interface of the wrapped container (a template parameter, defaulted to std::deque
, but could be anything that implements back()
, push_back()
and pop_back()
for std::stack
, and back()
, pop_front()
and push_back()
for std::queue
) to the restricted interface of a stack or a queue; if you prefer, they dumb down the underlying container interface.
The general idea should be that the "restricted" container provides just the operations of the "expected mode of operation" of the container - an std::stack
allows only stack-like operations, unlike the underlying std::deque
that allows, for example, random insert/access. Another advantage is that compile-time polymorphism over the underlying container type is a little more comfortable than passing the plain container (you may get better error messages).
In practice, I always found these adapters at least useless, more often just hindrances:
- they don't restrict the space of available states, as, given extra space, both an
std::stack
and std::queue
can be mutated in any way;
- they don't provide type erasure over the underlying container type, as it's a template parameter, so they aren't useful to write a non-template function that takes any stack, regardless of the underlying container;
- most often their interface is way too restricted; you cannot even do a debug print of the full content of an
std::stack
, even if the underlying container fully supported forward iterators (or even random access).