组合可选宏以形成列表

时间:2015-01-13 11:42:21

标签: c++ macros c-preprocessor

我有两个预处理器宏" A"和" B"需要组合为初始化列表。 E.g:

MyType obj = { A, B };

但是,A可以为空,单个值或列表,B可以为空或单个值。所以问题就变成了如何避免插入一个不必要的逗号,即当A或B为空时。

因此,伪CPP代码解决方案将是:

#if EMPTY(B)
MyType obj = { A };
#else
MyType obj = { A, B };
#endif

但是如何编写EMPTY()测试以使#define A为真,对于#define A 1,2,3它是假的? (我在使用帮助程序宏时没有得到任何可能编译的错误......)

请注意,宏来自外部配置机制,所以面向CPP的解决方案很自然,而不是不可避免的公平问题"为什么要用宏来做这个?"

2 个答案:

答案 0 :(得分:2)

无法测试宏是否已定义,但在编译时是否为空。预编译器允许比较整数,即

#if A > 5

但不是字符串:

#if A == ""  // Not allowed!

并且肯定不支持列表。我想说最简单的方法是为每个宏创建一个初始化列表,然后在运行时将它们组合起来,如:

MyType objA = { A };
MyType objB = { B };
// ... now combine them ...

当然,这非常简单并且高度依赖于您的宏,但如果保证它们是有效的列表,这应该可行。

答案 1 :(得分:2)

使用Boost.Preprocessor

#include <boost/preprocessor.hpp>

#define A (a)(b)
#define B (x)(y)(z)

#define SAFE_ENUM(seq) \
    BOOST_PP_IIF( \
        BOOST_PP_IS_BEGIN_PARENS(seq), \
        BOOST_PP_SEQ_ENUM, \
        BOOST_PP_TUPLE_EAT(1) \
    )(seq) \
    /**/

MyType obj = { SAFE_ENUM(A B) };

需要一定程度的间接,因为Boost序列不能为空(如果AB都是空的,那就是空的。

**编辑**

改为使用Chaos.Preprocessor

#include <chaos/preprocessor/control/inline_unless.h>
#include <chaos/preprocessor/detection/is_empty.h>
#include <chaos/preprocessor/seq/enumerate.h>

#define A a, b
#define B x, y, z

#define CONVERT(...) \
    CHAOS_PP_INLINE_UNLESS(CHAOS_PP_IS_EMPTY_NON_FUNCTION(__VA_ARGS__))( \
        (__VA_ARGS__) \
    ) \
    /**/

MyType obj = {
    CHAOS_PP_SEQ_ENUMERATE(
        CONVERT(A) CONVERT(B)
    )
};