0

An operator can be declared only for the syntax defined for it in the C++ grammar. For example, one can’t define a unary % or a ternary +.

Consider the output operator for a class A. It has the following signature as a non-member:

ostream& operator<<(ostream&, A&);

This signature can't be changed. operator<< is a binary operator. Ie, it can take only 2 arguments.

The same is the case with the corresponding >> operator.

In certain situations, this can be restrictive, since it doesn't give the user of this operator, the required flexibility.

For example, consider a class Money used to store a monetary amount and its output operator:

ostream& operator<<(ostream&, Money&);

Since a monetary value is involved, we need to display the currency symbol also, which could be either the local or international symbol. If the user should be able to specify this, we would need the above operator to have another parameter, say bool intl. The operator's signature would then be:

ostream& operator<<(ostream&, bool intl, Money&);

Of course, this isn't possible, since the signature is fixed.

How can we proceed in such a situation?

Thanks.

SSteven
  • 733
  • 5
  • 17
  • 2
    I'm not going to rehash all the how-to for you in an answer, but in short you can add custom io manipulators - see e.g. [this answer](https://stackoverflow.com/a/799877/410767) and research the Standard Library functions it mentions. – Tony Delroy Jan 16 '18 at 11:31
  • A good suggestion. I shall be considering this option too. – SSteven Jan 16 '18 at 11:37

2 Answers2

1

How about making some kind of tag-structure that can be used for overloading the operator? Like e.g.

ostream& operator<<(ostream&, LocalMonetaryType);

Then you can do e.g.

std::cout << LocalMonetaryTypeInstance << YourMoneyObject;

Could be refined so that you use a Money member function to get the tag object, and it then contains the expected symbol to be written.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • This suggestion is worth working on. There are 2 options: (1) LocalMonetaryType could be a wrapper to Money, encapsulating the bool intl arg also. (2) Use tag-dispatch. This may not be workable, because a tag couldn't encapsulate the Money instance. Option (1) is workable, I think. – SSteven Jan 16 '18 at 11:24
0

If a Money is a class it should have a bool intl as a member field. So in that case operator will still have proper definition. It will be even better to define enum for that, example code:

class Money
{
public:
  MonetaryEnum localCurrency;
  double amount;

  friend ostream& operator<< (ostream& os, const Money& m);
}

ostream& operator<<(ostream& os, const Money& m)
{
    os << enumToString(localCurrency) <<  m.getAmount() << std::endl;
    return os;
}

and you will be able to provide desired behaviour. It is only example :)

wdudzik
  • 1,264
  • 15
  • 24
  • No. The bool intl parameter isn't stored with the class itself. It is only a function parameter. This is because the currency involved is stored within the locale that is used, rather than in the Money class. – SSteven Jan 16 '18 at 11:19
  • So it might be good to reconsider storing currency within Money class. As money without currency migth make little sense because amount is meaningless without currency in real world. Just a sugestion – wdudzik Jan 16 '18 at 11:25
  • What you say is correct. However, the example I am considering involves storing the currency symbol in the locale. The correct locale would be matched with the appropriate Money instance - that is the programmer's responsibility. Also, for a specific symbol (say, USD), there are 2 display options: $ (ie, local) or USD (ie, international) – SSteven Jan 16 '18 at 11:29