Расширение макроса препроцессора до другой директивы препроцессора
-
12-09-2019 - |
Вопрос
Сначала я думал, что мне это нужно, но в конце концов избежал этого.Однако мое любопытство (и тяга к знаниям, хм) заставляют меня спросить:
Может ли макрос препроцессора, например, в
#include "MyClass.h"
INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)
разверните до другого включения, как в
#include "MyClass.h"
#include "FooTemplate.h"
template class FooTemplate<MyClass>;
?
Решение
Я считаю, что это невозможно сделать, это потому, что препроцессор одиночный проход.Таким образом, он не может выдавать другие директивы препроцессора.
В частности, из Стандарта C99 (пункт 3 6.10.3.4).:
3 Полученный полностью замененный макросом токен предварительной обработки последовательность не обрабатывается как директива предварительной обработки, даже если она похожа на нее, ...
Достаточно интересно, что именно поэтому унарный _Pragma
оператор был добавлен в c99.Потому что #pragma
не может быть выдан макросами, но _Pragma
могу.
Другие советы
Стандарт C говорит это о директивах предварительной обработки (C99 - 6.10 (2) - Директивы предварительной обработки):
Директива предварительной обработки состоит из последовательности токенов предварительной обработки, которая начинается с токена # предварительной обработки, который (в начале фазы перевода 4) ...
и (C99 - 6.10(7)):
Токены предварительной обработки в директиве предварительной обработки не подлежат расширению макрокомандой , если не указано иное.
ПРИМЕР В:
#define EMPTY EMPTY # include <file.h>
последовательность токенов предварительной обработки во второй строке не является директивой предварительной обработки, поскольку она не начинается с # в начале фазы перевода 4, даже если она будет делать это после замены ПУСТОГО макроса
Итак, нет, макросы не могут расширяться в '#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 и интерпретировать его как таковой.Вместо этого он будет интерпретирован как (ошибочный) код C++.