提取任意类型的提升日志属性值



有一个日志系统,具有任意类型的多个属性。属性由外部程序使用公共API(函数模板(添加。这些类型事先并不知道。打印属性值的典型方法如下(简化(:

void print(logging::attribute_value const& attr)
{
auto val = logging::extract<int>(attr);
if (val) {
std::cout << "value: " << val.get() << std::endl;
}
}

在上面的示例中,已经知道属性值类型是int。如果预期的类型未知怎么办?当然,我可以这样写:

typedef boost::mpl::vector<int, std::string> types; // Expected types
logging::value_ref<types> val = logging::extract<types>(attr);
[..]

然而,在这种情况下,我必须定义所有可能的类型,并分别处理它们。

有没有一种方法可以打印出(或转换为字符串(所有值,而不管它们的类型如何,假设类型重载了流运算符?

更新

以下是更多详细信息:

// Add new attributes with arbitrary types
template<typename T>
void addProperty(const std::string &key, T && value)
{
auto attrs = boost::log::core::get()->get_thread_attributes();
attrs.erase(key);
attrs.insert(key, boost::log::attributes::make_constant(std::move(value)));
boost::log::core::get()->set_thread_attributes(attrs);
}

以及另一个应该打印属性值的函数

void printProperties()
{
const auto &attrs = boost::log::core::get()->get_thread_attributes();
for (auto const &a : attrs) {
// Print all values. Types aren't known.
}
}

假设类型重载流运算符,是否有方法打印出(或转换为字符串(所有值(无论其类型如何(?

不,Boost.Log不支持,您必须知道属性值的名称和类型才能提取或访问它。

您可以做的是维护属性名称和格式化例程之间的映射,例如:

std::map<
logging::attribute_name,
std::function< void(std::ostream&, logging::attribute_value const&) >
> formatters;
template< typename T >
void formatter(std::ostream& strm, logging::attribute_value const& attr)
{
auto val = logging::extract< T >(attr);
if (val)
strm << val.get();
}
template<typename T>
void addProperty(const std::string &key, T && value)
{
typedef std::remove_cv_t< std::remove_reference_t< T > > value_type;
logging::attribute_name name(key);
formatters[name] = &formatter< value_type >;
boost::log::core::get()->add_thread_attribute(name,
boost::log::attributes::make_constant(std::forward< T >(value)));
}
void printProperties()
{
const auto &attrs = boost::log::core::get()->get_thread_attributes();
for (auto const &a : attrs) {
auto it = formatters.find(a.first);
if (it != formatters.end()) {
std::cout << "value: ";
it->second(std::cout, a.second.get_value());
std::cout << std::endl;
}
}
}

当然,我可以这样写:

typedef boost::mpl::vector<int, std::string> types; // Expected types
logging::value_ref<types> val = logging::extract<types>(attr);
[..]

但是,在这种情况下,我必须定义所有可能的类型和句柄它们是分开的。

是的,这将是我的第一个建议:考虑将类型设置为sum类型(一个绑定变体,在这里您可以访问所有绑定类型(。

有没有办法打印出(或转换为字符串(所有值无论其类型如何,假设类型重载流操作人员

规范的替代方法是使用类型擦除。请注意,它仍然有开销,但在引擎盖下用动态多态性取代了静态多态性。

看一看,例如https://www.boost.org/doc/libs/1_78_0/doc/html/boost/type_erasure/ostreamable.html


哪些编译器在非常特殊的情况下,通过适当的提示,有时会使返回静态调用失去机会,但我偏离了

最新更新