Stream manipulators in C++
July 7, 2017 · 3 minutes to read · C++
In C++ language, output streams are a nice way to display information in console. There are some caveats we can talk about - like bufferization, statefulness - but it is not the goal of this article.
Streams have a cool feature to format output (and input) called manipulators. Some of them:
- flush / endl
- oct / dec / hex
- boolalpha / noboolalpha
- setw() / setfill()
An interesting question is: can we add our owns manipulators? Yes we can! And this is the purpose of this post.
In this article, I use
std::locale::facet which is a feature of localization library. Its primary goal is to help to format output according to a selected locale.
facet is not intended to be used to create manipulators. But it is a fun (and useful) way to format data on standard streams.
std, manipulators set parameters directly on streams throught methods. We had to find a way to save a status without change standard streams or inherit from them.
Imagine we want to create a manipulator which reverse a boolean:
cout << boolrev << true << endl;
We can decompose implementation into several parts:
- Retain the status (reversed or not).
- Detect when user wants to display a boolean (and only a boolean).
- Output the reversed value in the stream.
- And the most important thing: how to tell to
coutto understand our new manipulator.
First let’s implement the status storage. The method iword of
std::ios_base is the key.
This function takes an index in argument and returns a storage location for a long.
The index has to be unique.
ios_base provides also a method to get a valid and unused index: xalloc.
Now, we have to intercept the call when user wants to display a boolean. We create a structure which inherits from num_put. This class is a tool to format numeric values as strings.
We check status of the manipulator, and output a value in result. Thanks to inheritence, we can use base method class so formatting with other manipulators is kept.
So now, we just have to connect all this stuff on output stream and use it!
Do not forget to add the 26th line. It is needed to add this manipulator to stream.
- Add one (or more) parameter(s) - like in
- Do not use
- Create an input manipulator
For more informations about manipulators in the
std, I guide you towards these links: