Как работает QDebug () << вещи; добавить новую строку автоматически? - PullRequest
15 голосов
/ 01 февраля 2010

Я пытаюсь реализовать свой собственный поток отладки-вывода в стиле QDebug (), это в основном то, что я имею до сих пор:

struct debug
{
#if defined(DEBUG)
    template<typename T>
    std::ostream& operator<<(T const& a) const
    {
        std::cout << a;
        return std::cout;
    }
#else
    template<typename T>
    debug const& operator<<(T const&) const
    {
        return *this;
    }

    /* must handle manipulators (endl) separately:
     * manipulators are functions that take a stream& as argument and return a
     * stream&
     */
    debug const& operator<<(std::ostream& (*manip)(std::ostream&)) const
    {
        // do nothing with the manipulator
        return *this;
    }
#endif
};

Типичное использование:

debug() << "stuff" << "more stuff" << std::endl;

Но я бы не хотел добавлять std :: endl;

Мой вопрос в основном, как я могу узнать, когда возвращаемый тип оператора << не будет использоваться другим оператором << (и, таким образом, добавить endl)? </p>

Единственный способ, которым я могу придумать для достижения чего-либо подобного, - это создать список вещей для печати, связанных с каждым временным объектом, созданным debug (), затем распечатать все вместе с завершающим символом новой строки (и я мог делать умные вещи, такие как вставка пробелов) в ~ debug (), но, очевидно, это не идеально, так как у меня нет гарантии, что временный объект будет уничтожен до конца области (или нет?).

Ответы [ 4 ]

17 голосов
/ 01 февраля 2010

Примерно так будет:

struct debug {
    debug() {
    }

    ~debug() {
        std::cerr << m_SS.str() << std::endl;
    }

public:
    // accepts just about anything
    template<class T>
    debug &operator<<(const T &x) {
        m_SS << x;
        return *this;
    }
private:
    std::ostringstream m_SS;
};

Что должно позволить вам делать такие вещи:

debug() << "hello world";

Я использовал подобный шаблон в сочетании с блокировкой, чтобы обеспечить поток, подобный системе журналирования, которая может гарантировать, что записи журнала записываются атомарно.

ПРИМЕЧАНИЕ : непроверенный код, но должен работать: -)

9 голосов
/ 02 февраля 2010

Qt использует метод, аналогичный @Evan. Смотрите версию qdebug.h для подробностей реализации, но они передают все в основной текстовый поток, а затем очищают поток и конечную строку при уничтожении временного объекта QDebug, возвращаемого qDebug () .

5 голосов
/ 01 февраля 2010

Когда вы пишете, что это типичное использование:

debug() << "stuff" << "more stuff" << std::endl;

вы определенно планируете создавать объект отладки каждый раз, когда используете его? Если это так, вы сможете получить желаемое поведение, добавив в деструктор отладки символ новой строки:

~debug()
{
    *this << std::endl;

    ... the rest of your destructor ...
}

Это означает, что вы не можете сделать что-то вроде этого:

// this won't output "line1" and "line2" on separate lines
debug d;
d << "line1";
d << "line2";
0 голосов
/ 01 февраля 2010

Предполагается, что вставка потока (<<) и извлечение (>>) не являются членами.

Мой вопрос в основном, как я могу сказать, когда возвращаемый тип оператор << не будет использоваться другой оператор << (и так добавить епсИ) </p>

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

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