Как работает «ленивая оценка» тривиальных регистраторов Boost Log? - PullRequest
0 голосов
/ 15 мая 2018

[ Отслеживает Ясно проверить boost :: log filter?]

В следующем примере используется тривиальный регистратор из Boost Log .Он выводит 1, показывая, что expensive() вызывается только один раз.Как это работает?Почему expensive() не вызывается?

Live On Coliru

#include <iostream>

#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>

int count = 0;

int expensive()
{
    return ++count;
}

int main()
{
    boost::log::core::get()->set_filter(
        boost::log::trivial::severity >= boost::log::trivial::warning
    );

    BOOST_LOG_TRIVIAL(error) << expensive();
    BOOST_LOG_TRIVIAL(info) << expensive();

    std::cout << count << '\n';

    return 0;
}

Вывод:

[2018-05-21 14:33:47.327507] [0x00007eff37aa1740] [error]   1
1

1 Ответ

0 голосов
/ 15 мая 2018

Работает, используя немного магии макросов / препроцессора. Операторы действительно похожи на вызов функции для некоторых operator<<():

BOOST_LOG_TRIVIAL(warning) << expensive();

Однако, сильно упрощая, макрос работает так, как будто мы написали что-то вроде:

if (level == warning)
    logger << expensive();

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

#define LOG_WARNING if (level == warning) logger

И тогда мы могли бы использовать его как:

LOG_WARNING << expensive();

Фактический макрос BOOST_LOG_TRIVIAL заканчивается расширением в:

for (
    ::boost::log::record _boost_log_record_N =
        (::boost::log::trivial::logger::get()).open_record(
            (::boost::log::keywords::severity = ::boost::log::trivial::error)
        )
    ;
    !!_boost_log_record_N;
)
    ::boost::log::aux::make_record_pump(
        (::boost::log::trivial::logger::get()),
        _boost_log_record_N
    ).stream() << expensive();

Как видите, в зависимости от условия цикла !!_boost_log_record_N (которое, в свою очередь, зависит от результата open_record()), тело цикла будет выполняться ноль или более раз; Именно поэтому expensive() не всегда выполняется.

...