如何实现一个大小有限的类似stl的容器?

时间:2010-08-25 07:12:55

标签: c++ stl refactoring

在重构时,我想更改一个数组,其中条目被添加到std :: vector,但是为了兼容性(持久性,降级,......),它仍然需要有一个上限。
有一个类似stl的容器的最佳方式(优雅,类似stl,有限的额外代码)是多么有限,所以你知道插入一个条目失败了吗?

修改
为了澄清:我想要一个类似stl的容器,它开始为空,你可以填充条目并可能删除条目并迭代填充的条目,但这不允许输入超过例如50个条目,所以几乎像一个顺序的对手,但有一个上限。

6 个答案:

答案 0 :(得分:5)

一个简单的解决方案是将矢量封装在您自己的有限大小容器中。您可以使用私有组合或私有继承 - 注意私有继承模型的形式实现,并且没有公共继承的一些缺点。

编辑:具有私有继承的解决方案草图

template <typename T, unsigned int N>
class fixed_vector : std::vector<T>
{
    typedef std::vector<T> 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();
    }
};

那里有相当多的挥手...... std::vector采取更多可以添加到外墙的论据。如果您需要任何其他方法或typedef,您可以使用using声明将它们放入范围,重新定义typedef,或者使用您的特定测试实现适配器。

此外,在此实现中,size是编译时常量,但将其修改为构造函数参数非常简单。

答案 1 :(得分:3)

自定义矢量类以施加上限。 也许你可以暴露一个新的api,它将检查大小与上限的关系,如果超过则返回false,否则调用常规插入方法。

答案 2 :(得分:2)

您可以创建一个自定义分配器(例如派生自std::allocator),拒绝分配大于给定大小的数组。

请注意,在向其添加内容之前,您需要在生成的对象上调用reserve( vector_max )。我提出了一个针对C ++标准的缺陷,因为这个要求应该是不必要的(在最近的GCC版本中也是如此)。

template< typename T, size_t N >
struct limited_alloc : std::allocator< T > {
    size_t max_size() const { return N; }
    typename std::allocator<T>::pointer allocate( size_t n ) {
        if ( n < N ) return std::allocator<T>::allocate( n );
        throw std::length_error( "array too large" );
    }

    limited_alloc() {} // silly cruft for standard requirements:
    template< typename T2 >
    limited_alloc( limited_alloc<T2,N> const & ) {}
    template< typename T2 >
    struct rebind { typedef limited_alloc<T2,N> other; };
};

enum { vector_max = 40 };

template< typename T >
struct limited_vector {
    typedef std::vector< T, limited_alloc< T, vector_max > > type;
};

void f() {
    limited_vector< int >::type x;
    x.reserve( vector_max );
    x.assign( vector_max + 1, 3 ); // throws.
}

答案 3 :(得分:2)

看看我刚才发现的this static_vector implementation。我认为它完全符合您的要求。

它是在非常自由的增强许可证下发布的,所以你可以用它来做任何事情。

答案 4 :(得分:1)

查看Boost.Array

  

作为普通数组的替代,STL提供了类std :: vector。但是,std :: vector&lt;&gt;提供动态数组的语义。因此,它管理数据以便能够改变元素的数量。如果只需要具有静态大小的数组,这会产生一些开销。

答案 5 :(得分:1)

看一下boost :: array

编辑:对于添加/删除boost :: optional可以用作boost :: array的元素类型。