使用Fortran预处理器连接扩展宏和单词

3
我正在尝试将源代码中的单词与预处理器宏的扩展连接起来。基本上,我在代码中有一个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)
会产生以下输出:
foobar
foo ## bar

当我使用ifort时,它会给我:

foo bar
foobar

当然,我可以通过检查两个编译器的预定义宏来选择正确的方式:

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

这适用于它们两个,但每次扩展都有预处理器条件相当丑陋。我更愿意避免这种情况,只需要一次在开始时进行一些宏魔法。

我看到另一个问题的这个答案,这可能允许我解决此问题,但我更希望找到不需要单独调用预处理器的解决方案。

我对C预处理器并不太熟悉。也许有一种简单的方法可以实现我的想法。有什么想法吗?

编辑:我已经尝试过类似以下的内容:

#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”函数。这可以用于所有扩展。有关详细信息,请参见此答案 - d_1999
谢谢您的建议。我已经尝试过类似的方法(请参见问题的编辑部分)。不幸的是,我无法使其工作... - Robert Rüger
1
奇怪的是,x/**/y 会产生 fooEXPANSION,但是 x/**/ y 会产生 foo bar。我建议将问题表述得更具吸引力,以吸引 C 预处理器专家,让他们不会因为认为这是 Fortran 特定的问题而跳过它(实际上并不是)。 - Vladimir F Героям слава
1
我认为我理解了这个。CAT的扩展首先发生,产生fooEXPANSION。然后单词EXPANSION不会进一步扩展,因为它没有被空格分隔开。如果在y之前加入额外的空格,CAT的扩展将产生foo EXPANSION,这将进一步扩展为foo bar - Robert Rüger
1个回答

2
我做了一些研究,似乎大多数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

另一个解决方案(仍使用`/**/`技巧)被Jonathan Leffler这个答案中发布,以回答一个相关的问题。

所以它类似于我最初建议的字符串化技巧... - Vladimir F Героям слава

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接