有线输出更大的宏构造

时间:2012-08-28 16:08:56

标签: c++ gcc macros

我使用宏来处理日志记录机制:

#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&gt; allocate”))     LOG_TRACE(“MemoryManager&gt; size:”&lt;&lt;&lt; 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

错误在哪里?

1 个答案:

答案 0 :(得分:4)

问题在于:

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

或更准确地说:

std::ostringstream() << s

原因是表达式std::ostringstream()是一个临时对象,您无法在其上调用非成员重载<<,因为所有非成员<<重载都将第一个参数作为{{ 1}},这是非const引用。但是临时不能绑定非const引用。因此,当您要打印std::ostream&时,会调用成员函数,该函数将转换为char*并打印地址。

你需要做一点点破解。将临时对象(rvalue)转换为引用类型(左值):

void*

为什么我会这样叫std::ostringstream().flush() << s

您可以在临时对象上调用成员函数。我选择了flush(),因为它返回flush(),这是非const引用,这就是我们需要的。

它的不同之处在于:

std::ostream&

第一个调用打印地址的成员std::ostringstream() << "nawaz" ; //it prints the address of "nawaz". std::ostringstream().flush() << "nawaz" ; //it prints "nawaz" ,第二个调用打印c-string的非成员operator<<。这就是幕后的差异。

所以试试这个:

operator<<

这应该有效。

此外,我建议您dynamic_cast< std::ostringstream & >((std::ostringstream().flush() << s )).str() ,因为您已知道类型:

static_cast

它不依赖于RTTI。