Включить Boost.Log только при отладке

Мне нужен регистратор для отладки, и я использую 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

4

Решение

Уровень серьезности записи в журнале действует как фильтр для приемников. Приемник будет решать, что делать с сообщением (печатать его или нет), в зависимости от уровня серьезности. Но сообщение все равно будет отправлено.

Если вы пытаетесь не отправлять сообщение вообще, тогда вам нужно переопределить 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, что всегда хорошо.

5

Другие решения

Мне нравится джона NullLogger учебный класс. Единственное изменение, которое я хотел бы сделать, заключается в следующем

#define LOG_MESSAGE(lvl) while (0) NullLogger (lvl)

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

3

По вопросам рекламы [email protected]