Понимание макросов DEFER и OBSTRUCT

Я создалнебольшая библиотека макропрограммирования макросов который реализует основные полезные конструкции, такие какREPEAT(times, x), IF(value, true, false), кортежи и многое другое.

Большинство моих реализаций работаютперегрузка макросы, основанные на числе переменных аргументов или счетчике:

// Example:
#define REPEAT_0(x) 
#define REPEAT_1(x) x REPEAT_0(x) 
#define REPEAT_2(x) x REPEAT_1(x)
#define REPEAT_3(x) x REPEAT_2(x)
// ...
// (these defines are generated using an external script)
// ...

#define REPEAT(count, x) CAT(REPEAT_, count)(x)

Это отлично работает, но я недавно сталкивалсячрезвычайно интересная реализация макрорекурсии Пола Фульца.

Доотложенное выражение В разделе у меня не было проблем с пониманием его статьи.

У меня, однако, много проблем с пониманием использованияDEFER а такжеOBSTRUCT должным образом.

Пол реализует очень элегантную версиюREPEAT это не требует сгенерированных скриптом определений как это:

#define EAT(...)
#define EXPAND(...) __VA_ARGS__
#define WHEN(c) IF(c)(EXPAND, EAT)

#define REPEAT(count, macro, ...) \
    WHEN(count) \
    ( \
        OBSTRUCT(REPEAT_INDIRECT) () \
        ( \
            DEC(count), macro, __VA_ARGS__ \
        ) \
        OBSTRUCT(macro) \
        ( \
            DEC(count), __VA_ARGS__ \
        ) \
    )
#define REPEAT_INDIRECT() REPEAT

//An example of using this macro
#define M(i, _) i
EVAL(REPEAT(8, M, ~)) // 0 1 2 3 4 5 6 7

DEFER, OBSTRUCT и другие утилиты реализованы так:

#define EMPTY()
#define DEFER(id) id EMPTY()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()
#define EXPAND(...) __VA_ARGS__

#define A() 123
A() // Expands to 123
DEFER(A)() // Expands to A () because it requires one more scan to fully expand
EXPAND(DEFER(A)()) // Expands to 123, because the EXPAND macro forces another scan

Когда препроцессор раскрывает макрос, результат «раскрашивается» до следующего сканирования - он не будет рекурсивно раскрываться, пока не произойдет дополнительное сканирование.Это правильно?

ЛиEXPAND(...) макросзаставить дополнительное сканирование? Если да, позволяет ли это сканирование рекурсивно расширять макросы?Какая разница междуEXPAND(...) а такжеDEFER(id)?

Есть лиDEFER заставить два дополнительных сканирования?

Что насчетOBSTRUCT(...) макрос? Это силадва дополнительных сканирования?

Сейчас - почемуOBSTRUCT требуется в рекурсивной реализацииREPEAT? Почему бы неDEFER или жеEXPAND работать здесь?

Ответы на вопрос(1)

Ваш ответ на вопрос