Ошибка передачи параметров в Boost.Log

#c #logging #boost

#c #ведение журнала #повышение

Вопрос:

Я экспериментировал с Boost.Впервые вошел в систему и быстро столкнулся с проблемами. Следующий простой код для меня работает некорректно

 #include <boost/log/common.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/sources/logger.hpp>

namespace logging = boost::log;
namespace src = boost::log::sources;

BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger)

static void init()
{
    logging::add_file_log("test.log");
}

int main(int, char* [])
{
    init();
    BOOST_LOG(my_logger::get()) << "hello, world";
    return 0;
}
  

Проблема в том, что журнал сохраняется в вызываемом файле 00000.log вместо test.log запрошенного. При небольшом исследовании кажется, что проблема в том, что "test.log" аргумент не передается в Boost.Внутренние классы журнала, и когда это происходит, используется шаблон файла по умолчанию "%N.log" , который приводит к 00000.log имени файла, которое я вижу.

Повышение.Журнал использует Boost.Параметр для реализации именованных параметров, поэтому я попытался указать, какой параметр я использую

 logging::add_file_log(logging::keywords::file_name = "test.log");
  

Этот сбой происходит таким же образом. Интересно, однако, что если я передаю два параметра, код работает правильно, например

 logging::add_file_log(logging::keywords::file_name = "test.log", 
    logging::keywords::auto_flush = true);
  

Я не смог определить, в чем заключается ошибка, это может быть Boost.Журнал, повышение.Параметр или ошибка компилятора. Что я ищу, так это некоторое объяснение природы ошибки. Я могу обойти эту конкретную проблему, как показано выше, но если есть что-то принципиально неправильное с передачей параметров в Boost.Журнал, это довольно серьезно. Если у кого-нибудь есть опыт работы с этой ошибкой или если они могут попробовать приведенный выше код на своей платформе, я был бы признателен.

Я использую Boost 1.74.0 и Visual Studio 2019 и C 17. Я использую статические библиотеки Boost, которые статически связаны со средой выполнения C .

Ответ №1:

Вы совершенно правы. Это ошибка.

Полностью сокращая его:

 std::cerr << (kw::file_name  = "first.log")[kw::file_name | boost::filesystem::path()] << std::endl;
  

Выводит «». Немного более информативный тестовый стенд:

Жить на Coliru

 #include <boost/log/utility/setup/file.hpp>
#include <iostream>

int main() {
    namespace kw = boost::log::keywords;
    auto test = [](auto params) {
        std::cerr << "Non-defaulted: " << params[kw::file_name] << std::endl;
        std::cerr << "Defaulted:     " << params[kw::file_name | boost::filesystem::path()] << std::endl;
    };

    test((kw::file_name = "aaa"));
    test((kw::file_name = "bbb", kw::auto_flush = false));
    test((kw::auto_flush = false, kw::file_name = "ccc"));
}
  

С принтами

 Non-defaulted: aaa
Defaulted:     ""
Non-defaulted: bbb
Defaulted:     bbb
Non-defaulted: ccc
Defaulted:     ccc
  

Очевидно, что | filesystem::path() синтаксис бросает вызов. И это проявляется только в случае с одним аргументом.


Причина / исправление?

Правильный поток переходит в `arglist::operator[]:

     template <typename Default>
    inline BOOST_CONSTEXPR reference
        operator[](
            ::boost::parameter::aux::default_r_<key_type,Default> constamp; d
        ) const
    {
        return this->get_default(d, _holds_maybe());
    }
  

В

         // Helpers that handle the case when TaggedArg is empty<T>.
        template <typename D>
        inline BOOST_CONSTEXPR reference
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
            get_default(D constamp;, ::boost::mp11::mp_false) const
#else
            get_default(D constamp;, ::boost::mpl::false_) const
#endif
        {
            return this->arg.get_value();
        }
  

В `tagged_arg::

     inline BOOST_CONSTEXPR reference get_value() const
    {
        return this->value;
    }
  

Неисправный случай переходит в

     template <typename KW, typename Default>
    inline BOOST_CONSTEXPR Defaultamp;amp;
        operator[](
            ::boost::parameter::aux::default_r_<KW,Default> constamp; x
        ) const
    {
        return ::std::forward<Default>(x.value);
    }
  

Это сразу неверно, поскольку KW == boost::log::v2_mt_posix::ключевые слова::тег::имя_файла, поэтому можно было бы ожидать, что эта перегрузка была принята:

     template <typename Default>
    inline BOOST_CONSTEXPR reference
        operator[](
            ::boost::parameter::aux::default_r_<key_type,Default> constamp;
        ) const
    {
        return this->get_value();
    }
  

Но. Это определено только для tagged_argument_rref , похоже, что это было упущением (перегрузки для default_<> обоих есть, для сравнения).

Проверка гипотезы

Если проблема специфична для default_r_<> , то она должна быть устранена со значением по умолчанию, которое является lvalue:

 auto args = (kw::file_name = "aaa");
path lvalue;
std::cerr << "default_r_<>: " << args[kw::file_name | path()] << "n";
std::cerr << "default_<>: "   << args[kw::file_name | lvalue] << "n";
  

Который действительно печатает

 default_r_<>: ""
default_<>: aaa
  

Исправить

Само собой разумеется, что перегрузка для default_r_<keyword_type, ...> должна быть добавлена для tagged_argument . Действительно, это работает (на моей машине).

Я собирался создать PR, поэтому я открыл выпуск # 104. Но при разветвлении оказывается, что в develop уже есть исправление:

 tree fff523c8fe0a3de1c1378a2292840f217cc4d6d3
parent 0f548424a5f966fadfa7a21a759c835729cbc009
author Andrey Semashev <andrey.semashev@gmail.com> Sun Mar 15 18:13:07 2020  0300
committer Andrey Semashev <andrey.semashev@gmail.com> Sun Mar 15 18:20:34 2020  0300

Fix argument value selection with an rvalue default.

In C  11 mode, when named parameter pack was a single tagged argument,
parameter value was not extracted when an rvalue default value was
provided by the user (instead, the default value was returned). This
commit adds a missing overload for default_r_, which returns the parameter
value.

Fixes https://github.com/boostorg/parameter/issues/97.
  

Итак, да, похоже, что исправлению несколько месяцев, и проблема дублирует # 97.

Комментарии:

1. Я рассмотрю это немного подробнее — приготовление имеет приоритет

2. @john нашел и устранил причину только для того, чтобы обнаружить, что эта проблема ожидает слияния в develop . Гррр. Надеюсь, что информация все еще помогает вам

3. Оставил там еще несколько комментариев. Похоже, что с обслуживанием там полный бардак: по-видимому, в develop было исправление, которое было объединено, но, по-видимому, все это было отменено, хотя они знали, что в нем было исправление # 97. Я ошеломлен тем, что там происходит, поэтому я оставил заметки для разработчиков, чтобы они это выяснили .

4. Для вдохновения, ваш конкретный пример работает правильно при размещении develop ветви параметра Boost в вашем пути включения. В конце концов, это только заголовок: imgur.com/a/rKnPO9f

5. Спасибо за вашу работу над этим. Приятно знать, что это исправляется.