组合可选宏以形成列表

Combining optional macros to form a list

我有两个预处理器宏 "A" 和 "B" 需要合并为初始化列表。例如:

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 为假? (我在 helper macros 上犯了错误,但没有得到任何可能编译的东西......)

请注意,宏来自外部配置机制,因此像这样的面向 CPP 的解决方案是很自然的选择,而不是不可避免的公平问题 "why are you doing this with macros?"

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

#if A > 5

但不是字符串:

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

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

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

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

使用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)
    )
};