Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Can I overload the bracket [] operator to do different things if it on the LHS vs RHS of an assignment?

Tags:

I am looking to accomplish the following:

int x, y, z;

  1. foo[x] = y; acts like do_this(x,y);

  2. z = foo[x]; acts like z = do_that(x)

I can accomplish the first with a Foo class and a Helper class, where the operator[] returns by value a Helper class constructed with x, and the operator= for the Helper class is defined to run do_this(this->x, y). Like below:

class Foo {
    public:
    Helper operator[](int x) { 
        return Helper(x);
    }
};

class Helper {
    public: 
    Helper(x) {
        this->x = x;
    }
    void operator=(int y) {
        do_this(this->x, y);
    }
    private:
    int x;
};

What I can't figure out is how to accomplish (2). Is there a way to overload the operator[] so that it knows if it was used on the lhs vs the rhs?

like image 544
lord_copperfield Avatar asked Jul 25 '20 20:07

lord_copperfield


People also ask

Can [] operator be overloaded?

An overloaded operator (except for the function call operator) cannot have default arguments or an ellipsis in the argument list. You must declare the overloaded = , [] , () , and -> operators as nonstatic member functions to ensure that they receive lvalues as their first operands.

How do you overload the operator?

Overloading Binary Operators Suppose that we wish to overload the binary operator == to compare two Point objects. We could do it as a member function or non-member function. To overload as a member function, the declaration is as follows: class Point { public: bool operator==(const Point & rhs) const; // p1.

Can we overload equal to operator in C++?

You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor. Following example explains how an assignment operator can be overloaded.

Can we overload address of operator?

It is not possible to change the precedence, grouping, or number of operands of operators. The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.


1 Answers

Yes - give your Helper class a conversion function to int:

class Helper {
    public: 
    Helper(x){
        this->x = x;
    }
    Helper& operator= (int y) {
        do_this(this->x, y);
        return *this;
    }
    operator int() const {
        return do_that(this->x);
    }
    private:
    int x;
};

This will also allow other uses like product *= foo[x]; or func_taking_int(foo[x]), etc.

One potential catch is that some uses of auto or function templates would still just keep the type Helper, which might not be what's wanted - so users of Foo should still understand that this proxy sugar is going on. It could also be helpful to have some alternative syntax to explicitly get the int value for cases like that, in either Foo or Helper.

like image 126
aschepler Avatar answered Oct 12 '22 02:10

aschepler