c++vectorstdvector

What prevents the subclassing of vector<> and having at() or operator[] resize the array if necessary?


What prevents the subclassing of vector<> and overriding at() or operator[] to resize the array if necessary? Specifically I'd like code to work like this:

MYvector<int> v;
v[3] = 1;

would be equivalent to:

vector<int> v;
if ( v.size() <= 3 )
    v.resize( 3 + 1 );
v[3] = 1;

I looked into this when vector<> first was standardized and concluded that vector<> simply wasn't designed to be subclassed, due to no methods being virtual. However, the above modification is still technically possible.

To be clear it's something I'd do it if were basically one new virtual method to write, but not worth doing if I then need to make dozens of other definitions (friend functions? iterators?) as well.

Dialect would be C++17 or C++20, though discussion of earlier or later dialects or vendor dialects would also be of high interest.


Solution

  • The strong consensus is that changing the meaning of the existing operators would lead to confusion or subtle bugs:

    1. someone changing a few lines will assume the obvious code does obvious things and they'd be wrong

    2. when a MYvector is passed in to a function accepting std::vector and lexically identical code produces different results on the same variable in different parts of the software (due to no vector methods being virtual).

    3. one might accidentally trigger the augmented functionality without intending to.

    That said, having a lot of repeats of the if size < x resize; [] paradigm is itself open to typos and errors and makes some code substantially more verbose than it could otherwise be.

    The solution is therefore to implement the new functionality with a new method name.

    Some suggest that having a few such novel methods would be "confusing" to code maintainers, but it's hard to think of a body of code so simple it could be maintained, but for this putative confusion. This cost, however minimal, must be balanced against the benefit, however minimal, of having these compound operations. In the project in question, the break-even for the benefit to the maintainer, minus the cost to the maintainer, may be as low as a single maintenance task.

    template <class T>
    class MYvector: public std::vector<T> {
    public:
        // sizi short for "SIZe as Int."  Prevents
        // int type mismatch errors.
        int sizi() {
            return (int) size();
        }
        void grow( size_t i ) {
            if ( size() <= i )
                resize( i + 1 );
        }
        T& at_grow( size_t i ) {
            grow( i );
            return at( i );
        }
        T& get_emplace_back() {
            emplace_back();
            return back();
        }
    };