2

I want to implement puthon list in cpp, bug do not fin a way to implement pyton's slice operator, e.g.:

list[3:7]   // sublist including item 3 included to item 7 excluded

As colon is not an operator in cpp, we cannot overload it. So I changed my implementation to use an overloadable comma, e.g. list[3,7]. I think I first need to overload comma operator and then overload [ ] operator

But I am getting error while overloading [ ] with 2 integers:

Error is : operator[](int, int) must have exactly one argument   

Please help me solve the issue.

4
  • 1
    I'm afraid you cannot get any of the syntaxes. You are correct that operator : cannot be overloaded, but to overload on , operator you would need a class object (or enum) - you cannot provide operator overloads for primitive types like ints. If you can live with list(3, 7) or list[{3, 7}], this could be done. Commented May 8, 2021 at 19:44
  • The closest you can come to what you want is overloading operator() Commented May 8, 2021 at 19:48
  • This is not easy... the only option is using slices in rangev3 Commented May 8, 2021 at 19:52
  • Indeed, the duplicate is not appropriate: it's not about a 2D index but about slicing, which is also dificult because lower or upper operand could be missing. Commented May 8, 2021 at 19:52

1 Answer 1

1

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()

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.