代码之家  ›  专栏  ›  技术社区  ›  stefaanv

如何实现一个大小有限的stl-like容器?

  •  3
  • stefaanv  · 技术社区  · 15 年前

    重构时,我想更改一个数组,在该数组中,条目被添加到std::vector,但是为了兼容性(持久性、降级等),它仍然需要有一个上限。
    最好的方法是什么(优雅的,类似STL的,有限的额外代码)拥有一个大小有限的类似STL的容器,所以您知道插入一个条目失败了吗?

    编辑 :
    澄清一下:我想要一个类似STL的容器,它开始是空的,可以用条目填充,也可以删除条目,并且迭代已填充的条目,但这不允许放入超过50个条目,所以几乎像一个连续的反向器,但有一个上限。

    6 回复  |  直到 15 年前
        1
  •  5
  •   David Rodríguez - dribeas    15 年前

    一个简单的解决方案是将一个向量封装在自己的有限大小的容器中。您可以使用私有组合或私有继承——请注意私有继承模型 在以下方面实施 而且没有一些公共继承的缺点。

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

    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或用特定的测试实现适配器。

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

        2
  •  3
  •   Hemant    15 年前

    自定义Vector类以施加上限。 可能,您可以公开一个新的API,它将根据上限检查大小,如果超过上限,则返回false,否则调用常规插入方法。

        3
  •  2
  •   sbi    15 年前

    看一看 this static_vector implementation 我不久前发现的。我想这正是你想要的。

    它是在非常自由的提振许可下发行的,所以你可以用它做任何事情。

        4
  •  2
  •   Potatoswatter    15 年前

    您可以创建自定义分配器(例如,派生自 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.
    }
    
        5
  •  1
  •   dirkgently    15 年前

    看一看 Boost.Array

    作为普通数组的替代,STL提供了std::vector类。但是,std::vector<gt;提供了动态数组的语义。因此,它管理数据以能够更改元素的数量。这会导致一些开销,以防只需要静态大小的数组。

        6
  •  1
  •   dimba    15 年前

    看看boost::array

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