如何重载多维括号?
我们说我有一个类可以让我访问 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:^)
答案 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';
}
更难改变尺寸,感觉比模板版本更脆弱,但它仍适用于您提供的用例。