In C++, to print a number in hexadecimal you do this:
int num = 10; std::cout << std::hex << num; // => 'a'
I know I can create a manipulator that just adds stuff to the stream like so:
std::ostream& windows_feed(std::ostream& out) { out << "\r\n"; return out; } std::cout << "Hello" << windows_feed; // => "Hello\r\n"
However, how can I create a manipulator that, like 'hex', modifies items to come on the stream? As a simple example, how would I create the plusone manipulator here?:
int num2 = 1; std::cout << "1 + 1 = " << plusone << num2; // => "1 + 1 = 2" // note that the value stored in num2 does not change, just its display above. std::cout << num2; // => "1"
A parameterized manipulator is implemented in two parts: The manipulator. It takes an extra parameter. In the previous code example, it takes an extra int parameter. You cannot place this manipulator function in a sequence of input or output operations, since there is no shift operator defined for it.
Manipulators are used to changing formatting parameters on streams and to insert or extract certain special characters.
Line 18 uses manipulator boolalpha to display the bool value as a string.
First, you have to store some state into each stream. You can do that with the function iword
and an index you pass to it, given by xalloc
:
inline int geti() { static int i = ios_base::xalloc(); return i; } ostream& add_one(ostream& os) { os.iword(geti()) = 1; return os; } ostream& add_none(ostream& os) { os.iword(geti()) = 0; return os; }
Having that in place, you can already retrieve some state in all streams. Now, you just have to hook into the respective output operation. Numeric output is done by a facet, because it potentially is locale dependent. So you can do
struct my_num_put : num_put<char> { iter_type do_put(iter_type s, ios_base& f, char_type fill, long v) const { return num_put<char>::do_put(s, f, fill, v + f.iword(geti())); } iter_type do_put(iter_type s, ios_base& f, char_type fill, unsigned long v) const { return num_put<char>::do_put(s, f, fill, v + f.iword(geti())); } };
Now, you can test the stuff.
int main() { // outputs: 11121011 cout.imbue(locale(locale(),new my_num_put)); cout << add_one << 10 << 11 << add_none << 10 << 11; }
If you want that only the next number is incremented, just set the word to 0
again after each call to do_put
.
I totally agree with Neil Butterworth on this one, however in the specific case you are using you could do this totally horrible hack. Do not do this in any production code. It has lots of bugs. For one thing it only works in your one-liner above, it does not change the state of the underlying stream.
class plusone_stream : public std::ostream { public: std::ostream operator<<(int i) { _out << i+1; return *this; } }; std::ostream& plusone(std::ostream& out) { return plusone_stream(out); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With