2012-08-28 89 views
0

我用宏在日誌機制工作的有線輸出:更大的宏觀結構

#define LOGFATAL 1 // very serious errors 
#define TOSTRING(s) dynamic_cast< std::ostringstream & >((std::ostringstream() << s)).str() 

#define LOG_TRANSFER(t, s) "[" << t << "] " << s 

void inline print_log(const char *level, const std::string& value) 
{ 
    std::cout << "[" << timestamp() << "]["<< level << "]" << value << std::endl; 
} 

#ifdef DEBUGGING 
    #define DEBUG_OUT(l, s) print_log(l, TOSTRING(s)); 
#else 
    #define DEBUG_OUT(s, l) 
#endif 


#if DEBUGGING >= LOGFATAL 
    #define LOG_FATAL(s)  DEBUG_OUT("FATAL", s) 
#else 
    #define LOG_FATAL(s) 
#endif 

我用它自己的方式: LOG_TRACE(LOG_TRANSFER(PTR「的MemoryManager>分配 「)) LOG_TRACE(」的MemoryManager>尺寸:「< < active_list.size())

什麼GCC所做的是:

print_log("TRACE", dynamic_cast< std::ostringstream & >((std::ostringstream() << "[" << ptr << "] " << "MemoryManager > allocate ")).str()); 
print_log("TRACE", dynamic_cast< std::ostringstream & >((std::ostringstream() << "MemoryManager > size : " << active_list.size())).str()); 

這看起來不錯,但我得到以下輸出:

[0 s][TRACE]0x80940d40x9988ea8] MemoryManager > allocate 
[0 s][TRACE]0x80941e01 

錯誤在哪裏?

回答

4

問題是與這樣的:

dynamic_cast< std::ostringstream & >((std::ostringstream() << s)).str() 

或更精確地與此:

std::ostringstream() << s 

的原因是表達std::ostringstream()是臨時對象在其上不能調用非成員過載<<,因爲所有非成員<<重載都將第一個參數作爲std::ostream&,這是非常量引用。但是臨時的不能綁定到非const引用。因此,如果要打印char*,則會調用成員函數,該函數將轉換爲void*並打印地址。

你需要做一點小事。轉換的臨時對象(右值)爲基準類型(左值)爲:

std::ostringstream().flush() << s 

我爲什麼會叫flush()這樣?

那麼你可以調用臨時對象的成員函數。我選擇了flush(),因爲它返回的是非常量引用std::ostream&,這是我們需要的。

它使不同的是這樣的:

std::ostringstream() << "nawaz" ; //it prints the address of "nawaz". 
std::ostringstream().flush() << "nawaz" ; //it prints "nawaz" 

第一個調用它打印的地址,第二個呼叫的非成員operator<<它打印的c字符串構件operator<<。這是現場背後的差異。

那麼試試這個:

dynamic_cast< std::ostringstream & >((std::ostringstream().flush() << s)).str() 

這應該工作。

另外,我在這裏建議static_cast,因爲你已經知道類型:

static_cast< std::ostringstream & >((std::ostringstream().flush() << s)).str() 

它不依賴於RTTI。

+1

右值轉換的不錯解釋 - 當我自己遇到這個問題時,我還沒有意識到.flush()技巧來解決它。 – Pyrce