std::deque is defined fairly carefully to be a linear queue. Its design isn't really suitable for a circular queue.
In particular, it breaks the queue up into a number of equal-sized blocks, so if the queue is reasonably balanced (i.e., on average, data is being consumed about as fast as it's being produced) you'll normally have blocks being discarded and ready for re-use, so you can use one for a long time with minimal heap fragmentation.
To accomplish that, a deque (at least normally) uses a two-level storage mechanism. That is to say, it has an expandable array of pointers, each pointing to an equal-sized block that contains the actual data.
For a circular buffer, however, that's pointless and unnecessary. With a circular buffer, you normally allocate a block of memory when you create it, and continue to use that same block of memory until you destroy it. In this case, the two-level storage used by a deque simply adds an extra level of indirection to every access without accomplishing anything useful.
For a circular buffer, you might as well using a single, flat chunk of memory to hold your data, and just create/destroy objects in that block of memory. Here's a simple implementation I wrote some time ago:
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
~circular_buffer() {
// first destroy any content
while (in_use != 0)
pop();
// then release the buffer.
operator delete(data);
}
};
#endif