C++ 标准对以下内容施加了限制operator[]
:
[over.sub]: operator[]
应该是一个只有一个参数的非静态成员函数。它实现了下标语法
(...) 下标表达式x[y]
被解释为x.operator[](y)
(...)
但单个参数不需要是标量。例如:
struct mylist {
vector<int> oops { 3,5, 7, 9};
int& operator[] (size_t i) {
cout << "indexing overload"<<endl;
return oops[i];
}
mylist operator[] (pair<int, int>p) {
cout << "slicing overload from "<<p.first<<" to "<<p.second<<endl;
return mylist(); // just for proof of concept
}
};
然后,您可以按预期使用此列表:
mylist l;
cout<< l[2] <<endl; // (1) traditional indexing
l[make_pair(3,5)]; // (2) will invoke the slice version
l[{4,8}]; // (3) slice version as well
在线演示
但是,C++ 不是 python,所以你的代码的读者会对 (2) 和 (3) 的语法感到非常困惑。此外,我不是 python 专家,但我知道切片运算符可能比这更棘手,因为可能存在启动、停止和步进,并且任何这些组件都可能丢失。
所以我建议不要使用一对作为参数,而是创建自己的切片运算符参数。然后,您可以处理不同的构造函数和默认参数。它可能看起来像:
l[myslice(3, 5)]; // myslice is a class
l[myslice(3, 4, 2)];
l[mysliceto(5)]; // mysliceto could be a function returning a myslice
// that is constructed using a default value for start
但是由于这仍然是一个非常不寻常的索引方案,考虑到最小惊讶的原则,我强烈建议采用 C++ 通常的做法并简单地定义正确的成员函数,例如 `
l.slice(3,5);
这将是自记录的,毫不奇怪,并且易于消化,因为它接近于众所周知的语义string::substr()