2

I am trying to figure out the best c++ container before I decide to define my own data structure.

Here is What I am trying to do : enter image description here

For example, In Vectors (C++) Is there any way to fix the size so that I can keep pushing and popping elements from one end and if I push more elements than the size, It should automatically remove the old elements from front.

If not vectors, any thing else ?

Severus Tux
  • 265
  • 3
  • 13
  • 1
    The Boost Library has [`boost::circular_buffer`](https://www.boost.org/doc/libs/1_66_0/doc/html/circular_buffer.html) – jogojapan Mar 31 '18 at 08:48
  • @jogojapan Thanks! , I think that's exactly what I wanted. But Can I dynamically change the size if required ? . i.e, After using size 7 circular buffer for a while, If I wanted it to resize it to hold 9 elements and continue its behaviour , is it possible ? – Severus Tux Mar 31 '18 at 08:56
  • Yes, definitely. The Boost version has a [`resize()`](https://www.boost.org/doc/libs/1_66_0/doc/html/boost/circular_buffer.html#idp39122944-bb) function. And if you implement the circular buffer yourself, you just have to make sure you use an underlying data structure that is flexible in size, e.g. a `std::vector` rather than a `std::array`. – jogojapan Mar 31 '18 at 09:04
  • Possible duplicate of [limit size of Queue in C++](https://stackoverflow.com/questions/1273026/limit-size-of-queuet-in-c) – xskxzr Mar 31 '18 at 09:12
  • @xskxzr: Beware, for the highest voted answer of that question is terrible (I just downvoted it). However, the accepted answer is correct (so I just upvoted it). – Christian Hackl Mar 31 '18 at 09:56

1 Answers1

4

There is no such container in the C++ standard library, but you can easily create your own by wrapping an existing container. std::deque may be appropriate, because it's designed to allow fast insertion and deletion at both ends.

template <class T, int MaxSize>
class CircularContainer
{
static_assert(MaxSize >= 0);

public:
    void Add(T const& t)
    {
        if (MaxSize > 0)
        {
            if (size(data) == MaxSize)
            {
                data.pop_front();
            }
            data.push_back(t);
        }
    }

// ...

private:
    std::deque<T> data;
};

There are a lot of design decisions to make here, for example:

  • Should be the maximum size be completely static, set in the constructor or possibly be modifiable even after a container object has been created?
  • Which iterators and references to elements are allowed to become invalid by operations like Add?
  • Which parts of the wrapped container's interface does your container need to expose? Does it need its own iterator classes, does it have to work with range-based for loops, and so on.
  • Do you wish to allow a maximum size of zero, and do you need to optimise the corresponding checks with template specialisation or constexpr if?
  • Should the wrapped container class itself be a template parameter, just like std::stack does it?

Most of those design decisions will depend on whether the container will be used in library code or in application code.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62