是否可以在 Fortran 中创建一个可调用的 class 实例?

Is it possible to make a class instance callable in Fortran?

我有一个多项式 class TPoly,请参阅下面的代码,它采用系数数组 coefs 并在某个点 x 使用eval 方法。我想知道是否可以通过使实例 p 可调用来直接评估多项式,即使用 p(x) 而不是 p%eval(x)。在 Python 中,可以通过定义 __call__ 方法来实现所需的行为。 Fortran 中是否存在类似的东西?

我想制作另一个 class,它将包含许多 TPoly 属性,并且我想避免组件选择的链接 object%poly1%eval(x)。指向 class 方法的函数指针可以解决我的问题,但我发现这是不可能的,请参阅 .

module polymod

    implicit none

    integer, parameter :: rp = kind(1.0d0)

    ! polynomial class
    type :: TPoly
        real(rp), allocatable :: coefs(:)
        contains 
        procedure, pass :: eval => eval_poly
    end type

    contains 

    real(rp) function eval_poly(self, x)
        class(TPoly), intent(in) :: self
        real(rp), intent(in) :: x

        eval_poly = polynomial(x, self%coefs)

    end function eval_poly

    ! use Horner's method to evaluate polynomial
    real(rp) function polynomial(x, coefs)
        real(rp), intent(in) :: x, coefs(:)
        real(rp) :: p
        integer :: n, i

        n = size(coefs)
        p = coefs(n)
        do i = n-1, 1, -1
            p = p * x + coefs(i)
        end do
        polynomial = p

    end function polynomial

 
end module polymod


program main
    
    use polymod
    implicit none

    type(TPoly) :: p
    real(rp) :: coefs(3)
    real(rp) :: x = 2.0_rp

    coefs = (/3.0_rp, -1.0_rp, 1.0_rp/)

    p = TPoly(coefs)

    print *, p%eval(x)
    ! I would like to use 
    ! print *, p(x)

end program main

很遗憾,不,这是不可能的。据我所知,也没有很好的解决方法可以模拟这种行为。

如果可能的话,需要避免与 Fortran 的数组访问语法冲突。考虑以下因素:

program main
  use polymod
  implicit none
  
  ! Declare an array of type TPoly.
  type(TPoly) :: p(1)
  
  ! Initialise the array.
  p = [TPoly(coefs=[3.0_rp, -1.0_rp, 1.0_rp])]
  
  ! Try to print.
  print *, p(1)
end program

编译器无法区分 p(1) 引用数组的第一个元素 pp(1) 调用 class 函数作为elemental 函数作用于 p 的每个元素,参数为 1.

您可以区分 non-elemental 函数的两者,但您需要一些像 p(1)(2.0_rp) 这样的语法,而这种语法在 Fortran 的上下文中并不存在。