Does emptying a std::queue using a scoped queue::swap break any rules?
Your code is fine. swap
will make foo
a default constructed std::queue
and when bar
is destroyed at the end of the scope it will release the memory that foo
was using. Since you aren't using new
or delete
there is no issue since std::queue
"does the right thing" (RAII types are a wonderful thing)
Effectively you've done
std::queue<int>{std::move(foo)}; // move foo into a temporary that is immediately destroyed to release the storage
but your method gives you a stronger guaranteed about the state of foo
. Your method leave foo
in a default constructed state, while the above method leaves it in a valid, but unspecified state.
Another option is to use one of the solutions provided in Is there a way to access the underlying container of STL container adaptors? to get the underlying container from foo
and call clear on it. That would look like
#include <cstdlib>
#include <iostream>
#include <queue>
// function from https://stackoverflow.com/a/29325258/4342498 by jxh: https://stackoverflow.com/users/315052
template <class ADAPTER>
typename ADAPTER::container_type & get_container (ADAPTER &a)
{
struct hack : ADAPTER {
static typename ADAPTER::container_type & get (ADAPTER &a) {
return a.*&hack::c;
}
};
return hack::get(a);
}
int main()
{
std::queue<int> foo;
foo.push(10);
foo.push(20);
foo.push(30);
std::cout << "size of before foo: " << foo.size() << '\n';
get_container(foo).clear();
std::cout << "size of after foo: " << foo.size() << '\n';
return 0;
}
Not only is this completely safe, it's also how move constructors for containers typically work: by swapping with a short-lived (or at least soon-to-be-destroyed) other object then letting the other object die. The destructor then does all the data cleanup for you as quickly as it can. (Here that works around the lack of a clear()
member function.)
I reckon if I needed a one-shot "clear" operation, and I really wanted to use a queue (e.g. for forcing FIFO like you've said) then I'd do the same thing.
Although if you can just let the old container go out of scope and switch to working on a newly-declared one then so much the better.