«Проблема» в том, что макросы лениво оцениваются. Рассмотрим определение вашего макроса:
#define PREPROCESSOR_LOOP_ITERATION (PREPROCESSOR_LOOP_ITERATION + 1)
Это определяет макрос с именем PREPROCESSOR_LOOP_ITERATION
, а его список замен представляет собой последовательность из пяти токенов предварительной обработки (
, PREPROCESSOR_LOOP_ITERATION
, +
, 1
и )
. Макрос не раскрывается в списке замены, когда макрос определен. Замена макроса происходит только при вызове макроса. Рассмотрим более простой пример:
#define A X
#define B A
B // this expands to the token X
#undef A
#define A Y
B // this expands to the token Y
Существует дополнительное правило, согласно которому если имя заменяемого макроса встречается в списке замены, оно не обрабатывается как макрос и, следовательно, не заменяется (это эффективно запрещает рекурсию во время замены макроса). Так что, в вашем случае, каждый раз, когда вы вызываете макрос PREPROCESSOR_LOOP_ITERATION
, он заменяется на
( PREPROCESSOR_LOOP_ITERATION + 1 )
затем замена макроса останавливается, и предварительная обработка продолжается со следующим токеном.
Вы можете выполнять ограниченную арифметику с препроцессором, определяя последовательность макросов и используя оператор конкатенации (##
), но это довольно утомительно. Вам следует подумать об использовании библиотеки Boost.Preprocessor , чтобы помочь вам в этом. Он будет работать как с C, так и с C ++ кодом. Он допускает ограниченную итерацию, но то, что он допускает, чрезвычайно полезен. Ближайшая функция, которая соответствует вашему варианту использования, вероятно, BOOST_PP_ITERATE
. Другие средства, такие как обработчики последовательности (BOOST_PP_SEQ
), очень полезны для написания генерирующего кода.