Home > Blockchain >  How to overload 2 versions of operator<< in a C class
How to overload 2 versions of operator<< in a C class

Time:08-18

I am overloading operator<< as follows :

std::ostream& operator<<(std::ostream& o, const MyClass& myobj);

Now, I would like to have 2 versions of operator<<, one that would display a short description of my object, and another that would display a longer version.

For example, MyClass could contain information about a client. In the short version I would display just the name, and in the long version I would display more details like birthday, address, etc.

Is there a way to do that in C ?

I know I could have a method of MyClass that receives the stream, but it would be called like this :

myObj.DisplayShort(cout)

or

myObj.DisplayLong(cout)

but I would like to stay with a syntax similar to the usual form :

cout << myObj << endl;

CodePudding user response:

The standard way is to create a custom formatting flag and a custom manipulator using std::ios_base::xalloc and std::ios_base::iword.

So you have

class MyClass {
   static int fmt_flag_index;
   enum fmt_flag { output_short, output_long };
}

You initialize fmt_flag_index somewhere at the program startup:

int MyClass::fmt_flag_index = std::ios_base::xalloc();

Here's your custom formatting flag ready to use. Now IO manipulators can set it:

std::ios_base& myclass_short(std::ios_base& os)
{
    os.iword(MyClass::fmt_flag_index) = static_cast<int>(MyClass::output_short);
    return os;
}

std::ios_base& myclass_long(std::ios_base& os)
{
    os.iword(MyClass::fmt_flag_index) = static_cast<int>(MyClass::output_long);
    return os;
}

And operator<< access it:

std::ostream& operator<<(std::ostream& os, MyClass& f)
{
   switch (static_cast<MyClass::fmt_flag>(os.iword(MyClass::fmt_flag_index)))
   {
     case MyClass::output_short: ...;
     case MyClass::output_long: ...;
   }
}

Use it like this:

MyClass myobj;
std::cout << myclass_long << myobj;
std::cout << myclass_short << myobj;

CodePudding user response:

I would use a printing adaptor:

class Adaptor
{
    MyClass &adaptee;
    operator <<
}

And then you can implement different logic based on:

  • Multiple adapter classes
  • Single adapter class with a data member
  • Single adapter class with a template argument
  • Related