重载多维括号

时间:2016-03-23 17:15:55

标签: c++ operator-overloading brackets square-bracket

如何重载多维括号?

我们说我有一个类可以让我访问 n - 向量空间中的点。例如:

class NSpaceVector {
    private:
        int vectorSpace[8][8][8][8][8][8][8];
    public:        
        const NSpaceVector operator[][][][][][][](int i, int j, int k, int l, int m, int n, int p)const {return vectorSpace[i][j][k][l][m][n][p]; }
        NSpaceVector operator[][][][][][][](int i, int j, int k, int l, int m, int n, int p) {return vectorSpace[i][j][k][l][m][n][p]; }
}
unsigned long & operator [](int i) {return registers[i];}

我想要做的是重载括号运算符,以便我可以像这样索引到这个位置:

int main() {
    NSpaceVector nsv; // Assume initializes all to 0
    nsv[2][4][7][4][0][7][6] = 2;
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2
    cout << nsv[1][4][7][4][0][7][6] << endl; //-> 0
    return 0;
}

我无法编译。有任何想法吗? Thx,Keith:^)

2 个答案:

答案 0 :(得分:1)

  

有什么想法吗?

只有选项可以为每个级别重载operator[](),并让返回类型有另一个operator[]()重载。

正如评论中所提到的,这通常是通过重载调用operator()

来解决的
int operator()(size_t dim1, size_t dim2, ... size_t dimn);  

答案 1 :(得分:1)

标准答案是让每个[](从左到右)返回正确嵌套子集的代理,其中最后一个实际返回对数据的引用。在您的方案中,最简单的方法是将嵌套类型模板化以自动化生产。

正如神秘的用户4581301所提到的,它提供起来要简单得多

nsv(2,4,7,4,0,7,6)

您所需类的示例模板生成可能比使用临时代理对象更简单:

template <size_t Width, size_t Depth, typename T=int>
struct SubSpace;

template <size_t Width, typename T>
struct SubSpace<Width,0,T> {
    std::array<T, Width> array;

    T& operator[] (size_t i) { return array[i]; }
    T const& operator[] (size_t i) const { return array[i]; }
};

template <size_t Width, size_t Depth, typename T>
struct SubSpace {
    using Nested = SubSpace<Width, Depth-1, T>;
    std::array<Nested, Width> array;

    Nested& operator[] (size_t i) { return array[i]; }
    Nested const& operator[] (size_t i) const { return array[i]; }
};


using NSpaceVector = SubSpace<8,6>;

int main()
{
    NSpaceVector nsv;
    nsv[2][4][7][4][0][7][6] = 2;
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2
}

注意,这并不是默认初始化数组成员,但我们仍然可以使用聚合初始化:

    NSpaceVector nsv {}; // value-initialize every element
    nsv[2][4][7][4][0][7][6] = 2;
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2
    cout << nsv[2][4][7][4][0][7][5] << endl; //-> 0

另请注意,SubSpace<8,6>给出了您想要的8x7结果,因为深度终止于0.这可以使用顶层包装器进行清理,但我不愿意在Depth==1上终止当某人偶然实例化SubSpace<0,0>时,一切都会出错。

更简单,取决于您是否希望班级中的任何行为,是这样的:

struct OtherSpaceVector {
    int s[8][8][8][8][8][8][8];

    auto operator[] (size_t i) -> decltype(s[i]) { return s[i]; }
};

int main()
{
    OtherSpaceVector osv{};
    osv[2][4][7][4][0][7][6] = 2;
    std::cout << osv[2][4][7][4][0][7][6] << '\n'; 
    std::cout << osv[2][4][7][4][0][7][5] << '\n';
}

更难改变尺寸,感觉比模板版本更脆弱,但它仍适用于您提供的用例。