Reputation: 14174
My question is simple: Its possible to obtain a pointer to the underlying storage of a std::queue
container adapter?
I'm working on some simulations using SFML for rendering, and I use the draw()
method of the SFML render target (sf::RenderTarget
) to draw the entire bunch of data. That method has a C-like interface expecting a pointer to the data and a std::size_t
with the number of elements to draw.
Since the data is stored in a queue for some purposes, I will be glad if there is some way to get that pointer to the queue underlying storage instead of copying the data to a vector.
I know that std::queue
adapts the container std::deque
by default, but I don't know how that circular buffer is implemented and if its data is contiguous (So I can extract a pointer to the data directly).
Looking at the answers bellow, let me note that I'm not using std::deque
because its fancy queue-like interface, but because I really need fast queueing. Of course I can use std::vector
. If performance wasn't the point here I would have used push_back()
and erase( begin() )
of vector. But what I need is fast queueing and a way to move the data of that queue to the render target efficiently. Of course if the balance queueing vs effort to draw it goes to the draw side, I will use std::vector
.
Upvotes: 7
Views: 1740
Reputation: 42899
The most intuitive thought would be to use a std::vector
as the underling container of your std::queue
to assure contiguous memory and then by taking the address of std::queue::front
to access the contiguous storage of the wrapped std::vector
.
However, as @Blastfurnace correctly noted std::vector
doesn't have a pop_front
member function and when you were going to call std::queue::pop
the program would blast.
Also as already mentioned, std::queue
normally requires as its underlying container, a container like std::deque
or std::list
. Due to their structural traits these containers are the most suitable because they can pop efficiently their front element. However, due to its contiguous memory std::vector
lacks of such versatility.
Also, if use of a container with contiguous memory is something that would boost significantly your application it's better and more straightforward to use a std::vector
.
However, and for the record, you could also do the following hack in order to circumvent the lack of std::vector
's pop_front
member function. You could define a class
that inherits from std::vector
and implement the pop_front
member function like the example below:
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
template<class T, class Alloc = std::allocator<T>>
class queuevec : public std::vector<T, Alloc> {
public:
void pop_front() {
if(!this->empty()) this->erase(this->begin());
}
};
int main() {
std::queue<int, queuevec<int>> Q;
for(int i(0); i < 10; ++i) Q.push(i);
Q.pop();
int *t = &(Q.front());
std::for_each(t, t + Q.size(), [](int const i){ std::cout << i << " "; });
std::cout << std::endl;
}
Upvotes: 1
Reputation: 68033
Is it possible to obtain a pointer to the underlying storage of a std::queue container adapter?
Short answer: No.
std::queue
requires a SequenceContainer
type, like std::deque
or std::list
. Neither of these guarantee contiguous storage, so there's no concept of a pointer to the underlying storage.
If they used contiguous circular buffers, this would either impose a fixed size on the container, or incur large cost (like std::vector can) when the container needs to be resized.
You could look at using a boost::circular_buffer
instead.
Upvotes: 10