boost-preprocessor - 如果 variadic 为空,则 Boost 预处理器会跳过

标签 boost-preprocessor

我有以下 boost 预处理器宏来生成一个函数

extern "C" EXPORT out name(BOOST_PP_SEQ_FOR_EACH_I(PARAMETER_LIST, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))

这很好用,除非 __VA_ARGS__ 为空。经过一番搜索后,我找到了一种使用 BOOST_PP_VARIADIC_SIZE 来计算 __VA_ARGS__ 中参数数量的方法。经过一番思考,我写了这个 MACRO:

extern "C" EXPORT out name(BOOST_PP_IF(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_SEQ_FOR_EACH_I(PARAMETER_LIST, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), void))

我认为这应该可行,但是我不断收到以下警告

 warning C4002: too many actual parameters for macro 'BOOST_PP_IIF_1'

虽然这是一个警告,但它似乎仍然破坏了预处理器。当传递多个参数时,它只会处理第一个。我觉得这很奇怪,如果打破一切都是一种奇怪的方式,怎么会添加这个?我已经检查了逗号和括号一百次,但它们看起来还不错。我该如何修复这个预处理器?

http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/ref/if.html

编辑:这个回归似乎是相关的:https://svn.boost.org/trac/boost/ticket/8606

最佳答案

实现:

#include <boost/preprocessor.hpp>

// based on the: http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments
#define __ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define __HAS_COMMA(...) __ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define __TRIGGER_PARENTHESIS_(...) ,
#define __PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define __IS_EMPTY_CASE_0001 ,
#define __IS_EMPTY(_0, _1, _2, _3) __HAS_COMMA(__PASTE5(__IS_EMPTY_CASE_, _0, _1, _2, _3))

#define TUPLE_IS_EMPTY(...) \
    __IS_EMPTY( \
        /* test if there is just one argument, eventually an empty one */ \
        __HAS_COMMA(__VA_ARGS__), \
        /* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma */ \
        __HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__),                 \
        /* test if the argument together with a parenthesis adds a comma */ \
        __HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
        /* test if placing it between _TRIGGER_PARENTHESIS_ and the parenthesis adds a comma */ \
        __HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
    )

#define __GEN_EMPTY_ARGS(...) \
    void

#define __GEN_NONEMPTY_ARGS_CB(unused, data, idx, elem) \
    BOOST_PP_COMMA_IF(idx) elem arg##idx

#define __GEN_NONEMPTY_ARGS(seq) \
    BOOST_PP_SEQ_FOR_EACH_I( \
         __GEN_NONEMPTY_ARGS_CB \
        ,~ \
        ,seq \
    )

#define GEN(out, name, ...) \
    extern "C" EXPORT out name( \
        BOOST_PP_IF( \
             TUPLE_IS_EMPTY(__VA_ARGS__) \
            ,__GEN_EMPTY_ARGS \
            ,__GEN_NONEMPTY_ARGS \
        )(BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
    ) {}

// test
GEN(void, finc0, int, char, long)
GEN(void, func1)

输出:

extern "C" EXPORT void finc0( int arg0 , char arg1 , long arg2 ) {}
extern "C" EXPORT void func1( void ) {}

关于boost-preprocessor - 如果 variadic 为空,则 Boost 预处理器会跳过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18851889/

相关文章:

c++ - 宏不通过直接调用扩展,而是通过间接调用扩展

c++ - 定义带有添加前缀的新宏的宏

c++ - 如何确定 boost.preprocessor 元组中的元素计数?

C++ 在编译时注册类成员 var

c++ - Boost.Preprocessor 使用宏而不是简单定义的基本原理?

C++ 泛型编程的精妙之处

c++ - 在使用 boost 预处理器序列时避免扩展宏

c++ - 一般打印一系列变量及其名称

c++ - 使用 Boost.Preprocessor 来减少代码重复