这实际上是我第一次真正使用过滤streambuf。给定类似的东西:
std::ostream& operator<<( std::ostream& dest,
std::vector<Matrix> const& object );
class MyClass
{
std::vector<Matrix> m;
};
std::ostream& operator<<( std::ostream& dest, MyClass const& object )
{
// ...
{
// Scope to control lifetime of the IndentingStreambuf...
// Could be (probably should be) in a separate function.
IndentingStreambuf indent( dest )
dest << m;
}
// ...
}
在哪里:
class IndentingStreambuf : public std::streambuf
{
std::streambuf* myDest;
std::ostream* myOwner;
bool myIsAtStartOfLine;
protected:
int overflow( int ch )
{
if ( myIsAtStartOfLine && ch != EOF && ch != '\n' ) {
myDest->sputn( " ", 4 );
}
myIsAtStartOfLine = ch == '\n';
return myDest->sputc( ch );
}
public:
IndentingStreambuf( std::streambuf* dest )
: myDest( dest )
, myOwner( NULL )
, myIsAtStartOfLine( true )
{
}
IndentingStreambuf( std::ostream& dest )
: myDest( dest.rdbuf() )
, myOwner( &dest )
, myIsAtStartOfLine( true )
{
myOwner->rdbuf( this );
}
~IndentingStreambuf()
{
if ( myOwner != NULL ) {
myOwner->rdbuf( myDest );
}
}
};
编辑:
我只是更详细地阅读了您想要的输出。相同的基本IndentingStreambuf
工作,但
您必须对其进行调整以支持任意缩进(作为构造函数的参数),
初始化myIsAtStartOfLine
为false
, 和
输出后调用它A(i) = [
。
当然,适当地定义operator<<
for Matrix
。
或者,您可以使用std::ios_base::xalloc
获取一个可以告诉operator<<
for
Matrix
缩进的地方。类似于以下内容:
static long& getMatrixIndent( std::ostream& dest )
{
static int ourIndex = std::ostream::xalloc();
return dest.iword( ourIndex );
}
class indent
{
int myIndent;
public:
indent( int n ) : myIndent( n ) {}
friend std::ostream& operator<<( std::ostream& dest,
indent const& manip )
{
getMatrixIndent( dest ) = myIndent;
}
};
std::ostream& operator<<( std::ostream& dest, Matrix const& object )
{
int indent = getMatrixIndent( dest );
// ...
}
这远不如过滤流缓冲区灵活。特别是,它不能用于您不控制operator<<
. 但它很简单,有时也很有用。
(事实上,我认为任何使用 C++ 的人都应该熟悉这两种技术。但我不知道有任何教程文本甚至提到了它们。而且在一个大量 C++ 用户仍在编写的世界中while ( ! file.eof() )
,这可能要求太多了。)