2016-06-14 118 views
-1

記錄器存在的問題之一是,即使您不希望它們記錄,它們也會記錄。他們通常是硬連線寫入文件或迴應控制檯 - 有時兩者。 這與單元測試相反,其中記錄到任一接收器會降低測試速度。重載函數運算符

我也反對使用printf樣式可變參數,因爲它們總是會因爲人員剪切,粘貼和忘記更改參數類型或從字符串中刪除參數而錯誤。

所以我決定做點什麼。

我的基本想法是將LogStream對象接受ostream作爲參數,以便您可以指定文件,控制檯或在單元測試期間靜默吞下它。這通過 作爲Logger類的參數,該類也接受嚴重性級別。

這是一個記錄器,僅記錄致命事件的ostringstream(從單元測試意譯)的概念流程:

std::ostringstream oss; 
auto logstream = LogStream(oss); 
auto logger = Logger(logstream, FATAL); 
logger(INFO) << "This is a log test\n"; // (1) 
std::cout << oss.str(); // Display nothing as nothing fatal has been logged 

有關問題的思考,我需要一個臨時的流(ostream的將工作)在決定它是否滿足放置在LogStream對象中的條件之前保存流。

我遇到的問題是線(1)您將有函數調用操作符,它返回參考LogStream已和它退出後流的其餘部分構成:

LogStream& operator()(Severity severity) 
{ 
    // stream not completed 
    return *m_dest; 
} 

我覺得有一種方法,因爲你可以得到重載插入運算符友元函數,其使用的是流參數:

std::ostream& operator<<(std::ostream& os, const Complex& c) 
{ 
    os << c.real << '.' << c.imaginary; 
    return os; 
} 

但作爲然而,我一直無法弄清楚的功能操作的正確語法。

有可能,還是我吠叫錯了樹?

+2

改造車輪很少會獲得獎勵。不缺乏滿足您要求的測井設施。 Boost.Log和Log4cpp等等。 – SergeyA

+0

通常我會同意,但是在比您的項目大幾個數量級的庫中,看起來有點OTT(並且我知道只有標題被拉入或者您只是鏈接一個靜態庫)。 –

+2

函數運算符的語法是正確的(作爲成員函數)。你有什麼問題? – ecatmur

回答

1

你需要某事像這樣的設計:

enum class LogLevel 
{ 
    FATAL, 
    INFO 
}; 

class LogStream : public std::ostream 
{ 
public: 
    LogStream(const std::ostream&) 
    // ... 
    { 
    } 

}; 

class EatStream : public std::ostream 
{ 
    // does nothing 
}; 

class Logger 
{ 
    const LogStream m_logger; 
    const EatStream m_nolog; 
    const LogLevel m_loglevel; 
public: 
    Logger(const LogStream&&, const LogLevel) // I'd suggest move, but you might as well just take a reference and copy 
    // ... 
    { 
     // ... 
    } 

    std::ostream& operator()(const LogLevel level) 
    { 
     return level <= m_loglevel ? m_logger : m_nolog; 
    } 
}; 

這裏的關鍵是,LogStream已和EatStream有一個共同的基礎和網絡運營商()返回參照。它不一定是std :: ostream,這只是因爲便利或拉丁使用。只要您返回對公共基礎的引用,就可以正確調用vftable中的虛擬。請注意,您所返回的引用由Logger保持活動狀態,所以它不應早於operator()()的結果超出範圍(對於您的情況,這可能不是問題,只是爲了完整性)。

+0

雖然我可以看到這肯定會工作 - 我沒有想過使用空流。但是,我已經從原始帖子中刪除了某些解決方案無法實現的內容。一旦我的初始版本工作,我計劃改變它,以便它可以接受一系列LogStreams,這樣您就可以將調試寫入文本文件,將信息回顯到屏幕,並將所有信息寫入另一個文件。 –

+0

你當然可以做到這一點,只需創建一個LogMultipleStream,該繼承自公共基礎並具有LogStreams和運算符<<()的向量;然後將其存儲在Logger中而不是LogStream中。 – lorro

+0

但是,如何從函數調用操作符返回兩次?這就是爲什麼我試圖弄清楚是否有辦法獲得完整的流。 –