.data () equivalent for std :: queue

My question is simple: Is it possible to get a pointer to the base storage of the container adapter std::queue ?

I am working on some simulations using SFML for rendering, and use the draw() method for the SFML rendering object ( sf::RenderTarget ) to draw the entire data set. This method has a C-like interface waiting for a data pointer, and a std::size_t with the number of elements to draw.

Since the data is stored in the queue for some purposes, I will be glad if there is some way to get this pointer to the storage lying in the queue, instead of copying the data to a vector.
I know that std::queue adapts the std::deque container by default, but I don’t know how this circular buffer is implemented, and if its data is contiguous (so I can directly extract a pointer to the data).

EDIT: Performance

Looking at the answers below, let me say that I am not using std::deque because it is a fancy interface that looks like a queue, but since I really need a fast queue . Of course, I can use std::vector . If performance was not here, I would use push_back() and erase( begin() ) for the vector. But I need a fast queue and a way to efficiently move the data of this queue into rendering. . Of course, if balancing in the queue and trying to pull it out goes to the draw side, I will use std::vector .

+7
c ++ c ++ 11 containers c ++ - standard-library
source share
2 answers

Is it possible to get a pointer to the underlying storage std :: container of the queue container?

Short answer: None.

std::queue requires a type of SequenceContainer , for example std::deque or std::list . None of them guarantee continuous storage, so there is no concept of a pointer to the underlying storage.

If they use continuous circular buffers, this either imposes a fixed size on the container or entails a high cost (for example, std :: vector) when it is necessary to resize the container.

Instead, you can use boost::circular_buffer .

+10
source share

The most intuitive way would be to use std::vector as the underling container of your std::queue to provide continuous memory, and then take the address std::queue::front to access the continuous storage of the wrapped std::vector .

However, since @Blastfurnace correctly noted that std::vector does not have a member function pop_front , and when you are going to call std::queue::pop , the program will burst.

Also, as already mentioned, std::queue usually required as the main container, a container of type std::deque or std::list . Due to their structural features, these containers are the most suitable, because they can effectively use their front element. However, due to its contiguous memory, std::vector lacks such versatility.

Also, if using a container with contiguous memory is something that would greatly enhance your application, it is better and easier to use std::vector .

However, for recording, you can also do the following hack to get around the lack of the member function std::vector pop_front . You can define a class that inherits from std::vector and implement the member function pop_front , as shown 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; } 

Live demo

+1
source share

All Articles