如何向流运算符添加缩进 我们在项目中使用C++流运算符(不好的方法是添加全局变量,它告诉缩进。 std::string OwnClassIndentation; std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) { oStream << "[SomeMember1:" << OwnClassIndentation << iOwnClass._ownMember1 << "]\n"; oStream << "[SomeMember2:" << OwnClassIndentation << iOwnClass._ownMember2 << "]\n"; } std::string OwnClassIndentation; std::ostream&operator

如何向流运算符添加缩进 我们在项目中使用C++流运算符(不好的方法是添加全局变量,它告诉缩进。 std::string OwnClassIndentation; std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) { oStream << "[SomeMember1:" << OwnClassIndentation << iOwnClass._ownMember1 << "]\n"; oStream << "[SomeMember2:" << OwnClassIndentation << iOwnClass._ownMember2 << "]\n"; } std::string OwnClassIndentation; std::ostream&operator,c++,stream,operator-overloading,indentation,C++,Stream,Operator Overloading,Indentation,您可以创建自己的具有缩进变量的流类,并覆盖该类的endl,插入缩进。这可以使用自定义流操纵器完成,该操纵器将所需缩进级别存储在流的内部可扩展数组的字中。您可以使用函数ios\u base::xalloc。此函数将为您提供单词索引。您可以使用ios\u base::iword访问它。实现此功能的一种方法是: struct indent { indent(int level) : level(level) {} private: friend std::ostream& op

您可以创建自己的具有缩进变量的流类,并覆盖该类的endl,插入缩进。

这可以使用自定义流操纵器完成,该操纵器将所需缩进级别存储在流的内部可扩展数组的字中。您可以使用函数
ios\u base::xalloc
。此函数将为您提供单词索引。您可以使用
ios\u base::iword
访问它。实现此功能的一种方法是:

struct indent {
    indent(int level) : level(level) {}
private:
    friend std::ostream& operator<<(std::ostream& stream, const indent& val);

    int level;
};

std::ostream& operator<<(std::ostream& stream, const indent& val) {
    for(int i = 0; i < val.level; i++) {
        stream << " ";
    }
    return stream;
}

std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) {
    oStream << indent(oStream.iword(index)) << "[SomeMember1: " << 
               iOwnClass._ownMember1 << "]\n";
    oStream << indent(oStream.iword(index)) << "[SomeMember2: " << 
               iOwnClass._ownMember2 << "]\n";
}
您可以这样使用它:

void some_func() {
    indent_guard(2, std::cout, index);

    // all output inside this function will be indented by 2 spaces

    some_func(); // recursive call - output will be indented by 4 spaces

    // here it will be 2 spaces again
}

最简单的解决方案是在
ostream
和实际的streambuf。类似于:

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的实例:

IndentingOStreambuf indent( std::cout );
//  Indented output...
当缩进超出范围时,一切恢复正常

(对于日志记录,我有一个稍微复杂一点的:
LoggingOStreambuf
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuu
myIndent
到带有这些参数的格式化字符串,再加上时间 在每次输出后,将其重置为缩进字符串 std::ostringstream中的所有输出,并以原子方式输出
到析构函数中的
myDest

不会缩进第一个输出(可能是功能,也可能不是功能),将在最后一行后插入空格(如果文件以文本模式打开,则未定义行为),并且在输出
'\n'
时不会缩进。当然,您必须定义所有
,我也考虑过这一点,但是我必须写入的ostream不在我手中,所以我不能更改它的“类型”。我必须使用日志库中的ostream。streambuf工作了。@W.Goeman:您可以从ostream派生,它有虚拟方法s、 @Dani:我知道我可以派生ostream,假设我实现了“myostream”从中,我将要写入的流将永远不会是mystream。我正在写入另一个库提供给我的ostream。@W.Goeman:如果您只想在输出特定类型(其
operator@JamesKanze:这一点很好-这同样适用于我的solution-没有想到。这当然会起作用,但我真的不喜欢全局变量,尤其是当它们只需要格式化我的日志时:)至少你知道
iostream
:-)。这显然是处理自定义类的任何特殊操纵器的方法。如果第一个输出不是您自己定义的类型,则没有帮助;在这种情况下,您需要在
streambuf
级别截取输出。这并没有完全解决我的问题,但肯定是一个“好消息”。谢谢。您的
某些函数()
将导致堆栈溢出。工作正常!不过我做了一些更改,比如添加了increaseIndent和decreseindent方法。我的日志现在看起来正是我想要的。谢谢。@James:请您也提供更复杂的代码好吗?
void some_func() {
    indent_guard(2, std::cout, index);

    // all output inside this function will be indented by 2 spaces

    some_func(); // recursive call - output will be indented by 4 spaces

    // here it will be 2 spaces again
}
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 );
        }
    }
};
IndentingOStreambuf indent( std::cout );
//  Indented output...