Я делаю что-то очень похожее для трассировки, но использую stringstream
. Это гарантирует работу всех сторонних operator << ()
и манипуляторов. Я также использую desctructor вместо манипулятора записи клиента.
class DebugStream
{
public:
DebugStream(short level, const char * file, int line) {
sstream << "L" << level << "\t" << file << "\t" << line << "\t";
}
~DebugStream() { write(sstream.str()); }
std::ostream & stream() { return sstream; }
private:
std::stringstream sstream;
DebugStream(const DebugStream &);
DebugStream & operator=(const DebugStream &);
};
Затем он становится доступен с некоторыми макросами:
#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()
А код просто использует макросы
DBG_INFO << "print some debug information";
Вам не нужен специальный манипулятор записи для сброса данных в файл журнала. Когда анонимный объект DebugStream
выходит из области видимости (когда элемент управления покидает линию), содержимое автоматически записывается.
Хотя в этом случае я обычно избегаю макросов, использование оператора if
означает, что у вас нет накладных расходов на построение линии трассировки, если вы на самом деле не требуете ее.
Возвращение ostream
с помощью метода stream()
позволяет этому работать для глобальных функций-членов, поскольку анонимные объекты не могут быть переданы как неконстантные ссылочные параметры.