Объединение расширенного макроса и слова с помощью препроцессора Fortran

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

Согласно его документации, препроцессор 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

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

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

Я не слишком знаком с препроцессором 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 в той же строке. Подозреваю, что это особенность "традиционного" препроцессора Си...


person Robert Rüger    schedule 20.12.2016    source источник
comment
Я думаю, что ответ заключается в определении функции CONCAT, которая зависит от компилятора. Это можно использовать для всех расширений. Подробнее см. этот ответ.   -  person d_1999    schedule 20.12.2016
comment
Спасибо за предложение. Я уже пробовал что-то подобное (см. РЕДАКТИРОВАТЬ вопрос). Не получилось, к сожалению...   -  person Robert Rüger    schedule 20.12.2016
comment
Странно, x/**/y производит fooEXPANSION, но `x/**/y` производит foo bar. Я рекомендую сформулировать вопрос так, чтобы он привлек внимание экспертов по препроцессорам C, и они не пропустили его, потому что они подумали бы, что он специфичен для Fortran (а это не так).   -  person Vladimir F    schedule 20.12.2016
comment
Думаю, я понимаю это. Расширение CAT происходит первым, производя fooEXPANSION. В этом случае слово EXPANSION не будет расширено, так как оно не разделено пробелом. Если вы поместите дополнительный пробел перед y, расширение CAT даст foo EXPANSION, которое будет расширено до foo bar.   -  person Robert Rüger    schedule 21.12.2016


Ответы (1)


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

Благодаря записи на 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

Другое решение (в котором все еще используется прием /**/) было опубликовано Джонатаном Леффлером в этот ответ на связанный вопрос.

person Robert Rüger    schedule 26.12.2016
comment
Так что это похоже на трюк со строкой, который я первоначально предложил... - person Vladimir F; 27.12.2016