组合可选宏以形成列表
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 ...
当然这非常简单并且高度依赖于您的宏,但只要保证它们是有效列表,这应该可行。
#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
都为空。
** 编辑 **
#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)
)
};
我有两个预处理器宏 "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 ...
当然这非常简单并且高度依赖于您的宏,但只要保证它们是有效列表,这应该可行。
#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
都为空。
** 编辑 **
#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)
)
};