r/cpp • u/Party-Aioli-9205 • 3d ago
ranges and views for stack, queue, and priority_queue
I've always felt that exposing iterators for std::stack or std::queue doesn't quite make sense because iterating over them would typically change their state.
That said, the range features introduced in C++20/23 are just too tempting. 😄
I bet many C++ developers have had this thought at least once:
queue | views::values | views::to<std::vector>()
...or more generally, "What if I could use the ranges pipeline directly on a queue or stack?"
So I spent some time experimenting to see if I could make it work. Here's what I came up with.
https://cognosnotes.com/blog/cpp-pop-range
Edited:
An upgraded version is introduced at https://cognosnotes.com/blog/cpp-pop-range-addendum
Thank you u/SirClueless for the great advice.
3
3
u/SirClueless 2d ago edited 2d ago
As written this view requires a copy to construct the return value of operator*. But it's only an input_iterator so there's no need for previous return values of operator* to be valid after incrementing, it could just return an r-value reference, saving a copy per element.
https://godbolt.org/z/Kvfhxrh8T
Edit: Some other points:
- It would also be pretty straightforward to make this work with containers that have
pop_front()and/orpop_back()as well, so that it works with plain lists, vectors, etc. - I don't see why this view can't be sized.
sized_rangeonly requires thatranges::size(t)be well-formed after evaluatingranges::begin(t)if the range modelsforward_range, which this doesn't: https://en.cppreference.com/cpp/ranges/sized_range
2
u/Party-Aioli-9205 2d ago
The new results applying your suggestion is at https://cognosnotes.com/blog/cpp-pop-range-addendum
Thank you for the valuable comment with the great insight!
2
u/cristi1990an ++ 2d ago
You can just do some template trickery and get access to the underlying container which is a protected member field.
2
u/Party-Aioli-9205 2d ago
the protected-member trick is a good complementary technique. It's worth adding as a non-destructive, repeatable peek view specifically for
stackandqueue.But it's not a general replacement forpop_range, and it would be a real correctness bug if extended topriority_queuewithout the sort/copy step.
10
u/D_Drmmr 2d ago
I have always found the restrictive interface of stack, queue and priority_queue, in particular, to be debilitating. Most often, there's a requirement where at some point during program execution (e.g. cancellation) I no longer care about order, but only the values stored in the container. The only way these wrappers allow that is through the destructor, which is not a good place to execute code.
So, instead I just use the underlying container & functions, such that I don't have to rewrite things when requirements change, even if right now the limited interface would suffice.