我正在爲我的項目工作一個簡單的記錄器包裝,這將允許我輕鬆地交換出後端。
這是我的理想接口:C++禁用鏈接調用,而不包裝在指令
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
禁用這些類型的鏈接調用的乾淨方式是什麼? 任何幫助表示讚賞。
太棒了,但是虛擬'Sink'的拷貝構造函數無法刪除,或者需要移動構造函數。 –