I usually implement the output operator for a class, operator<<()
.
I find it useful for debugging and regression testing purposes.
Occasionally when defining a class hierarchy with polymorphism in mind
I’ll instead define a virtual print()
method.
Base base; std::cout << "base = " << base << std::endl;
Here’s the typical implementation:
class Base { // ... public: /// print Base with flags indicating hw much extra to include virtual void print (std::ostream &out, int flags); }; std::ostream & operator<< (std::ostream &out, const Base &base) { base.print (out, 0); }
So everything is great except… I now want to pass that extra
argument. I could write the following ugly code:
std::cout << "base = "; base.print (std::cout, 1); std::cout << std::endl;
Instead, I’m going to follow the example from <iomanip>
and define a struct
that saves the arguments and then define an output operator for that
struct. The following code makes it so you can write the above as:
std::cout << "base = " << printstream (base, 1) << std::endl;
Here is the implementation of that. This expects the class to implement a method print()
that takes a std::ostream
and a second argument. It’s pretty easy to extend this to a print()
that takes a third argument.
#ifndef INCLUDED_PRINTSTREAM_H #define INCLUDED_PRINTSTREAM_H #include namespace printstream_impl { template struct PrintStream1 { const ObjectType & m_object; const Arg1Type & m_arg1; PrintStream1 (const ObjectType &object, const Arg1Type &arg1) : m_object (object), m_arg1 (arg1) { } std::ostream &print (std::ostream &out) const { m_object.print (out, m_arg1); return out; } }; template std::ostream &operator<<(std::ostream &out, const PrintStream1 &ps) { ps.print (out); return out; } } // End namespace printstream template printstream_impl::PrintStream1 printstream (const ObjectType &object, const Arg1Type &arg1) { return printstream_impl::PrintStream1 (object, arg1); } #endif /* INCLUDED_PRINTSTREAM_H */