2

我正在尝试有条件地将宏扩展为“(a”或“b)”,但这样做的天真方法不适用于我正在使用的任何一个编译器(Microsoft C/C++ 和 NDK 编译器)。例子:

// This works on both compilers, expands to ( a ) as expected
#define PARENS_AND_SUCH BOOST_PP_IF(1, BOOST_PP_LPAREN() a BOOST_PP_RPAREN(), b)

// MSVC: syntax error/unexpected end of file in macro expansion 
// NDK: unterminated argument list
#define PARENS_AND_SUCH BOOST_PP_IF(1, BOOST_PP_LPAREN() a, b)

// Desired expansion: ( a
// MSVC expansion: ( a, b )
// NDK: error: macro "BOOST_PP_IIF" requires 3 arguments, but only 2 given
#define PARENS_AND_SUCH BOOST_PP_IF(1, BOOST_PP_LPAREN() a, b BOOST_PP_RPAREN())

我究竟做错了什么?

4

1 回答 1

1

您可以通过抽象出 to 子定义的分支来强制评估顺序符合预期的IF顺序,并延迟它们的扩展,直到条件返回一个分支:

#define PARENS_AND_SUCH BOOST_PP_CAT(PAS_, BOOST_PP_IF(1, THEN, ELSE))
#define PAS_THEN BOOST_PP_LPAREN() a
#define PAS_ELSE b BOOST_PP_RPAREN()

由于THENELSE不是完整名称,因此在扩展之前不会扩展分支IF;当它返回时,该值与 结合PAS_形成一个新的有效定义,并将在那时扩展。

您还可以参数化THENandELSE宏并使该技术更通用(并且 IMO 更优雅):将参数传递给不完整的名称本质上形成了一个 thunk,并且工作方式几乎相同(不完整的类似函数的宏名称将被传递加上参数列表,直到完成)。

于 2014-07-25T01:05:00.063 回答