- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想弄清楚,最好的方法是在类中使用日志记录源。简单地将其定义为成员(堆栈)变量的直接解决方案有一个很大的缺点,即我必须包含 Boost.Log 头文件,这确实会减慢编译速度。
我想使用严重性 channel 记录器。所以我的第一个方法是定义一个新类型,例如:
#include <boost/log/sources/severity_channel_logger.hpp>
typedef boost::log::sources::severity_channel_logger_mt<SeverityLogLevel, std::string> DefaultLogger;
这种方法只简化了记录器的定义,但我仍然需要包含头文件。
我的下一个想法是创建一个新类,它对记录器进行子类型化,然后使用此类的前向声明:
// MyLogger.h
class MyLogger : public boost::log::sources::severity_channel_logger_mt<SeverityLogLevel, std::string>
{
public:
MyLogger(const std::string& name);
};
// MyLoggingClient.h
include <memory>
class MyLogger;
class MyLoggingClient
{
// Actual implementation
private:
std::unique_ptr<MyLogger> lg;
};
但是这样做时,编译器会提示 MyLogger 没有定义二进制“[”运算符或转换为预定义运算符可接受的类型。
所以,我的问题是,简单转发logger的定义有什么好方法?(我正在重构现有代码的日志记录,因此使用 PIMPL 或类似模式会导致大量额外工作。)
谢谢,-拉斯
最佳答案
我认为您已经展示了转发声明记录器的最佳方法,尽管我建议将 Boost.Log 记录器存储为 MyLogger
的成员而不是从它派生。 Boost.Log 记录器是使用 CRTP 设计的,因此从中派生可能会导致意外行为。
您遇到的编译器错误可能是由于您的代码的某些部分未更新以说明您所做的更改引起的 - lg
不再是一个记录器,而是一个指针。
PIMPL 是另一种实现您想要的方法,我认为它实际上可能比使用指针更容易。您需要为记录器实现一个包装器,该包装器实现类似于您使用的 Boost.Log 记录器的接口(interface)。例如,对于 severity_channel_logger_mt
这可能就足够了:
// MyLogger.h
#include <string>
#include <boost/log/core/record.hpp>
#include <boost/log/keywords/severity.hpp>
#include <boost/log/keywords/channel.hpp>
enum SeverityLogLevel { ... };
class MyLogger
{
private:
struct Impl;
Impl* impl;
public:
MyLogger();
MyLogger(MyLogger const&);
MyLogger(MyLogger&& that) noexcept : impl(that.impl) { that.impl = nullptr; }
~MyLogger();
MyLogger& operator= (MyLogger const&);
MyLogger& operator= (MyLogger&& that) noexcept
{
MyLogger copy(static_cast< MyLogger&& >(that)); // you can use use std::move here and include <utility>
this->swap(copy);
return *this;
}
boost::log::record open_record();
boost::log::record open_record(SeverityLogLevel sev, std::string const& chan);
template< typename Args >
boost::log::record open_record(Args const& args)
{
return open_record(args[boost::log::keywords::severity], args[boost::log::keywords::channel]);
}
void push_record(boost::log::record&& rec);
void swap(MyLogger& that) noexcept
{
Impl* p = impl;
impl = that.impl;
that.impl = p;
}
};
// MyLogger.cpp
#include "MyLogger.h"
#include <utility>
#include <boost/log/sources/severity_channel_logger.hpp>
typedef boost::log::sources::severity_channel_logger_mt<
SeverityLogLevel,
std::string
> DefaultLogger;
struct MyLogger::Impl
{
DefaultLogger lg;
};
MyLogger::MyLogger() : impl(new Impl())
{
}
MyLogger::MyLogger(MyLogger const& that) : impl(new Impl(*that.impl))
{
}
MyLogger::~MyLogger()
{
delete impl;
}
MyLogger& MyLogger::operator= (MyLogger const& that)
{
MyLogger(that).swap(*this);
return *this;
}
boost::log::record MyLogger::open_record()
{
return impl->lg.open_record();
}
boost::log::record MyLogger::open_record(SeverityLogLevel sev, std::string const& chan)
{
return impl->lg.open_record((boost::log::keywords::severity = sev, boost::log::keywords::channel = chan));
}
void MyLogger::push_record(boost::log::record&& rec)
{
impl->lg.push_record(std::move(rec));
}
您应该能够按原样将 Boost.Log 宏与此包装器一起使用。您仍然需要在 MyLogger.h 中包含一些 header ,但希望这对您来说是一个足够重要的改进。如果您删除对关键字的支持(Boost.Log 包含和模板化的 open_record
重载),它可以进一步改进,但是您将必须在整个代码中定义和使用您自己的日志记录宏。
如果您使用其他日志记录功能,例如属性,您可能需要向包装器添加更多转发功能。参见 Reference记录器函数的签名。
关于c++ - boost 日志 : How to forward a loging source,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34144781/
我是一名优秀的程序员,十分优秀!