如何向流运算符添加缩进 [英] How to add indention to the stream operator

查看:114
本文介绍了如何向流运算符添加缩进的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的项目中,我们在对象模型中使用c ++流运算符(<<)来打印出易于读取的数据格式.一个简化的示例是这样:

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]

我们现在想要的是能够缩进该运算符的结果.一些调用类可能不希望这样的结果,但是想要在每行之前添加2个空格缩进.我们可以在类中添加一个指定缩进的成员,但这似乎不是一个很好的解决方案.

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.

谢谢

推荐答案

最简单的解决方案是在 ostream和实际的流缓冲.像这样:

The simplest solution is to slip a filtering streambuf between the ostream and the actual streambuf. Something like:

class IndentingOStreambuf : public std::streambuf
{
    std::streambuf*     myDest;
    bool                myIsAtStartOfLine;
    std::string         myIndent;
    std::ostream*       myOwner;
protected:
    virtual int         overflow( int ch )
    {
        if ( myIsAtStartOfLine && ch != '\n' ) {
            myDest->sputn( myIndent.data(), myIndent.size() );
        }
        myIsAtStartOfLine = ch == '\n';
        return myDest->sputc( ch );
    }
public:
    explicit            IndentingOStreambuf( 
                            std::streambuf* dest, int indent = 4 )
        : myDest( dest )
        , myIsAtStartOfLine( true )
        , myIndent( indent, ' ' )
        , myOwner( NULL )
    {
    }
    explicit            IndentingOStreambuf(
                            std::ostream& dest, int indent = 4 )
        : myDest( dest.rdbuf() )
        , myIsAtStartOfLine( true )
        , myIndent( indent, ' ' )
        , myOwner( &dest )
    {
        myOwner->rdbuf( this );
    }
    virtual             ~IndentingOStreambuf()
    {
        if ( myOwner != NULL ) {
            myOwner->rdbuf( myDest );
        }
    }
};

要插入,只需创建一个streambuf的实例:

To insert, just create an instance of the streambuf:

IndentingOStreambuf indent( std::cout );
//  Indented output...

indent超出范围时,一切恢复正常.

When indent goes out of scope, everything returns to normal.

(对于日志记录,我有一个比较复杂的部分: LoggingOStreambuf__FILE____LINE__作为参数,设置 myIndent转换为带有这些参数的加格式的字符串,加上一个时间 标记,在每次输出后将其重置为缩进字符串,收集 所有输出都放在std::ostringstream中,并自动输出 到析构函数中的myDest.

(For logging, I have one that is a bit more complex: the LoggingOStreambuf takes __FILE__ and __LINE__ as arguments, sets myIndent 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 an std::ostringstream, and outputs it atomically to myDest in the destructor.)

这篇关于如何向流运算符添加缩进的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆