2015-05-21 102 views
1

我正在寫我自己的記錄器。我知道那裏有很多,但我想自己寫。它有消息在離開示波器時被記錄。所以如果我打電話給Logger::Error(__FILE__,__LINE__) << "some error",它會被直接記錄下來,因爲沒有對變量進行分配。記錄器記錄2次而不是一次,因爲複製

但我想有一個消息記錄範圍的時間。因此它確定了自創建和刪除以來的時間。因此我需要它被分配給一個變量中的範圍與例如本馬爾科:#define LOG_SCOPE_TIME LogTimer ___t = Logger::Timer(__FILE__,__LINE__) 它可用於這樣的:

int main() 
{ 
    { 
    LOG_SCOPE_TIME << "Some scope"; 
    //do something to mesure 
    } 
} 

輸出示例:

[timer][File:main.cpp][Line:19][thread:8024][21-05-2015][13:15:11] Some scope[0µs] 
[timer][File:main.cpp][Line:19][thread:8788][21-05-2015][13:15:11] Some scope[118879µs] 

但這實際上導致2日誌。臨時創建的第一個LogTime對象(時間爲0μs),第二個爲實際示波器時間。

我該如何預防?有什麼建議麼?這裏是一個簡化的例子:

#include <iostream> 
#include <chrono> 

class LogTimer { 
    std::string str; 
    std::chrono::high_resolution_clock::time_point m_start; 
public: 
    LogTimer(const std::string& file, int i) 
     : m_start(std::chrono::high_resolution_clock::now()) 
    { 
     str = file + ':' + std::to_string(i); 
    } 

    ~LogTimer() { 
     auto end = std::chrono::high_resolution_clock::now(); 
     auto duration = std::chrono::duration_cast<std::chrono::microseconds> 
        (end - m_start).count(); 
     std::cout << str << " [" << duration << "µs]\n"; 
    } 

    LogTimer& operator<<(const std::string& p) { 
     str += '[' + p + ']'; 
     return *this; 
    } 
}; 

namespace Logger { 
    LogTimer Timer(const std::string& f, int i) { 
     return LogTimer(f, i); 
    } 
} 

#define LOG_SCOPE_TIME LogTimer ___t = Logger::Timer(__FILE__,__LINE__) 

int main() 
{ 
    LOG_SCOPE_TIME << "something"; // logs two lines 
} 
+1

你能想出一個更簡單的例子嗎?這是很多代碼。 – Barry

+0

虐待盡我所能給我幾分鐘 – BennX

+1

這裏是一個[簡短的例子](http://coliru.stacked-crooked.com/a/b00dabea34c4364f) – Barry

回答

2

您正遇到運算符優先級問題,排序。當您使用宏:

LOG_SCOPE_TIME << "Some scope"; 

被擴展成:

LogTimer ___t = Logger::Timer(__FILE__,__LINE__) << "Some scope"; 

它得到的評價:

LogTimer ___t = (Logger::Timer(__FILE__,__LINE__) << "Some scope"); 

因爲<<=更高的優先級。因此,由於編譯器現在需要創建一個臨時Timer來執行<< "Some Scope",然後複製到___t(這在技術上是一個保留名稱),因此您正在防止副本的發生。額外的副本意味着一個額外的析構函數,在你的情況下意味着一個額外的行記錄。

您需要確保複製elision。我能想到的最簡單的方法是改變你的宏來完成:

#define LOG_SCOPE_TIME LogTimer ___t = Logger::Timer(__FILE__,__LINE__); ___t 

這樣一來,你的原來的例子擴展爲:

LogTimer ___t = Logger::Timer(__FILE__,__LINE__); ___t << "Some scope"; 

沒有問題存在。

+0

是的,小事情按預期固定它。非常感謝您的時間來檢查這一點。 – BennX