我有一个子例程,它在中间包含一个简单的if语句,我想去掉它。原因是,我预先知道该语句是真是假,这是基于调用发生的位置,而不是基于输入数据。这甚至更有吸引力,因为它是1行代码,如果它真的不做太多事情的话。
现在有一个额外的逻辑输入,它只用于if语句,它被调用了两次-一次使用"false“,一次使用"true”。
本质上,我想让if语句在编译期间工作,但#ifdef不允许同一个子例程有两种不同的用法/配置。
愚蠢的解决方案是完全复制子例程,并使一个实例具有"true“段,而另一个实例仅具有"false”段。
然而,除此之外,这远远不是优雅的(并且有99.9%的相似性),这是一个打开的麻烦,一旦子例程在未来被改变。
我要指出的是,我的意思不是重载子例程(至少不是在“传统”意义上),尽管这是一种相同的一般概念。
所以我的问题是-有没有解决这种情况的方案,或者我将不得不把它作为一个运行时的if语句,并有一个额外的逻辑true/false输入?
我用的是Fortran 90/95。
发布于 2018-05-30 07:52:31
所以我的理解是代码应该是这样的:
module mymod
implicit none
contains
subroutine mysub(a, l)
integer, intent(inout) :: a
logical, intent(in) :: l
a = mod(a**3, 53)
if (l) then
a = a + 1
else
a = a - 1
end if
end subroutine mysub
end module mymod
program myprog
use mymod
implicit none
integer :: b
b = 10
call mysub(b, .TRUE.)
print *, b
call mysub(b, .FALSE.)
print *, b
end program myprog
您还会担心mysub
子例程的效率并不高,因为它有一条if语句,即使编译器在编译时知道它每次都会采用哪条路径。
在进一步研究这一点之前,我强烈建议您评估一下是否有必要这样做。您所能做的一切都会降低代码的可读性和可维护性,并且可能最多只能带来轻微的性能提升。
您可以编写两个不同的子例程,并在单独的文件中包含相同的部分,然后将其INCLUDE
到两个子例程中,如下所示:
same.inc:
integer, intent(inout) :: n
n = mod(n**3, 53)
sub.f90:
module mymod
implicit none
contains
subroutine mysub_true(n)
include 'same.inc'
n = n + 1
end subroutine mysub_true
subroutine mysub_false(n)
include 'same.inc'
n = n - 1
end subroutine mysub_false
end module mymod
与预处理器一起,您甚至可以全力以赴:
mysub.inc:
#if PATH == 1
#define SUB_NAME mysub_true
#else
#define SUB_NAME mysub_false
#endif
subroutine SUB_NAME(n)
integer, intent(inout) :: n
n = mod(n**3, 53)
#if PATH == 1
n = n + 1
#else
n = n - 1
#endif
end subroutine SUB_NAME
#undef SUB_NAME
#undef PATH
mymod.F90:
module mymod
implicit none
contains
#define PATH 1
#include mysub.inc
#define PATH 0
#include mysub.inc
end module mymod
myprog.F90:
program myprog
use mymod
implicit none
integer :: b
b = 10
call mysub_true(b)
print *, b
call mysub_false(b)
print *, b
end program myprog
并使用
gfortran -c -o mymod.o -cpp mymod.F90
gfortran -o myprog myprog.F90 mymod.o
这是否使其更容易阅读或更难阅读取决于相同部分的复杂程度。
https://stackoverflow.com/questions/50594188
复制相似问题