fortran - 传递一个可选的 Fortran 参数值,该参数将返回 false 给present()

标签 fortran optional-parameters

我想找到一种方法让 Fortran 方法为可选参数获取一些值,这将使参数看起来不存在于已调用的方法中。

这是一个简化的测试用例,它提取了 Fortran 代码中的问题:

MODULE FortranOptional
  USE ISO_C_BINDING

CONTAINS
  SUBROUTINE optionaltest(scalar)
    REAL(8), OPTIONAL, INTENT(IN) :: scalar

    IF (PRESENT(scalar)) THEN
      print *, "scalar is present: ", scalar
    ELSE
      print *, "scalar is NOT present"
    END IF

  END SUBROUTINE optionaltest

  SUBROUTINE optionaltest_c(scalarC) BIND(C, NAME="optionaltest_c")
    REAL(C_DOUBLE), OPTIONAL, INTENT(IN) :: scalarC
    REAL(8) :: scalar

    IF (PRESENT(scalarC)) THEN
      print *, "scalarC is present: ", scalarC
      scalar = scalarC
    ELSE
      print *, "scalarC is NOT present"
      ! Can I do something here to make scalar appear not present in optionaltest()?
    END IF

    CALL optionaltest(scalar)
  END SUBROUTINE optionaltest_c
END MODULE FortranOptional

以及相关的C++测试代码:

extern "C"
{
void optionaltest_c(double*);
}

void testMethod()
{
    double v = 5.3;
    optionaltest_c(0);

    std::cout << "\n";

    optionaltest_c(&v);
}

产生:

scalarC is NOT present
scalar is present:    6.9118029901527309E-310

scalarC is present:    5.2999999999999998     
scalar is present:    5.2999999999999998     

有什么方法可以根据 scalarC 的存在来设置 scalar 变量,使其在 scalarC 时看起来不存在> 不在场?

一些限制:

  • 我宁愿避免涉及对 optiontest 的不同调用的 if 语句,因为子例程的真实版本具有多个可选参数,这些参数可以单独指定,也可以不指定,从而导致在组合爆炸中。

  • 我无法将 optiontest 子例程直接绑定(bind)为 C 函数,因为该子例程的真实版本已采用形状可选参数,而这些参数在 Fortran I 版本中与 C 不兼容正在使用。

  • 我无法修改opticaltest的签名。

最佳答案

在子例程optionaltest_c中,变量scalar是一个本地变量。正如您所注意到的,局部变量没有可选性的概念。

为了完整起见,如果只是将可选虚拟参数从 optiontest_c 传递到 optiontest ,那么

call optionaltest(scalarC)

就足够了。也就是说,可选的虚拟参数可以是过程的实际参数,其中相应的虚拟参数也是可选的,无论其是否存在。

那么,如果您需要进行某种形式的操作,该怎么办?1我注意到您在虚拟参数和局部变量之间进行了内部赋值。

在 Fortran 2008 下有一个明智的选择:让局部变量可分配。如果变量未分配并且是可选的不可分配虚拟变量的实际参数,则将其视为不存在:

  subroutine optionaltest_c(scalarC) bind(C)
    type(type1), optional, intent(in) :: scalarC
    type(type2), allocatable :: scalar  ! Local, conformable with scalarC

    if (PRESENT(scalarC)) scalar=scalarC
    ...

    call optionaltest(scalar)
  end subroutine optionaltest_c

[您可能需要提供分配标量并设置其值的替代方法,具体取决于您的编译器支持。]

随着 scalarC 的存在,scalar 被分配并具有其值。然后在调用时,出现虚拟参数。如果 scalarC 不存在,则 scalar 未分配,并且在调用时虚拟参数不存在。

这对于数组和标量都同样有效。

现在,我看到您提到了 gfortran 4.4.7,因此这种方法可能行不通。在这种情况下,我会让其他人以特定的方式回答,但是为了其他人的利益/升级后,这也许仍然值得记录。


1 如果 c_double 的值为 8,则本问题的情况可能并非如此,但我们无论如何都会考虑。

关于fortran - 传递一个可选的 Fortran 参数值,该参数将返回 false 给present(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43351338/

相关文章:

php - 使用 mb_substr() 将字符串的其余部分获取到末尾并仍然设置编码

c# - 当接口(interface)方法没有参数时,为什么不能识别具有所有可选参数的方法的实现?

c - sscanf - 带有可选/空格式说明符的解析帧

swift 可选参数函数

fortran - 如何在保持兼容性的同时从 mpif.h 切换到 fortran 中的 mpi_f08?

fortran - 定义我自己的类型时 ifort 和 gfortran 的不同结果

fortran - Fortran 中的纯子例程 - 编译器优化

c# - 在c#中使用[可选]参数后如何知道它是否由调用方法给出?

compiler-errors - 在模块中找不到 (1) 中引用的非法预处理器指令和符号

file-io - 将数据按列写入文件(Fortran)