简体   繁体   中英

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 (eg, 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?

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.

Since C++11, custom allocators are permitted to have state (previous to C++11, custom allocators had to be stateless). Each C++ container that takes a custom allocator stores an instance of it.

Your allocator can then detect whether or not it has already fulfilled a request for the maximum allotment, and throw otherwise.

#include <vector>
#include <string>
using namespace std;

template <typename T, typename A>

void add_or_throw(std::vector<T,A> &vec, int max, T value)
{
    if (vec.size() < max)
    {
        vec.push_back(value);
    }else{
        throw length_error("vecor too beaucoup");
    }
}

int main() {
    std::vector<std::string> v;
    add_or_throw(v, 2, string("hi"));
    add_or_throw(v, 2, string("there"));
    add_or_throw(v, 2, string("man!"));

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM