使用 Fortran 预处理器连接扩展宏和单词 [英] Concatenating an expanded macro and a word using the Fortran preprocessor
问题描述
我正在尝试将源代码中的单词与预处理器宏的扩展连接起来.基本上我在代码中的某处有 foo
,并且我想通过 #define EXPANSION bar
获得 foobar
.但是,我正在努力寻找一种适用于所有编译器的方法.目前,如果它可以与 gfortran 和 ifort 一起使用,我会很高兴.
I'm trying to concatenate a word in the source code with the expansion of a preprocessor macro. Basically I have foo
somewhere in the code, and with a #define EXPANSION bar
I want to obtain foobar
. However, I'm struggling to find a way to do this, which works with all compilers. For the moment I would be happy if it works with gfortran and ifort.
根据其 文档,gfortran预处理器是在传统模式"下运行的 C 预处理器,它没有 ##
标记粘贴操作符.但是,使用空的 C 样式 /**/
注释可以获得相同的效果.ifort 预处理器的行为似乎更像普通的 C 预处理器,所以普通的标记粘贴在 ifort 中可以解决问题.不幸的是,空的 /**/
注释在 ifort 中不起作用,因为注释被替换为一个空格.
According to its documentation, the gfortran preprocessor is a C preprocessor running in "traditional mode", which does not have the ##
token paste operator. However, the same effect can be obtained with an empty C-style /**/
comment. The ifort preprocessor seems to behave more like the normal C preprocessor, so normal token pasting does the trick in ifort. Unfortunately the empty /**/
comment does not work in ifort, as the comment is replaced by a single space instead.
这是一个小例子:
#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#define PASTE(x,y) x ## y
foo/**/EXPANSION
CAT(foo,EXPANSION)
gfortran 生成:
For which gfortran produces:
foobar
foo ## bar
虽然 ifort 给了我:
While ifort gives me:
foo bar
foobar
当然,我可以通过检查两个编译器的预定义宏来选择正确的方法:
Of course I could choose the right way by checking the predefined macros for both compilers:
#ifdef __GFORTRAN__
foo/**/EXPANSION
#else
CAT(foo,EXPANSION)
#endif
这对他们俩都有效,但是让预处理器为每个扩展设置条件是相当丑陋的.我宁愿避免这种情况,并且在开始时只使用一次宏魔法.
This works for both of them, but it's rather ugly to have the preprocessor conditional for every expansion. I would much rather avoid this and have some macro magic only once in the beginning.
我已经看到 this answer 对另一个问题,这可能会让我解决这个问题,但我会而是找到一个不单独调用预处理器的解决方案.
I have seen this answer to another question, which would probably allow me to work around this issue, but I would rather find a solution that does not invoke the preprocessor separately.
我对 C 预处理器不太熟悉.也许有一种简单的方法可以做我想做的事.有什么想法吗?
I'm not too familiar with the C preprocessor. Maybe there is a simple way to do what I want. Any ideas?
我已经尝试过这样的事情:
I've already tried something like this:
#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)
不幸的是,这在生成 fooEXPANSION
的 gfortran 中不起作用.我不完全确定这是如何工作的,但显然 CAT
宏的扩展阻止了 EXPANSION
在同一行中的扩展.我怀疑这是传统"C 预处理器的一个特性......
Unfortunately this does not work in gfortran where it produces fooEXPANSION
. I'm not entirely sure how this works, but apparently the expansion of the CAT
macro prevents the expansion of EXPANSION
in the same line. I suspect that this is a feature of the "traditional" C preprocessor ...
推荐答案
我做了一些研究,似乎基本上大多数 Fortran 编译器(即 Intel 和 PGI)都使用带有标记粘贴运算符的相对普通的 C 预处理器.我们只需要对 gfortran 进行特殊处理,它在传统模式下使用 C 预处理器,没有标记粘贴操作符.
I have done some research and it seems that basically most Fortran compilers (i.e. Intel and PGI) use a relatively normal C-preprocessor with a token pasting operator. We only need a special treatment for gfortran, which uses a C preprocessor in traditional mode without a token pasting operator.
感谢 c-faq.com 上的条目,我找到了以下定义一个 CAT
宏,适用于我目前测试过的所有编译器:
Thanks to an entry on c-faq.com I found this definition of a CAT
macro that works with all compilers I tested so far:
#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 中对相关问题.
Another solution (that still uses the /**/
trick) was posted by Jonathan Leffler in this answer to a related question.
这篇关于使用 Fortran 预处理器连接扩展宏和单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!