Предварительная позиция вкладки в C ++? - PullRequest
2 голосов
/ 07 сентября 2010

В настоящее время я пишу программу, в которой разбросан отладочный вывод. Это все хорошо, но я хотел бы иметь возможность продвигать позицию вкладки для вещей в разных областях, например, это то, что у меня есть сейчас:

#ifndef NDEBUG
printf("Updating player\n");
#endif
player.Update();
#ifndef NDEBUG
printf("Done updating player\n");
#endif

Мне бы хотелось, чтобы весь вывод, вызываемый между этими двумя блоками, продвигался на одну позицию табуляции; однако простое добавление вкладок в начало вывода Player :: Update () невероятно неуклюжее и сложное в обслуживании.

Кто-нибудь получил помощь? (Примечание: у меня нет проблем с использованием cout; недавно я читал лекции о накладных расходах и ненадежности cout)

Ответы [ 3 ]

6 голосов
/ 07 сентября 2010

Вместо непосредственного использования printf создайте класс для обработки вывода на консоль и получите функцию-член, такую ​​как SetTabLevel() - и, возможно, также IncrementTabLevel() и DecrementTabLevel() - которая сообщает классу, сколько вкладок добавитьначало каждой последующей строки.

3 голосов
/ 07 сентября 2010

У вас может быть класс, который по существу поддерживает «счетчик вкладок» и имеет функцию print_line: при вызове он выводит вкладки с количеством вкладок, а затем печатает строку.Хотя у вас может быть функция increment_indent, вы можете создать дочерний объект TabIndent, используя RAII: когда он создается, увеличивайте вкладку, когда она разрушается, уменьшайте отступ:

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, и пусть компилятор оптимизирует все остальное.

1 голос
/ 07 сентября 2010

Хорошей новостью является то, что 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 действительно удаляет себя, когда связанный поток уничтожается, но, очевидно, сам std::cout никогда не уничтожается в GCC.

Повышение уровня iostream fu, whee!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...