• 可变参数宏的展开,宏重载


    因某些方面需要,涉及到可变参数宏的展开及可变参数数量的确定,在网上查找了大部分资料,基本如下所述

    http://www.cnblogs.com/goooon/p/5642514.html

    涉及到的问题点:不支持0个参数

    经过VS2010及gcc version 4.9.1 (GCC)两个编译器编译,可以至少支持此两种编译器下的0参数问题。

    以上文中的代码为例:

    定义部分

    #define PRIVATE_ARGS_GLUE(x, y) x y

    #define PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT(_1,_2,_3,_4,_5,_6,_7,_8,_9, _10, N, ...) N
    #define PRIVATE_MACRO_VAR_ARGS_IMPL(args) PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT args
    #define COUNT_MACRO_VAR_ARGS(...) PRIVATE_MACRO_VAR_ARGS_IMPL((__VA_ARGS__,10, 9,8,7,6,5,4,3,2,1,0))

    #define PRIVATE_MACRO_CHOOSE_HELPER2(M,count)  M##count
    #define PRIVATE_MACRO_CHOOSE_HELPER1(M,count) PRIVATE_MACRO_CHOOSE_HELPER2(M,count)
    #define PRIVATE_MACRO_CHOOSE_HELPER(M,count)   PRIVATE_MACRO_CHOOSE_HELPER1(M,count)

    #define INVOKE_VAR_MACRO(M,...) PRIVATE_ARGS_GLUE(PRIVATE_MACRO_CHOOSE_HELPER(M,COUNT_MACRO_VAR_ARGS(__VA_ARGS__)), (__VA_ARGS__))

    实现部分

    #define PRINT_ARGS1(a1) std::cout<<a1<<std::endl
    #define PRINT_ARGS2(a1,a2) std::cout<<a1<<","<<a2<<std::endl
    #define PRINT_ARGS3(a1,a2,a3) std::cout<<a1<<","<<a2<<","<<a3<<std::endl
    #define PRINT_ARGS4(a1,a2,a3,a4) std::cout<<a1<<","<<a2<<","<<a3<<","<<a4<<std::endl

    使用部分

    INVOKE_VAR_MACRO(PRINT_ARGS, 4);
    INVOKE_VAR_MACRO(PRINT_ARGS, 4, 5);
    INVOKE_VAR_MACRO(PRINT_ARGS, 4, 5, 6);

    如何实现?

    #define PRINT_ARGS0() std::cout<<"ARGS0"<<std::endl

    如何使用?

    INVOKE_VAR_MACRO(PRINT_ARGS);

    参考  http://en.cppreference.com/w/cpp/preprocessor/replace

    some compilers offer an extension that allows ## to appear after a comma and before __VA_ARGS__,

    in which case the ## does nothing when __VA_ARGS__ is non-empty,

    but removes the comma when __VA_ARGS__ is empty: this makes it possible to define macros such as fprintf (stderr, format, ##__VA_ARGS__)

    看不懂?那看看http://blog.csdn.net/sakaue/article/details/29591631

     

    那是不是可以改成这样呢?

    #define PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9, _10, N, ...) N
    #define PRIVATE_MACRO_VAR_ARGS_IMPL(args) PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT args
    #define COUNT_MACRO_VAR_ARGS(...) PRIVATE_MACRO_VAR_ARGS_IMPL((0,##__VA_ARGS__,10, 9,8,7,6,5,4,3,2,1,0))

    在gcc version 4.9.1 (GCC)下是没有问题的,

    可以输出

    ARGS0
    4
    4,5
    4,5,6

    但是在vs2010中就出现了编译错误

    warning C4003: “PRINT_ARGS1”宏的实参不足
    error C2059: 语法错误:“<<”

    那是不是意味着vs2010不支持 如果可变参数被忽略或为空,‘##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。

    在vs2010中定义

    #define debug(format, ...) fprintf (stderr, format, ##__VA_ARGS__)

    vs2010中实现

    debug("abc");

    结果编译没有问题,输出也正常。

    因此,应该是vs2010和gcc在预编译中,对于宏的处理存在差异。最明显的一个例子就是参考google chromium中logging,

    typedef int LogSeverity;
    const LogSeverity LOG_VERBOSE = -1;  // This is level 1 verbosity
    // Note: the log severities are used to index into the array of names,
    // see log_severity_names.
    const LogSeverity LOG_INFO = 0;
    const LogSeverity LOG_WARNING = 1;
    const LogSeverity LOG_ERROR = 2;
    const LogSeverity LOG_FATAL = 3;

    LOG(INFO) << "Found " << num_cookies << " cookies";

    其中涉及使用 ::logging::LOG_ ## severity  组成一个 ::logging::LOG_INFO

    个人修改时,添加了一个LOG_DEBUG,结果vs2010上编译使用都没有问题,gcc version 4.9.1 (GCC)下编译不过,说找不到LOG_1,修改为LOG_DEBUGGING,编译及输出均OK。

    那么如何在此两种编译环境下解决不支持0个参数问题呢?

    测试代码

    #define PP_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9, _10, N, ...) ((#_1 == "") ? 0 : N)
    #define PP_NARG_(args)  PP_ARG_N args
    #define PP_NARG(...) PP_NARG_((__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0))

    #define TESTINVOKE_VAR_MACRO(M,...) std::cout<<PP_NARG(__VA_ARGS__)<<std::endl

    TESTINVOKE_VAR_MACRO(PRINT_ARGS);
    TESTINVOKE_VAR_MACRO(PRINT_ARGS, 4);
    TESTINVOKE_VAR_MACRO(PRINT_ARGS, 4, 5);
    TESTINVOKE_VAR_MACRO(PRINT_ARGS, 4, 5, 6);

    输出

    0
    1
    2
    3

    但要针对#define PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT(_1,_2,_3,_4,_5,_6,_7,_8,_9, _10, N, ...) N 的修改,那就要需要慢慢修改,为什么呢?

    参考宏替换规则,如果将N改为一个表达式,那还能找到对应的 PRINT_ARGSX 吗?显然是不能的。但如果作为函数传参,这个方法还是能够胜任的,比如上述的测试代码。

  • 相关阅读:
    实战 Windows下搭建Objectivec的编译环境
    C# 协变和逆变 精解(直观明了,简单易懂)
    求两个字符串的最大公共串
    [C++][数据结构]队列(queue)的实现
    转换一个矩阵(2维数组)为HTML Table
    [C++][数据结构][算法]单链式结构的深拷贝
    LaTeX 中的特殊符号
    [C++11][数据结构]自己的双链表实现
    现代诗十则
    [C++11][算法][穷举]输出背包问题的所有可满足解
  • 原文地址:https://www.cnblogs.com/liaokang/p/5949835.html
Copyright © 2020-2023  润新知