C ++ макрос распаковать и присоединиться - PullRequest
0 голосов
/ 01 октября 2019

Я пытаюсь определить структуру C ++ с переменными членами макросом как часть системы метаданных самоанализа. Учитывая, что я создаю определение структуры, я не могу использовать шаблоны времени компиляции (верно?). Вместо этого я создаю макрос с переменным числом аргументов, который должен принимать кортежи (тип, имя), но у меня возникли проблемы при написании макроса, который будет расширяться и соединять кортеж с символом, чтобы получить что-то вроде

JOIN(.,(a,A)) -> a.A или JOIN(&,(b,B)) -> b&B.

Я работаю в Visual Studio 2017, и часть моей путаницы может заключаться в несоответствии в расширении VA_ARGS в MSVC и GCC: Расширение MSVC ++ с переменным макросом

Мой подход состоял в том, чтобы написать макрос для распаковки, который просто удаляет скобки из кортежа, и макрос соединения, который бы соединял аргументы по желаемой строке:

#define UNPACK(a, b) a, b
#define JOINAB(a, b, S) a S b
#define JOINTUPLE(S, ab) JOINAB(UNPACK ab, S)

Но это не такработать, как кажется, макрос не оценивается в правильном порядке. Затем я попытался явно расширить аргументы, например #define EXPAND(args) args, но безуспешно.

Наконец-то я нашел обходной путь, вставив скобку аргумента в распаковку, тем самым «форсируя» порядок вычисления:

#define EXPAND(...) __VA_ARGS__
#define UNPACK(a, b) (a, b
#define JOINAB(a, b, S) a S b
#define JOINTUPLE(S, ab) EXPAND(JOINAB UNPACK ab, S))

, который работает, но кажется очень хакерским ...

Мои вопросы

  1. Есть ли правильный способ оценки неупакованного результата? ?
  2. Зачем мне РАСШИРЯТЬСЯ? Без него выражение JOINTUPLE(:,(a,B)) преобразуется в JOIN (a, B, :), но почему это не обрабатывается далее до a : B?
  3. Может ли быть способ решить это с помощью оператора вставки токена? S существует только в 3 вариантах.

1 Ответ

0 голосов
/ 01 октября 2019

После комментария Квентина решение состоит в том, чтобы включить скобку аргумента в макрос EXPAND:

#define EXPAND(...) __VA_ARGS__
#define UNPACK(a, b) a, b
#define JOINAB(a, b, S) a S b
#define JOINTUPLE(S, ab) EXPAND(JOINAB EXPAND((UNPACK ab, S)))

Полное решение с переменными аргументами следующее:

#define JOIN1(S, aA) JOINTUPLE(S, aA)
#define JOIN2(S, aA, bB) JOINTUPLE(S, aA), JOINTUPLE(S, bB)
#define JOIN3(S, aA, bB, cC) JOINTUPLE(S, aA), JOINTUPLE(S, bB), JOINTUPLE(S, cC)
#define JOINN(_1, _2, _3, N, ...) JOIN##N
#define JOIN(S,...) _EXPAND(JOINN(__VA_ARGS__,3,2,1)(S,__VA_ARGS__))

, который включает следующий синтаксис:

JOIN(:, (a, A)) // Expands to "a : A"
JOIN(., (a, A), (b, B)) // Expands to "a . A, b . B"

Ответ на , почему необходимо манипулировать синтаксисом с этим EXPAND, если это зависит от компилятора /Портативный и погода это хорошая / плохая практика будет приветствоваться.

...