使用迭代器支持实现通用的固定大小数组

时间:2009-06-27 21:36:17

标签: c++ arrays templates iterator

我需要一个在编译时已知大小的数组。我知道我可以使用 std :: vector boost :: array 。但这并没有教我如何在内部工作。除了使用初始化程序之外,我还找不到如何将项添加到 boost :: array 中。我为通用数组编写了以下代码。我的目的是熟悉迭代器,模板特化等。以下是代码

template<typename T>
struct iterator_traits
{
    typedef T           value_type;
    typedef T&          reference_type;
    typedef T*          iterator;
    typedef const T*    const_iterator;
    typedef std::reverse_iterator<iterator> reverse_iterator;
};

template<typename T>
struct iterator_traits<T*>
{
    typedef T*          value_type;
    typedef T*&         reference_type;
    typedef T**         iterator;
    typedef const T     const_iterator;
    typedef std::reverse_iterator<iterator> reverse_iterator;
};

template<typename T, size_t size = 10>
class Array
{
    public:

        typedef typename iterator_traits<T>::value_type       value_type;
        typedef typename iterator_traits<T>::reference_type   reference_type;
        typedef typename iterator_traits<T>::iterator         iterator;
        typedef typename iterator_traits<T>::const_iterator   const_iterator;
        typedef typename iterator_traits<T>::reverse_iterator reverse_iterator;

        Array() : lastIndex(0) {
        }

        void add(value_type element) {
            if(lastIndex >= size)
                throw std::out_of_range("Array is full");
            array_[lastIndex++] = element;
        }

        reference_type at(unsigned int index){
            if(index < size)
                return array_[index];
            else
                throw std::out_of_range("Invalid index");
        }

        size_t capacity(){
            return size;
        }

        iterator begin(){
            return array_;
        }

        iterator end(){
            return array_ + size;
        }

        const_iterator begin() const{
            return array_;
        }

        const_iterator end() const{
            return array_ + size;
        }

        reverse_iterator rbegin() {
            return reverse_iterator(end());
        }

        reverse_iterator rend() {
            return reverse_iterator(begin());
        }

    private:

        value_type array_[size];
        unsigned int lastIndex;
};

以上代码效果很好。以下是我的问题

1 - 如何像 boost :: array 那样创建我的数组呢?像

这样的东西
Array<int> ints = { 10, 12 };

2 - 代码中是否有任何陷阱?

3 - 我必须对特征中的指针类型使用特化。这是最好的做法吗?

4 - 迭代器模式是否正确实现?

任何想法都会很棒!

3 个答案:

答案 0 :(得分:2)

boost :: array使用该语言的一个特性:没有构造函数的struct可以使用初始化列表。如果您提供自己的构造函数,则无法使用初始化列表。

此外,您使用iterator_traits错误。你的代码应该是

    // type definitions
    typedef T              value_type;
    typedef T*             iterator;
    typedef const T*       const_iterator;
    typedef T&             reference;
    typedef const T&       const_reference;
    typedef std::size_t    size_type;
    typedef std::ptrdiff_t difference_type;

iterator_traits用于迭代器的特征。此外,您可以只使用指针作为迭代器。 STL明确允许这样做。

答案 1 :(得分:2)

1 - 如何像boost :: array一样创建我的数组?像

这样的东西
Array<int> ints = { 10, 12 };

在c ++中,如果struct,union或c-style数组符合聚合条件,则只能(当前)使用大括号括起初始化列表。要做到这一点,根据标准:

8.5.1.1聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),并且没有虚函数(10.3)。

如果您想在当前标准中使用它们,则必须使您的类具有这些功能。下一个标准(参见here)包括允许其他类型这样做的规定。

2 - 代码中是否有任何陷阱?

这是一个:你不能将东西添加到提升列表的原因是它总是具有相同数量的元素(分配的大小)。在您的阵列中,您可以添加元素,但在构造期间,您仍然在引擎盖下构建了10个元素。如果用户不期望默认构造函数被调用10次,这可能会导致一些令人惊讶的结果。

答案 2 :(得分:1)

2 - 有任何陷阱吗?

我会摆脱默认大小“size = 10”。 10是什么使得数组的默认大小?我所看到的恰恰是有人意外地忽略了它的大小,并假设它比它大。

关于添加元素和C风格的初始化,我不相信它可以做到这两点。它在boost中工作,因为(我相信)该对象非常简单,是一个数组。它无法动态重新调整大小。该类只是将迭代器(以及其他糖类,如:: at())添加到普通数组中。