"present()" 内在函数是否在编译时求值

Is the "present()" intrinsic evaluated at compile time

在处理 fortran 中的 optional 参数时,我认为通常使用 present() 内部函数进行分支,即:

subroutine foo(ii,jj)
    implicit none
    integer, intent(in) :: ii
    integer, optional   :: jj

    if (present(jj)) then
! do something
    else
! do something else
    end if

end subroutine foo

我的假设(来自 C++ 世界)是 present() 希望是一个编译时构造,并且不会有任何相关的运行时性能损失。我希望编译器能够(应该被要求?)优化上面显示的 if 语句,这取决于调用的是 foo(ii) 还是 foo(ii,jj)

编译器在实践中如何处理 present() 内在函数? fortran 规范是否保证某些行为?

这取决于(您还期望什么?:-)

如果您使用最新版本的 gfortran,并在至少一个分支中做大量工作,并使用 LTO 或将所有内容放入一个文件中,编译器将为您克隆该函数(通过不断传播).否则,可能不会。如果你想知道过程 foo 是否已经被克隆,grep for foo.*constprop in the assembly file.

PRESENT 是一个运行时概念 - 在某种程度上,参数的存在可能取决于程序的某些方面,这些方面直到运行时才能确定(基于从文件或类似文件读取的输入)。

C++ 程序中 PRESENT 的等效实现同样是一个运行时概念。请注意,C++ 的默认参数功能与 Fortran 的可选参数功能的概念并不完全相同(尽管它可能是等效实现的一部分)。

除了编译器优化聪明之外,如果你想编译时解决类似于 C++ 的默认参数或函数重载的事情,那么考虑在通用名称后面使用多个特定过程,特定的一个变体带有 "optional"争论,另一个没有。

一个带有可选参数的子例程的替代方法是两个子例程,一个有参数,一个没有,共享相同的接口。我不认为这样做会花费 运行 时间,而不是给子例程的两个版本赋予不同的名称。从示意图上看,它看起来像这样:

interface foo
   module procedure foo_1,foo_2
end interface foo

contains

subroutine foo_1(ii)
! some code

subroutine foo_2(ii,jj)
! some code