2012-08-28 47 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