Я пытаюсь условно расширить макрос до «(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())
Что я делаю неправильно?
Вы можете заставить порядок оценки соответствовать ожидаемому, абстрагируя ветви 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, и работает почти так же (неполное имя, похожее на функцию макроса, будет передано вокруг плюс список параметров, пока не будет завершено ).