开发者

How to write user-defined manipulators for streaming self-written class

How do I write user-defined stream manipulators in C++ that control the format of streaming a self-written class?

Specifically, how would I write simple manipulators verbose and terse to control the amount of output streamed?

My environment is GCC, versions 4.5.1 and up.

Example:

class A
{
 ...
};

A a;

// definition of manipulators verbose and terse

cout << verbose << a << endl; // outputs a verbosely
cout << terse << a << endl; // outputs开发者_运维问答 a tersely

PS: What follows is just a side question, feel free to ignore it: Can this portably be extended to manipulators taking arguments? Josuttis writes in "The C++ Standard Library" near the end of section 13.6.1 that writing manipulators taking argument is implementation dependent. Is this still true?


I don't see any reason for them to be implementation dependent.

This is comething that I use, for the actual manipulator, create a function that returns an instance of the following helper. If you need to store the data, just store it inside the helper, some global variable, singleton, etc...

    /// One argument manipulators helper
    template < typename ParType >
    class OneArgManip
    {
        ParType par;
        std::ostream& (*impl)(std::ostream&, const ParType&);

        public:
            OneArgManip(std::ostream& (*code)(std::ostream&, const ParType&), ParType p) 
                : par(p), impl(code) {}

            // calls the implementation
            void operator()(std::ostream& stream) const
            { impl(stream,par); }

            // a wrapper that allows us to use the manipulator directly
            friend std::ostream& operator << (std::ostream& stream, 
                            const OneArgManip<ParType>& manip)
            { manip(stream); return stream; }
    };

Example of a manipulator based on this:

OneArgManip<unsigned> cursorMoveUp(unsigned c) 
{ return OneArgManip<unsigned>(cursorMoveUpI,c); }

std::ostream& cursorMoveUpI(std::ostream& stream, const unsigned& c)
{ stream << "\033[" << c << "A"; return stream; }

For some explanation:

  1. u use the manipulator, that returns a new instance of the helper bound to an implementation of the helper
  2. stream tries to process the helper, that invokes the << overload on the helper
  3. that invokes the () operator on the helper
  4. that invokes the real implementation of the helper with the parameter passed from the original manipulator call

If you want I can post 2 param and 3 param helpers as well. The principle is the same though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜