5

当我打电话时:a7[0][1][100];

我能够获得第一个索引0operator[]但作为索引,我将无法以递归方式获得其他索引值 1 和 100。我如何能够使用operator[]以获得递归的以下索引值。在此示例中,对于 3 维数组,operator[]仅对第一个维度(即 )调用一次0

我的示例代码如下:

template <class T, unsigned ... RestD> struct array;

template <class T, unsigned PrimaryD>
struct array <T, PrimaryD> {
    typedef T type[PrimaryD];

    type data;

    T& operator[] (unsigned i) {
        return data[i];
    }
}; 

template <class T, unsigned PrimaryD, unsigned ... RestD>
struct array <T, PrimaryD, RestD...> {
    typedef typename array<T, RestD...>::type OneDimensionDownArrayT;
    typedef OneDimensionDownArrayT type[PrimaryD];

    type data;

    OneDimensionDownArrayT& operator[] (int i) {
        OneDimensionDownArrayT& a = data[i];
        return a;
    }
}; 

int main () {

    array<int, 1, 2, 3> a7 {{{{1, 2, 3},{4, 5, 6}}}};
    a7[0][1][2] = 100; //=>won't recursively go through operator[]
                     //I want to recursively  obtain 0, 1 and 2 as index values

    a7[0][1][100] = 100; //also works correctly.
    std::cout << a7[0][1][100] << std::endl;

    return 0;
}
4

2 回答 2

1

这里的错误其实有点微妙,换行

   typedef typename array<T, RestD...>::type OneDimensionDownArrayT;

   typedef array<T, RestD...> OneDimensionDownArrayT;

这样做的原因是因为array<int, 1, 2, 3>::typeequals array<int, 2, 3>::typewhich 等于array<int, 3>::typewhich is int。最后你得到array<int, 1, 2, 3>::OneDimensionDownArrayTequal to int[2][3]。这就是为什么您在重载的 operator[] 中只下降一级的原因,因为它返回一个实际的整数数组。您可以通过添加 main 方法来亲自查看:

        auto & e1 = a7[0];
        auto & e2 = e1[0];
        auto & e3 = e2[1];
        auto & e4 = e3[2];
        e4 = 100;

而不是一次访问它们。然后使用调试器单步执行并检查 e1-e4 的类型。e1 将有 typeint (&) [2][3]而不是array<int, 2, 3> &.

要在堆上而不是在堆栈上分配这些,请在您的类中声明指向您的指针OneDimensionDownArrayT而不是它们的数组,定义构造函数和析构函数来处理分配/释放数组。它可能看起来像这样:

    template <class T, unsigned PrimaryD, unsigned ... RestD>
    struct array <T, PrimaryD, RestD...> {
        typedef typename array<T, RestD...>::type OneDimensionDownArrayT;

        array():data(new OneDimensionDownArrayT[PrimaryD]){}
        ~array() {
            delete[] data;
        }

        OneDimensionDownArrayT * data;

        OneDimensionDownArrayT& operator[] (int i) {
            OneDimensionDownArrayT& a = data[i];
            return a;
        }
    };

您还需要为您的类定义一个复制构造函数、移动构造函数和赋值运算符。这种实现将在堆栈上占用更少的空间,但总体上会稍微多一些内存,因为指针和数组本身也需要空间。

于 2013-05-20T21:39:25.050 回答
1

如果你想[]连续使用一个多维数组的运算符,那么每个运算符都[]必须返回一个(少一维)数组。

如果您的多维数组类型是:

template <class Type, int dim> MArray;

然后 aMArray<SomeType, n>::operator[]必须返回 a MArray<SomeType, n-1>。对于返回对象(最好是引用)的特殊一维数组或返回本机一维数组的二维数组的特殊情况。此示例使用了过于简单的表示法,但关键是 nD [] 运算符返回 (n-1)-D 数组。

于 2013-05-20T22:38:33.180 回答