helloB helloB - 1 month ago 6
C++ Question

Unintrusive way to enforce size constraint on std::vector?

I want to have a certain kind of

std::vector
that cannot have more than
const int MAX_LENGTH
elements. I understand that I cannot override
std::vector
non-virtual functions, which I'd need to do to put a size check in all the relevant member functions (e.g.,
assign
,
push_back
...there are so many). The most obvious way to do this is to wrap
std::vector
in a
class
that ensures no operation adds beyond the maximum length. But this seems clunky. Is there a more elegant solution than a wrapper class to limit std::vector size?

Answer

Are you sure that the vector itself can't grow, or that merely the consumers of such a vector need to limit the size of the arguments? If it's the latter, then simply assert(arg.size() <= MAX_LENGTH) where needed, document it, and be done. Otherwise, read on.

A std::vector can have unlimited size. If you limit that size, it's not a std::vector anymore. So, you cannot publicly derive from std::vector and limit the size without breaking the Liskov Substitution Principle. The derived class is still a vector, but doesn't act as one, and can't be used as one, and such an interface will thoroughly confuse your users, and the compiler will not catch serious usage bugs that will ensue. It's a bad idea.

The best you can do is to privately derive from vector, or have-a vector as a member, and expose all of the vector's interfaces while enforcing the size. Such a vector must not be convertible to std::vector, although obviously you can allow it to be copied or moved to a std::vector. It'll still perform just as well as a vector would, will still allow access via iterators, etc.

We're talking of a very small class, and its implementation simply has to follow the standard (or at least the cpp reference), you're leaving all the real work to the private std::vector. So that's not clunky, that's the only sane way to do it.