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