Нулевой поток, нужно ли включать ostream?

Я пишу регистратор. Если отключено, это код, определяющий макрос LOG:

#ifdef NO_LOG

#include <ostream>

struct nullstream : std::ostream {
    nullstream() : std::ios(0), std::ostream(0) {}
};

static nullstream logstream;

#define LOG if(0) logstream

#endif

LOG << "Log message " << 123 << std::endl;

Это работает правильно. Компилятор должен полностью удалить код, связанный с макросом LOG.

Однако я хотел бы избежать включения ostream и определить объект logstream как что-то действительно «легкое», возможно, нулевое.

Благодарю вас!


person Pietro M    schedule 08.12.2011    source источник


Ответы (2)


Почему бы не реализовать все это с нуля:

struct nullstream { };

template <typename T>
nullstream & operator<<(nullstream & o, T const & x) { return o; }

static nullstream logstream;
person Kerrek SB    schedule 08.12.2011
comment
Это должно быть nullstream вместо std::ostream? - person sth; 08.12.2011
comment
Вы имеете в виду nullstream & operator<<(nullstream & o, T const & x)? И это не будет работать с endl. - person fefe; 08.12.2011
comment
@fefe: ты прав; endl теперь кажется единственной проблемой. Можно ли завершить поток другим способом. Я действительно хотел бы избежать включения ostream, если мне не нужно ведение журнала... - person Pietro M; 08.12.2011
comment
@PietroM, если вы используете endl, то, возможно, вам придется включить ostream, поскольку endl на самом деле является (шаблонной) функцией, принимающей ostream& в качестве параметра, а endl определено в ‹ostream›. Однако для этого может быть уродливое решение, которое заключается в #define endl 0. Это нарушит нормальное использование endl, но если у вас нет ostream, я думаю, нормального использования endl не будет. - person fefe; 08.12.2011
comment
@fefe: #define endl 0 — это слишком экстремально. Мне может потребоваться нормальный вывод, даже если ведение журнала отключено... - person Pietro M; 08.12.2011
comment
@sth: О, да! Исправлено, спасибо! О endl... если мы включим <iosfwd>, это очень дешево; можем ли мы определить подходящую перегрузку для размещения endl? - person Kerrek SB; 08.12.2011
comment
встроенный нулевой поток и заканчивается (нулевой поток и s) { return s; } - person Pietro M; 08.12.2011

person    schedule
comment
Работает, но можно ли обойтись без включения iostream? Например, можно ли вместо std::endl использовать что-то другое? - person Pietro M; 08.12.2011
comment
@Pietro: это нужно только для примера, для std::endl. Самому nullstream это не нужно, только <iosfwd> (форвардные объявления типов <iostream>). - person Mike Seymour; 08.12.2011
comment
@Pietro Часто можно использовать '\n' вместо std::endl. - person UncleBens; 08.12.2011
comment
@Mike: в этом случае '\0' или '\n' будут иметь тот же эффект, что и std::endl? Они не потребуют включения ostream. - person Pietro M; 08.12.2011
comment
'\n' - это символ новой строки, std::endl выводит новую строку и очищает выходной буфер. Насколько я знаю, нет необходимости сбрасывать std::cerr и не уверен насчет std::clog. - person UncleBens; 08.12.2011
comment
@UncleBens: я пишу в файл. Могу ли я заставить файл вести себя как std::cerr? - person Pietro M; 08.12.2011
comment
@MikeSeymour: я проверил: '\n' не сбрасывает строку, по крайней мере, когда вывод находится в файле. - person Pietro M; 08.12.2011