我正在编写一个程序,它的调试输出遍布整个程序。这一切都很好,但我希望能够提升不同范围内事物的标签位置,例如,这就是我现在所拥有的:
#ifndef NDEBUG
printf("Updating player\n");
#endif
player.Update();
#ifndef NDEBUG
printf("Done updating player\n");
#endif
我希望这两个块之间调用的所有输出都被一个选项卡位置提前;但是,只需在Player :: Update()输出的开头添加选项卡就非常笨重且难以维护。
有人帮忙吗? (注意:我使用cout没有问题;我最近刚刚讲了cout的开销和不安全感)
答案 0 :(得分:6)
不是直接使用printf,而是创建一个类来处理控制台输出,并且有一个成员函数,例如SetTabLevel()
- 也许还有IncrementTabLevel()
和DecrementTabLevel()
- 它告诉班级在每个后续行的开头添加多少个选项卡。
答案 1 :(得分:3)
你可以拥有一个基本上保持“标签计数”且具有print_line
功能的类:调用时,它会输出制表符计数选项卡,然后打印该行。虽然你可以有一个increment_indent
函数,你可以使用RAII创建一个姐妹对象TabIndent
:当它被创建时,递增标签,当它被破坏时,减少缩进:
some_function()
{
TabIndent ti(global_debug_outputter);
global_debug_outputted.print_line("foo bar baz");
// ti's d-tor calls global_debug_outputted.unindent()
}
class TabIndent
{
public:
TabIndent(Outputter &o) : m_outputter(o)
{
o.indent();
}
~TabIndent()
{
o.unindent();
}
};
class Outputter
{
// functions indent, unindent, print_line...
};
好好使用inline
s会让编译器在它们的主体为空时优化它们。在#ifndef
类中使用Outputter
,让编译器优化其余部分。
答案 2 :(得分:1)
好消息是C ++ iostreams可以自定义。坏消息是界面有点奇怪。
#include <iostream>
class scoped_streambuf : public std::streambuf {
std::streambuf *sb;
size_t tabs;
bool at_nl;
virtual int_type overflow( int_type c = traits_type::eof() ) {
if ( at_nl ) for ( size_t t = 0; t < tabs; ++ t ) {
int_type r = sb->sputc( '\t' );
if ( r == traits_type::eof() ) return r;
}
int_type r = sb->sputc( c );
if ( r == traits_type::eof() ) return r;
at_nl = c == '\n';
return c;
}
virtual int sync() { return sb->pubsync(); }
static void uninstall( std::ios_base::event what, std::ios_base &ios, int ) {
if ( what != std::ios_base::erase_event ) return;
std::ostream &os = dynamic_cast< std::ostream & >( ios );
scoped_streambuf *this_ = static_cast< scoped_streambuf * >( os.rdbuf() );
os.rdbuf( this_->sb );
delete this_;
}
public:
scoped_streambuf( std::ostream &inos )
: sb( inos.rdbuf( this ) ), tabs(), at_nl() {
inos.register_callback( &uninstall, 0 );
}
friend std::ostream &indent( std::ostream &os ) {
++ dynamic_cast< scoped_streambuf & >( * os.rdbuf() ).tabs;
return os;
}
friend std::ostream &outdent( std::ostream &os ) {
-- dynamic_cast< scoped_streambuf & >( * os.rdbuf() ).tabs;
return os;
}
};
std::ostream &indent( std::ostream & );
std::ostream &outdent( std::ostream & );
struct indent_scope {
std::ostream &os;
indent_scope( std::ostream &inos ) : os( inos ) { os << indent; }
~indent_scope() { os << outdent; }
};
int main() {
new scoped_streambuf( std::cout );
std::cout << "hello\n";
{
indent_scope s( std::cout );
std::cout << "world" << std::endl;
}
std::cout << "!\n";
}
我检查了scoped_streambuf
确实在关联的流被销毁时删除了自己,但显然{G}}本身在GCC上永远不会被销毁。
升级iostream fu,哇!