In our project we use the c++ stream operator (<<) in our object model to print out an easy readible format of the data. A simplified example is this:
std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) {
oStream << "[SomeMember1: " << iOwnClass._ownMember1 << "]\n";
oStream << "[SomeMember2: " << iOwnClass._ownMember2 << "]\n";
}
Resulting in this in the logging:
[SomeMember1: foo]
[SomeMember2: bar]
What we want now is to be able to indent the result of that operator. Some calling class might not want the result like this, but want to add 2 spaces indention before each line. We could add a member to our class specifying the indention, but that does not seem to be an elegant solution.
Of course this is not a very big issue, but our logging would be so much nicer if this would work.
Thanks
This can be done using a custom stream-manipulator that stores the desired indentation-level in a word of the internal extensible array of the stream. You can request such a word using the function
ios_base::xalloc
. This function will give you the index of your word. You can access it usingios_base::iword
. One way to implement that would be this:You'd have to figure out where to store the
index
. This effectively allows you to add custom state to the stream (note that this would not be thread-safe out-of-the-box). Every function that wants indentation should add the requested indentation to the stream, and subtract it again when it is done. You could make sure this always happen by using a guard to add/subtract the desired indent (IMHO this is more elegant than using a manipulator):You could use it like this:
Not so good way to do this is to add a global variable, which tells the indentation. Something like this :
And then set it as appropriate.
You can make your own stream class that has an indentation variable and override the endl for that class, inserting the indentation.
The simplest solution is to slip a filtering streambuf between the
ostream
and the actual streambuf. Something like:To insert, just create an instance of the streambuf:
When
indent
goes out of scope, everything returns to normal.(For logging, I have one that is a bit more complex: the
LoggingOStreambuf
takes__FILE__
and__LINE__
as arguments, setsmyIndent
to a formatted string with these arguments, plus a time stamp, resets it to an indentation string after each output, collects all of the output in anstd::ostringstream
, and outputs it atomically tomyDest
in the destructor.)