65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (27投票s)

2003年1月10日

1分钟阅读

viewsIcon

115463

downloadIcon

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 上尝试过(因为我只有这个),但我相信它可以在……好吧,几乎任何东西上工作。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.