Home > Back-end >  C overload >> operator with different interaction based on which side of >>
C overload >> operator with different interaction based on which side of >>

Time:12-27

I was wondering if it is possible to have overload the C >> operator in this way

Account& operator>> (double left, Account &right)
{
    right.deposit(left);
    return right;
}

Account& operator>> (Account &left, double right)
{
    left.withdraw(right);
    return left;
}

I was wondering if the >> operator had this functionality so I could do something like this

account1 >> 200 >> account2

Which would withdraw 200 from the first account and then deposit it into the second account.

CodePudding user response:

As described, this is not going to work for the following simple reason:

account1 >> 200 ...

When this gets evaluated this ends up calling the following overload:

Account& operator>> (Account &left, double right)

Your attention is drawn to the fact that this overload returns an Account &. That's declared right there, in black and white. Let's keep going:

... >> account2

And now, the left-hand side of this operator>> is now an Account &, what the overload returned. It is not a double anymore. And it needs to be a double in order for the other overload to pick up the slack, and bring it home. That's how overloaded operators work in C .

The simplest solution is probably to simply return a double value from the first overload:

double operator>> (Account &left, double right)
{
    left.withdraw(right);
    return right;
}

Now the result of this expression is a double value, which will have a much easier time getting the other overloaded operator>> to come into picture.

CodePudding user response:

As was pointed out, your operator>>() returns an Account& in both cases, i.e., you can't chain the operators as indicated. You could use them individually, though. However, it seems, that isn't intended.

You could achieve your effective goal by returning something like a Withdraw(account, amount) entity from operator>> (Account& account, double amount) and have the second operator be operator>> (Withdraw const& withdraw, Account&). The second operator would then trigger the transaction. Technically doable but I'm not convinced to that's the way to go.

#include <utility>

struct Account {
    double withdraw(double amount) { return amount; }
    double deposit(double amount) { return amount; }
};
struct Withdraw {
    Account& account;
    double   amount;
    double do_it() && { return account.withdraw(amount); }
};

void operator>> (Withdraw && left, Account &right)
{
    right.deposit(std::move(left).do_it());
}

Withdraw operator>> (Account &left, double right)
{
    return Withdraw{left, right};
}

int main() {
    Account a1, a2;
    a1 >> 200 >> a2;
}

Whether that approach is advisable I'm not so sure. I think I'd be confused by the code and would be better off with the operations being named. It may however, still be reasonable to build an operation object which is eventually executed as a transaction, combining multiple individual operations.

  • Related