Я пишу основанную на x-macro систему описания структуры файла реестра для моего проекта. В большинстве случаев макросы расширяются до иерархии шаблонных классов. Однако я также хочу перечисление всех регистров, например:
#define RINT(num,name,flags,width) name,
...
enum Regs
{
#include REGDEF
};
Это работает просто отлично. Однако я также указываю регистры псевдонимов, используя макрос с переменным числом аргументов. Поскольку не существует тривиального способа удаления запятых между элементами __VA_ARGS__ (не то, о чем я знаю, пожалуйста, исправьте меня, если я ошибаюсь), я пишу:
#define RALIAS_10(r0,r1,r2,r3,r4,r5,r6,r7,r8,r9) r0 r1 r2 r3 r4 r5 r6 r7 r8 r9
#define RALIAS_9(r0,r1,r2,r3,r4,r5,r6,r7,r8) r0 r1 r2 r3 r4 r5 r6 r7 r8
...
#define RALIAS_1(r0) r0
#define RALIAS_N(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,aliasn,...) aliasn
#define RALIAS(...) RALIAS_N(__VA_ARGS__, RALIAS_10(__VA_ARGS__), RALIAS_9(__VA_ARGS__), ..., RALIAS_1(__VA_ARGS__))
Теперь, если я напишу
RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))
запятые в макросе RINT исчезают:
enum Reg
{
...
RSP ESP SP SPL
...
};
Если, в свою очередь, я использую макрос RALIAS_4 напрямую
RALIAS_4(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))
Я получаю то, что ожидаю:
enum Reg
{
...
RSP, ESP, SP, SPL,
...
};
Я знаю, что GCC применяет некоторую нестандартную логику для удаления запятых к вариационным макросам, но этого не должно происходить, когда я явно указываю -std = c ++ 11. Кроме того, Clang дал мне точно такие же результаты. Однако я не смог найти ничего, что могло бы объяснить это поведение в стандарте (черновике) или в документации GCC.
Что мне не хватает?
Я попробовал GCC 6.1.1 и Clang 3.8.1 на Arch Linux (x86-64). Оба компилятора были установлены из репозитория.
Это:
RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))
собирается расширить в:
RALIAS(RSP,,ESP,,SP,,SPL,)
который является макросом, который принимает 8 аргументов, из которых 4 являются пустыми. Вы не получите аргумент "RSP,"
вы получите аргумент RSP
а потом отдельно аргумент ""
,
Других решений пока нет …