我第一次尝试使用Boost.Log,很快就遇到了问题。以下简单代码对我来说无法正常工作

#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.Log的内部类,并且当这种情况发生时,使用了"%N.log"的默认文件模式,这导致我看到的00000.log文件名。
Boost.Log使用Boost.Parameter来实现命名参数,因此我尝试了明确使用的参数
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.Log,Boost.Parameter或编译器错误。我正在寻找的是有关错误性质的一些解释。我可以解决上面显示的这个特定问题,但是如果Boost.Log中传递的参数存在根本错误,那是非常严重的。如果有人对此错误有任何经验,或者可以在自己的平台上尝试上述代码,我将不胜感激。
我正在使用Boost 1.74.0和Visual Studio 2019和C++ 17。我正在使用静态Boost库,这些库与C++运行时静态链接。

最佳答案

你说的没错这是一个错误。
一路减少:

std::cerr << (kw::file_name  = "first.log")[kw::file_name | boost::filesystem::path()] << std::endl;
打印“”。稍微有用的测试平台:
Live On 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> const& 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 const&, ::boost::mp11::mp_false) const
#else
            get_default(D const&, ::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 Default&&
        operator[](
            ::boost::parameter::aux::default_r_<KW,Default> const& x
        ) const
    {
        return ::std::forward<Default>(x.value);
    }
由于KW == boost::log::v2_mt_posix::keywords::tag::file_name,这一次是不正确的,因此有人会期望会发生这种重载:
    template <typename Default>
    inline BOOST_CONSTEXPR reference
        operator[](
            ::boost::parameter::aux::default_r_<key_type,Default> const&
        ) 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,所以打开了issue #104。但是事实证明,在进行 fork 时,开发中已经有了解决方法:
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中。

关于c++ - Boost.Log中的参数传递错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63718805/

10-11 23:10
查看更多