Мне нужен регистратор для отладки, и я использую Boost.Log (1.54.0 с патчем на домашней странице boost.org).
Все хорошо, я создал такой макрос:
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
Теперь это способ расширения LOG_MESSAGE (lvl) в BOOST_LOG_TRIVIAL (lvl) только в режиме отладки и игнорирования при выпуске?
например:
LOG_MESSAGE( critical ) << "If I read this message we're in debug mode"
редактировать
Моя первая попытка создать nullstream … Я думаю, что в режиме релиза компилятор оптимизирует его …
#if !defined( NDEBUG )
#include <boost/log/trivial.hpp>
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
#else
#if defined( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"#endif#include <iosfwd>
struct nullstream : public std::ostream {
nullstream() : std::ios(0), std::ostream(0) {}
};
static nullstream g_nullstream;
#define LOG_MESSAGE( lvl ) g_nullstream
#if defined( __GNUC__ )
#pragma GCC diagnostic pop
#endif
#endif
Уровень серьезности записи в журнале действует как фильтр для приемников. Приемник будет решать, что делать с сообщением (печатать его или нет), в зависимости от уровня серьезности. Но сообщение все равно будет отправлено.
Если вы пытаетесь не отправлять сообщение вообще, тогда вам нужно переопределить LOG_MESSAGE
к чему-то, что на самом деле ничего не делает. для этого может быть что-то в библиотеке Boost, иначе вам придется написать свой собственный. Возможно, это будет началом:
class NullLogger
{
public:
template <typename SeverityT> NullLogger (SeverityT) {};
template <typename Val> NullLog& operator<< (const Val&) { return * this};
};
…а потом:
#define LOG_MESSAGE (lvl) NullLogger (lvl)
Обратите внимание, что, хотя ничего не делается с сообщением журнала или выражениями, которые его составляют, выражения все еще оцениваются. Если некоторые из этих выражений стоят дорого, вы все равно будете терять производительность. Например:
LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();
Даже если вы используете NullLogger
выше, SomeSuperExpensiveFunction()
все еще будет называться.
Я бы предложил в качестве альтернативы добавить флаг, который оценивается во время выполнения, и решить, во время выполнения стоит ли делать регистрацию:
if (mLogStuff)
{
LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();
}
bool
Сравнение может быть очень дешевым, и однажды в будущем вы обнаружите, что возможность включать и выключать регистрацию может быть очень удобной. Кроме того, это означает, что вам не нужно добавлять еще один #define
, что всегда хорошо.
Мне нравится джона NullLogger
учебный класс. Единственное изменение, которое я хотел бы сделать, заключается в следующем
#define LOG_MESSAGE(lvl) while (0) NullLogger (lvl)
К сожалению, это может генерировать предупреждения, но я надеюсь, что приличный компилятор сможет удалить весь связанный код регистрации.