2016-12-20 2 views
1

Я пытаюсь объединить слово в исходном коде с расширением макроса препроцессора. В основном у меня есть foo где-то в коде, а с #define EXPANSION bar хочу получить foobar. Тем не менее, я изо всех сил пытаюсь найти способ сделать это, который работает со всеми компиляторами. На данный момент я был бы счастлив, если бы он работал с gfortran и ifort.Конкатенация расширенного макроса и слова с использованием препроцессора Fortran

В соответствии с его documentation препроцессор gfortran является препроцессором C, работающим в «традиционном режиме», который не имеет оператора точечной пасты ##. Тем не менее, тот же эффект может быть получен с пустым комментарием /**/ C-стиля. Препроцессор ifort, похоже, больше похож на обычный препроцессор C, поэтому обычное вставку токенов делает трюк в ifort. К сожалению, пустой комментарий /**/ не работает в ifort, так как комментарий заменяется на одно место.

Вот маленький пример:

#define EXPANSION bar 
#define CAT(x,y) PASTE(x,y) 
#define PASTE(x,y) x ## y 

foo/**/EXPANSION 
CAT(foo,EXPANSION) 

Для которых gfortran производит:

foobar 
foo ## bar 

Хотя ifort дает мне:

foo bar 
foobar 

Конечно, я мог бы выбрать правильный путь, проверка предопределенных макросов для обоих компиляторов:

#ifdef __GFORTRAN__ 
foo/**/EXPANSION 
#else 
CAT(foo,EXPANSION) 
#endif 

Это работает для обоих из них, но довольно уродливо, чтобы препроцессор был условным для каждого расширения. Я бы предпочел избежать этого и немного макрома магии только один раз в начале.

Я видел this answer на другой вопрос, который, вероятно, позволит мне обойти эту проблему, но я бы предпочел найти решение, которое не будет запрашивать препроцессор отдельно.

Я не слишком хорошо знаком с препроцессором C. Возможно, есть простой способ сделать то, что я хочу. Есть идеи?

EDIT: Я уже пытался что-то вроде этого:

#define EXPANSION bar 
#define CAT(x,y) PASTE(x,y) 
#ifdef __GFORTRAN__ 
#define PASTE(x,y) x/**/y 
#else 
#define PASTE(x,y) x ## y 
#endif 

CAT(foo,EXPANSION) 

К сожалению, это не работает в gfortran, где она производит fooEXPANSION. Я не совсем уверен, как это работает, но, по-видимому, расширение макроса CAT предотвращает расширение EXPANSION в той же строке. Я подозреваю, что это особенность «традиционного» препроцессора C ...

+1

Я думаю, что ответ заключается в определении функции 'CONCAT', которая зависит от компилятора. Это можно использовать для всех расширений. См. [Этот ответ] (http://stackoverflow.com/a/39692172/6382074) для получения более подробной информации –

+0

Спасибо за предложение. Я уже пробовал что-то вроде этого (см. EDIT вопроса). Не удалось заставить его работать, к сожалению ... –

+1

Странный, 'x/**/y' производит' fooEXPANSION', но 'x/**/y' производит' foo bar'. Я рекомендую сформулировать вопрос так, чтобы он привлекал экспертов препроцессора C, и они не пропускают его, потому что они будут думать, что это Fortran специфический (чего это не так). –

ответ

1

Я провел некоторое исследование, и кажется, что большинство компиляторов Fortran (т.е. Intel и PGI) используют относительно обычный C-препроцессор с токеном вставка оператора. Нам нужна только специальная обработка gfortran, которая использует препроцессор C в традиционном режиме без оператора маркера.

Благодаря entry on c-faq.com я нашел это определение CAT макрос, который работает со всеми компиляторами я тестировал до сих пор:

#ifdef __GFORTRAN__ 
#define PASTE(a) a 
#define CAT(a,b) PASTE(a)b 
#else 
#define PASTE(a) a ## b 
#define CAT(a,b) PASTE(a,b) 
#endif 

Другое решение (что до сих пор использует /**/ трюк) была опубликована Jonathan Leffler в this answer к связанный с этим вопрос.

+0

Так что это похоже на трюк, который я изначально предложил ... –

Смежные вопросы