zoukankan      html  css  js  c++  java
  • 在宏定义中怎么使用可变参数

    http://www.cppblog.com/API/archive/2013/08/19/202633.html

    几天前,在CSDN论坛看到这么一则讨论:在宏定义中怎么使用可变参数?(http://expert.csdn.net/Expert/topic/2925/2925165.xml)。楼主希望能定义这样的macro:

    #define fun1(a, b, ...) fun2(__FILE__, __LINE__, a, b, ...)

    我猜楼主是想写trace,如果不能使用可变参数的macro,那么就得像MFC那样写一堆TRACE macros:


    // 取自 MFC 7.1 的 afx.h
    // The following trace macros are provided for backward compatiblity
    // (they also take a fixed number of parameters which provides
    // some amount of extra error checking)
    #define TRACE0(sz) TRACE(_T("%s"), _T(sz))
    #define TRACE1(sz, p1) TRACE(_T(sz), p1)
    #define TRACE2(sz, p1, p2) TRACE(_T(sz), p1, p2)
    #define TRACE3(sz, p1, p2, p3) TRACE(_T(sz), p1, p2, p3)

    太丑陋了!还好,C99标准支持Variadic Macros,在GCC中,可以这么写:

    // http://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html
    #define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)

    还可以顺便打印文件名和行号:

    #define debug(format, ...) do {/
    fprintf(stderr, "%s (%d): ", __FILE__, __LINE__);/
    fprintf(stderr, format, __VA_ARGS__);/
    } while (0)

    但可惜Visual C++ 7.1还不支持这项功能:( 不过我们在C++中至少可以绕弯解决,做到既能自动记录文件名和行号,又能使用变长参数调用。这个办法不是我独创的,实际上ATL的atltrace.h中就有它的实现(CtraceFileAndLineInfo class),我在Code Project也找到了相同的实现(http://www.codeproject.com/debug/location_trace.asp),甚至在CUJ的C++ Experts Forum 也能看到相近的做法(http://www.cuj.com/documents/s=8250/cujcexp2106alexandr/),当然Alexandrescu的办法技巧性更强。

    思路:写一个重载了 operator() 的class,令 TRACE 宏返回该class的一个object:

    #include 
    #include

    #ifndef NDEBUG // debug mode

    class tracer
    {
    public:
    tracer(const char* file, int line)
    : file_(file), line_(line)
    {}

    void operator()(const char* fmt, ...)
    {
    va_list ap;

    // print the file name and line number
    fprintf(stderr, "%s (%d): ", file_, line_);

    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);

    fprintf(stderr, "/r/n"); // print the new-line character
    }

    private:
    // copy-ctor and operator=
    tracer(const tracer&);
    tracer& operator=(const tracer&);

    private:
    const char* file_;
    int line_;
    };
    #define TRACE (tracer(__FILE__, __LINE__))
    #else // NDEBUG
    #define TRACE (void)
    #endif // NDEBUG

    int main()
    {
    #ifndef NDEBUG
    tracer(__FILE__, __LINE__)("%x", 123);
    #endif

    TRACE("%s", "Happy debugging.");
    }

    这样做是multithreading-safe的。G++ 3.3.1 / Visual C++ 7.1 / Borland C++ 5.5.1 通过。 

  • 相关阅读:
    数据库查询服务框架
    postgresql清理工具
    postgre索引
    SAP模块一句话入门(专业术语的理解)
    SAP订单结算详解
    SAP Datasheet
    ASP.NET MVC5 网站开发实践
    VMware S/4 HANA OP 1511虚拟机下载,64G内存限制解决方案
    SAP标准教材列表
    SAP文章链接
  • 原文地址:https://www.cnblogs.com/0530z/p/3344390.html
Copyright © 2011-2022 走看看