The C++ standard imposes restrictions on operator[]
:
[over.sub]: operator[]
shall be a non-static member function with exactly one parameter. It implements the subscripting syntax
(...) a subscripting expression x[y]
is interpreted as x.operator[](y)
(...)
But the single argument doesn't need to be a scalar. For example:
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
}
};
You can then use this list as explected:
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
Online demo
However, C++ is not python, so the readers of your code will be very confused by the syntax of (2) and (3). Moreover, I'm not a python expert but I understand that slice operator can be more tricky than that, since there could be start, stop and step and any of those components can be missing.
So I'd recommend not to use a pair as an argument, but create your own slice operator parameters. You could then work on different constructors and default parameters. It could then look like:
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
But since this would still be quite an unusual indexing scheme, with a view to the principle of least astonishment, I'd strongly recommend to go for the C++ usual practice and simply define the right member functions, e.g. `
l.slice(3,5);
This will be self-documenting, without surprise, and easily digested, since it is close to well known semantics of string::substr()