我有两个预处理器宏" 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的解决方案很自然,而不是不可避免的公平问题"为什么要用宏来做这个?"
答案 0 :(得分:2)
无法测试宏是否已定义,但在编译时是否为空。预编译器允许比较整数,即
#if A > 5
但不是字符串:
#if A == "" // Not allowed!
并且肯定不支持列表。我想说最简单的方法是为每个宏创建一个初始化列表,然后在运行时将它们组合起来,如:
MyType objA = { A };
MyType objB = { B };
// ... now combine them ...
当然,这非常简单并且高度依赖于您的宏,但如果保证它们是有效的列表,这应该可行。
答案 1 :(得分:2)
#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序列不能为空(如果A
和B
都是空的,那就是空的。
**编辑**
改为使用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)
)
};