Расширение макроса препроцессора в другую директиву препроцессора - PullRequest
8 голосов
/ 11 августа 2009

Сначала я думал, что мне это нужно, но в конце концов я этого избегал. Однако, мое любопытство (и аппетит к знаниям, гул) заставляет меня спрашивать:

Может ли макрос препроцессора, например, в

#include "MyClass.h"

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)

расширить до другого включения, как в

#include "MyClass.h"

#include "FooTemplate.h"
template class FooTemplate<MyClass>;

?

Ответы [ 3 ]

13 голосов
/ 11 августа 2009

Я считаю, что это невозможно сделать, потому что препроцессор однопроходный Поэтому он не может выдавать другие директивы препроцессора.

В частности, из стандарта C99 (пункт 6 6.3.3.4):

3 Полученный полностью макропеременный токен предварительной обработки последовательность не обрабатывается как директива предварительной обработки, даже если она напоминает одну, ...

Интересно, что именно поэтому унарный оператор _Pragma был добавлен в c99. Потому что #pragma не может генерироваться макросами, а _Pragma может.

9 голосов
/ 11 августа 2009

Стандарт C говорит это о директивах предварительной обработки (C99 - 6.10 (2) - Директивы предварительной обработки):

Директива предварительной обработки состоит из последовательности токенов предварительной обработки, которая начинается с токен предварительной обработки #, который (в начале фазы перевода 4) ...

и (C99 - 6,10 (7)):

Токены предварительной обработки в директиве предварительной обработки не подлежат макросу расширение, если не указано иное.

ПРИМЕР В:

#define EMPTY
EMPTY # include <file.h>

последовательность токенов предварительной обработки во второй строке не является директивой предварительной обработки, поскольку она не начинается с символа # в начале фазы 4 трансляции, даже если она произойдет после замены макроса EMPTY

Итак, нет, макросы не могут расширяться в директиву предварительной обработки '#include'. Эти директивы должны быть в начале фазы перевода 4 (когда обработка этих директив имеет место, происходит предварительная обработка). Поскольку расширение макроса происходит во время фазы 4, макросы не могут заставить что-либо существовать в начале фазы 4.

Хотелось бы отметить, что следующее работает :

#ifdef WIN32
#define PLATFORM_HEADER "platform/windows/platform.h"
#else
#define PLATFORM_HEADER "platform/linux/platform.h"

#include PLATFORM_HEADER

, потому что стандарт C говорит это (C99, 6.10.2 (4) - Включение исходного файла):

Директива предварительной обработки вида

# include pp-tokens new-line

(что не соответствует одной из двух предыдущих форм) разрешено. Предварительная обработка токены после include в директиве обрабатываются так же, как и в обычном тексте. (Каждый идентификатор, определенный в качестве имени макроса, заменяется его списком замен токены предварительной обработки.)

1 голос
/ 12 августа 2009

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

...