Мне нужно использовать макрокоманду variadic для расширения до нескольких вариаций класса. Так как они должны иметь разные имена, основанные на вводе макросов, я не могу просто использовать шаблоны. Проблема в том, что я не могу расширить запятую (,
), и в моем классе есть функции, которые принимают несколько параметров (для которых мне нужно использовать символ запятой).
boost
обеспечивает BOOST_PP_COMMA()
макрос, который расширяется до запятой, но работает только вне конструкций цикла. Я предполагаю, что проблема в том, что BOOST_PP_COMMA()
раскрывается один раз, а затем обрабатывается как запятая, после чего программа прерывается.
Чтобы проиллюстрировать проблему, предположим, что у меня есть макрофункция, которая принимает переменное число параметров и выдает число запятых, равное количеству заданных ей параметров. Наивное решение было бы так:
#define TEST(...)\
BOOST_PP_REPEAT( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
#define MACRO(z, n, data) BOOST_PP_IF(1,BOOST_PP_COMMA(),BOOST_PP_COMMA())\
Но это приводит к ряду ошибок, потому что запятая раскрывается и макрос думает, что они разделяют параметры.
Есть ли способ обойти эту проблему?
С помощью BOOST_PP_REPEAT
с макросом, который может быть вызван с ожидаемыми аргументами, будет работать нормально, и это даже предотвращает необходимость BOOST_PP_COMMA
:
#define PRINT_COMMAS(...)\
BOOST_PP_REPEAT( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
PRINT_COMMAS_MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
#define PRINT_COMMAS_MACRO(z, n, data) ,
Чтобы сохранить дополнительный макрос, вы можете воспользоваться тем, что BOOST_PP_ENUM
добавляет запятые между расширениями, добавляя один к числу повторений и отбрасывая аргументы макроса, используя BOOST_PP_TUPLE_EAT
:
#define PRINT_COMMAS(...)\
BOOST_PP_ENUM( \
BOOST_PP_INC(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), \
BOOST_PP_TUPLE_EAT(), \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
Я лично думаю, что первое более понятно.