How should a size-limited stl-like container be implemented?

前端 未结 6 1880
生来不讨喜
生来不讨喜 2020-12-07 04:09

While refactoring, I wanted to change an array where entries are added to an std::vector, but for compatibility (persistency, downgrading,...), it still needs to have an upp

6条回答
  •  萌比男神i
    2020-12-07 04:47

    A simple solution would be encapsulating a vector inside your own limited size container. You could use private composition or private inheritance --note that private inheritance models implemented in terms of and does not have some of the shortcomings of public inheritance.

    EDIT: Sketch of the solution with private inheritance

    template 
    class fixed_vector : std::vector
    {
        typedef std::vector vector_type;
    public:
        typedef typename vector_type::reference reference;
        typedef typename vector_type::const_reference const_reference;
        typedef typename vector_type::iterator iterator;
        typedef typename vector_type::const_iterator const_iterator;
        typedef typename vector_type::value_type value_type;
        typedef typename vector_type::size_type size_type;
    
        fixed_vector() : vector_type() {}
        fixed_vector( size_type size, value_type const & value = value_type() )
           : vector_type(size,value)
        {}      
    
        void push_back( value_type v ) {
            ensure_can_grow();
            vector_type::push_back( v );
        }
        iterator insert( iterator position, value_type const & v ) {
            ensure_can_grow();
            vector_type::insert( position, v );
        }
        void reserve( size_type size ) {
            if ( size > N ) throw std::invalid_argument();
            vector_type::reserve( size );
        }
        size_type capacity() const {
            // In case the default implementation acquires by default 
            // more than N elements, or the vector grows to a higher capacity
            return std::min( vector_type::capacity(), N );
        }
        // provide other insert methods if required, with the same pattern
        using vector_type::begin;
        using vector_type::end;
        using vector_type::operator[];
        using vector_type::erase;
        using vector_type::size;
        using vector_type::empty;
    private:
        void ensure_can_grow() const {
            // probably a different exception would make sense here: 
            if ( this->size() == N ) throw std::bad_alloc();
        }
    };
    

    There is quite a bit of hand-waving there... std::vector take more arguments that could be added to the façade. If you need any of the other methods or typedefs, you can just bring them into scope with a using declaration, redefine the typedef, or implement the adaptor with your particular test.

    Also, in this implementation the size is a compile time constant, but it would be really simple to modify it into a constructor parameter.

提交回复
热议问题