2009-08-11 10 views
7

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

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

#include "MyClass.h" 

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass) 

расширить к другому относятся, например, в

#include "MyClass.h" 

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

?

+2

В один прекрасный день вы захотите перенести свой код на ОС, например, в Linux, где дело значимо (например, Foo.h и foo.h - это два разных файла), а затем все ошибки, которые не попадают в Windows, придут домой насест. альтернативно, если вы являетесь человеком Linux, вы однажды захотите пойти другим путем с разными, но одинаково ужасными проблемами. – 2009-08-11 18:29:14

+1

Я согласен с правилом всегда для нижнего регистра для имен файлов. Я написал это так, потому что я хотел исключить проблему преобразования нижнего регистра (имя класса -> имя файла). Но это стоит упомянуть, спасибо. +1! – moala

+0

Наше правило состоит в том, что имена файлов соответствуют схеме именования для наших типов и функций. Мы делаем точно так же, как и в этом вопросе, имя типа FooType будет определено в FooType.h. Как и в любом «стиле», выберите стиль и придерживайтесь его. Сказав, что мы сильно развиваемся в Linux, и поэтому это правило автоматически применяется для нас ОС ... hmmmmm ..... –

ответ

12

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

В частности, от C99 стандарта (6.10.3.4 пункт 3):

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

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

+0

Ну, это может, конечно, испустить директивы. то, что он не может сделать, это обрабатывать их в одном и том же препроцессорном проходе. – 2009-08-11 18:19:13

+1

Поскольку символы '#' и '##' имеют специальные значения в макросах, я не вижу, как вы могли бы испустить директиву ... –

+0

На самом деле препроцессор GCC, похоже, разрешает «#define X #ifdef X», где пространство между #ifdef и вторым X действительно является новой строкой, и на самом деле это испускает #ifdef при запуске cpp. Кто-то еще может это проверить, поскольку у меня только что было пару сортов пива :-) – 2009-08-11 18:37:30

9

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

директива предварительной обработки состоит из последовательности предобработки лексем, которая начинается с A # предобработки лексем, что (в начале фазы трансляции 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 

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

+0

Я посмотрел на эту часть стандарта, но я не думаю, что это самый важный раздел. Пример не тот, который пытается исправить директиву. Вместо этого это пример директивы, которой не предшествует «пробел» (хотя макрос EMPTY разрешает пробелы). –

+1

Я согласен с тем, что ваша цитата из стандарта более актуальна, но там, когда я ответил, не было.Даже если приведенный выше пример не совпадает с запросом о том, что бит о директиве предварительной обработки, который должен быть установлен в начале фазы 4, также запрещает макросы из объяснения в полезные директивы предварительной обработки, даже если 6.10.3.4 (3) говорит так более прямо. (другими словами, даже если я не думаю, что мой ответ неверен, ваш, безусловно, лучший ответ). –

+0

Достаточно честный, вы делаете хороший момент, +1 :-). –

1

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

+0

Вы можете получить это впечатление, потому что многие директивы отключают макроразложение своих аргументов, но это неверно. Расширение макросов происходит одновременно с директивным анализом. Если это правда, #if не будет работать, а #undef не будет иметь эффекта, которого ожидают люди. – zwol