我试图有条件地将宏扩展到"("或" 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())
我做错了什么?
答案 0 :(得分:1)
您可以通过抽象出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()
由于THEN
和ELSE
不是完整名称,因此在IF
展开之前不会展开分支;返回时,该值与PAS_
组合以形成新的有效定义,并在此时展开。
你也可以参数化THEN
和ELSE
宏并使这种技术更通用(和IMO更优雅):将参数传递给一个不完整的名称基本上形成一个thunk,并且工作几乎相同方式(不完整的类函数宏名称将传递给参数列表,直到它完成)。