我正在为我的项目开发一个简单的记录器包装器,它可以让我轻松换出后端。
这是我理想的界面:
log::error << "some" << " log " << "message";
我实现它的方式是:
log::error#operator<<
返回一个临时Sink
对象。Sink#operator<<
返回*this
并定义一个移动构造函数。完整的消息可以在
Sink
调用链末尾调用的析构函数中使用。
人为的实现:
#include <iostream>
#include <string>
struct Sink {
Sink (std::string const& msg) : m_message(msg) {}
// no copying
Sink (Sink const& orig) = delete;
// move constructor
Sink (Sink && orig) : m_message(std::move(orig.m_message)) {};
// use the complete string in the destructor
~Sink() { std::cerr << m_message << std::endl;}
Sink operator<< (std::string const& msg) {
m_message.append(msg);
return std::move(*this);
}
std::string m_message;
};
struct Level {
Sink operator<< (std::string const& msg) { return Sink(msg); }
};
int main() {
Level log;
log << "this" << " is " << "a " << "test";
}
这很好用,除非我需要一种干净的方式来禁用日志记录。如果我没有使用链接,我的日志函数可以使用预处理器指令来删除函数的内容
void log (std::string) {
#ifdef LOGGING_ENABLED
// log message
#endif
}
然后编译器将优化并删除空函数调用。但我不知道如何使用我试图实现的 api 来做到这一点。我知道这是可能的,因为glog以某种方式做到了。
使用这样的指令违背了拥有一个好的 api 的目的。
#ifdef LOGGING_ENABLED
log << "this" << " is " << "a " << "test";
#endif
禁用这些类型的链接调用的干净方法是什么?任何帮助表示赞赏。