我第一次尝试使用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/