#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;
Выводит «». Немного более информативный тестовый стенд:
#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/rKnPO9f5. Спасибо за вашу работу над этим. Приятно знать, что это исправляется.