【发布时间】:2018-06-08 17:16:40
【问题描述】:
我想编写一个重载swap 例程的模块,该例程接受一个数组和两个索引并交换两个元素。
这个例程应该适用于广泛的数组,所以我想重载它:
module mod_swap
use iso_fortran_env
implicit none
interface swap
module procedure swap_int64, swap_int32, swap_int16, &
swap_real64, swap_real32
end interface swap
public :: swap
private :: swap_int64, swap_int32, swap_int16, &
swap_real64, swap_real32
contains
#define VAR_TYPE real
#define TYPE_KIND real64
#include "swap.inc"
#undef TYPE_KIND
#define TYPE_KIND real32
#include "swap.inc"
#undef TYPE_KIND
#undef VAR_TYPE
#define VAR_TYPE integer
#define TYPE_KIND int64
#include "swap.inc"
#undef TYPE_KIND
#define TYPE_KIND int32
#include "swap.inc"
#undef TYPE_KIND
#define TYPE_KIND int16
#include "swap.inc"
#undef TYPE_KIND
#undef VAR_TYPE
end module mod_swap
swap.inc 是:
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SWAP EVALUATOR(swap, TYPE_KIND)
subroutine SWAP(a, i, j)
implicit none
VAR_TYPE(kind=TYPE_KIND), intent(inout) :: a(:)
integer, intent(in) :: i, j
VAR_TYPE(kind=TYPE_KIND) t
t = a(i)
a(i) = a(j)
a(j) = t
end subroutine SWAP
当我运行 gfortran -o test.o -c -cpp test.F90 时它失败了,当我运行 gfortran -E -cpp test.F90 时我发现了原因:SWAP 宏已扩展为 swap ## _ ## int16,而不是预期的 swap_int16。
但是,cpp 直接起作用:
$ cpp test.F90 > test.f90
$ gfortran -c -o test.o test.f90
在浏览了这个论坛和谷歌之后,我推断问题是这样的:
预处理器以传统模式运行。
事实上,cpp --traditional 表现出与gfortran -E -cpp 相同的行为
所以这是我的问题:
有没有更好的方法来实现这个例程,这样我就不必因为数组类型发生变化而重复相同的指令。 (注意变量
t需要和a有相同的类型)。有没有办法让
gfortran使用非传统的预处理器?如果不是,我将如何使用传统预处理器做我想做的事情?
【问题讨论】:
-
对 (2) 的回答是“否”。 (3)的答案是直接使用 cpp 如您所演示的。使用 (3) 为可能的奇怪结果做好准备,因为现代 C 预处理器语法和 Fortran 语法存在冲突。 (1) 的答案可能在于 Fortran 的子模块功能。
-
cpp 在非传统模式下会将
//视为注释分隔符。 gfortran 使用传统模式,因为必须不破坏 Fortran 代码。
标签: fortran gfortran preprocessor