Search code examples
c++vectorcollectionscontainers

How do you restrict `resize()` from being called after constructing a vector?


I'm building a class that exposes a sequential container, with a fixed length, but the length isn't known at compile-time.

So when an instance of my class is constructed, a parameter is passed in, to indicate how big the vector needs to be.

But the length needs to be fixed after construction.
I need to guarantee that the resize() function cannot be invoked, while still allowing other parts of my code to modify individual elements within the vector.
(In other words, I can't simply expose the vector as vector<T> const&)

The same goes for any other function which modifies the length, such as insert(), push_back(), etc.
These functions need to be restricted or hidden.

Is this possible?
Or do I really need to build my own fixed_vector wrapper class to hide the undesired functions?


Solution

  • Since C++20 you can return a std::span to the range in the vector. This allows access to the size and modifiable access to the elements, but not the vector's modifiers.

    For example:

    #include<vector>
    #include<span>
    
    class A {
        std::vector<int> vec;
    public:
        /*...*/
        auto getVec() {
            return std::span(vec);
        }
     };
    

    The return value can be used as a range, but there is no access to the container interface.

    Depending on the types and initialization required, you may also be able to use an array std::unique_ptr instead of a std::vector if you know the size won't change. However that doesn't store the size, which you would then need to store yourself:

    #include<vector>
    #include<span>
    
    class A {
        std::size_t vec_size;
        std::unique_ptr<int[]> vec;
    public:
        A(std::size_t size) : vec_size(size), vec(std::make_unique<int[]>(size)) { }
    
        auto getVec() {
            return std::span(vec, vec_size);
        }
     };
    

    This may be slightly more space efficient since it doesn't require accounting for a difference in vector size and capacity.