#define M(N)\
#if N == 5\
/*several lines of code that
Can't be replaced with a
tertnary operator*/
#else\
N;\
#endif
当我像这样使用这个宏时
M(5);
我希望输出为
// everything within the #if #else block
但它没有编译。
我并不感到意外,因为它不能编译:我知道#if不能用于连续行,即“\”。
我也试过
#define POUND_IF #if
然后使用POUND_IF但不起作用。
这可能吗?
是否有一些漂亮的Boost预处理器可以使用?
答案 0 :(得分:6)
简洁地说,你做不到。不过,您可以依赖优化器:
#define M(N)\
do { if (N == 5) { \
/*several lines of code that
Can't be replaced with a
ternary operator*/ \
} else { N; } } while (0)
如果编译器在运行代码时可以确定N
的值为5(例如,您编写M(5)
),那么只有if
正文中的代码将包含在生成的代码中。如果编译器在运行代码时可以确定N
的值不为5,则它将仅生成else
子句正文中的代码。如果它无法确定该值是什么,预处理器也无法这样做,但编译器将包含所有代码。
答案 1 :(得分:5)
宏定义不能包含预处理程序指令(以println
开头的任何内容)。
要有条件地扩展到某些值,需要相当复杂的宏观,并且可能并不总是以您想要的方式运行。上面的例子可以这样写:
#
但这非常脆弱。例如,您只能使用某些类型的表达式作为#define ONE_OR_TWO(...) ONE_OR_TWO_(__VA_ARGS__, 2, 1,)
#define ONE_OR_TWO_(_1, _2, X, ...) X
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B
#define M(N) CAT(IF_, ONE_OR_TWO(CAT(IS_, N)))({\
code; \
code; \
}, N)
#define IS_5 ,
#define IF_1(A, B) B
#define IF_2(A, B) A
M(5); //-> { code; code; }
M(8); //-> 8
的参数 - 它们必须具有允许连接的语法结构,并且没有未包装的逗号 - 并且它仅适用于预定值(例如,用于比较使用此方法无法使用比简单数字更复杂的东西,因为您无法使用更复杂的表达式构建宏名称。)
但原则上可以做到。您只需要成千上万行宏定义来覆盖一组有用的案例,而不是像这样的普通案例。您可以使用Order-PP或Boost.Preprocessor之类的元编程库来获取这些文件,但如果您在语法中略微下滑,请准备好应用于模糊的错误消息。