绕过对 vararg #define 的需求,以便在 TRACE 宏中自动使用 __FILE__ 和 __LINE__






4.77/5 (27投票s)
2003年1月10日
1分钟阅读

115463

812
你是否曾经编写过 #define TRACE, #define TRACE1, #define TRACE2 等,仅仅是为了能够在宏中使用 __FILE__ 宏和 printf 样式的格式化?
引言
可能别人之前已经做过这个了,但我没有见过,所以只能自己想办法。
如果你想创建一个将内容输出到日志的预处理器宏,通常你希望它像这样工作
MYTRACE( "something something: %s (%d)", str, i );
这有点棘手,因为你希望它接受可变参数,但我经常看到这样的写法
#define MYTRACE MyTrace
static inline MyTrace( const char* msg, ... )
{
// ...
}
__FILE__ 和 __LINE__
但是,如果你希望 MYTRACE
自动将 __FILE__
和 __LINE__
放入跟踪消息中,你就会遇到问题。你不能在 MyTrace()
函数内部使用它们,因为 __FILE__
和 __LINE__
总是指向定义它的头文件,而不是你调用 MYTRACE
的位置——而且不可能有一个 vararg
预处理器宏。
如果你对这类事情很固执,你会这样做
#define MYTRACE1( m, a ) MyTrace( __FILE__, __LINE__, m, a )
#define MYTRACE2( m, a, b ) MyTrace( __FILE__, __LINE__, m, a, b )
#define MYTRACE3( m, a, b, c ) MyTrace( __FILE__, __LINE__, m, a, c )
(等等。) 虽然使用起来很糟糕,因为你每次添加参数时都必须更改你使用的宏。
解决方案!
通过一点想象力,可以解决这个问题(至少在 C++ 中)
class tracing_output_debug_string
{
private:
const char* m_file;
int m_line;
enum { MY_BUFFER_SIZE = 1024 };
public:
tracing_output_debug_string( const char* file, int line ) :
m_file( file ),
m_line( line )
{
}
void operator()( const char* Format, ... )
{
// vararg stuff
}
};
#define MYTRACE (tracing_output_debug_string( __FILE__, __LINE__ ))
可下载的项目在 .h 文件中有一个实现(它写入 ::OutputDebugString()
),还有一个小测试,表明它确实有效。
我只在 VS.NET 上尝试过(因为我只有这个),但我相信它可以在……好吧,几乎任何东西上工作。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。