user7140484 user7140484 - 6 days ago 6
C++ Question

How to write my own manipulator?

Let's suppose I want to write my own manipulator for input and output.

cin >> mymanip >> str;


or

cout << mymanip << str;


What I want that mymanip does is toggle case the caracters I read from input and assigns the result to one string.

So, if I type "QwErTy" I get "qWeRtY" in the string.

This is a very basic task with one function, but i want to learn more about manipulators.

Can someone give a clue?

Thank you.

Answer

All that a manipulator does is set the corresponding bits in the std::ios_base base class.

For example, the std::setprecision() manipulator simply invokes std::ios_base::precision(), on the manipulated stream.

The implementation of std::setprecision() is almost readable, in gcc's headers (a rarity, for a C++ library template implementation):

 inline _Setprecision  setprecision(int __n)
     { return { __n }; }

std::setprecision() returns an internal std::_Precision object. Then, a simple template overload for the >> (and the << operator, which is similar) operator, for the std::_Precision object, handles the rest of the magic:

 template<typename _CharT, typename _Traits>
    inline basic_istream<_CharT, _Traits>& 
    operator>>(basic_istream<_CharT, _Traits>& __is, _Setprecision __f)
    { 
      __is.precision(__f._M_n); 
      return __is; 
    }

In your case, there are no bits in the std::ios_base class that implement your desired input/output transformation. As such, a manipulator, per se, won't work here.

What you're trying to do requires a completely different, more complicated, approach:

  1. A custom subclass of std::[io]stream, that uses a custom subclass of std::streambuf.

  2. The std::streambuf subclass reads or writes from a chained stream, transforming the input or output as you've described.

  3. Reading or writing from the custom subclass ends up reading or writing from the chained stream, transforming the data accordingly.

Comments