Class Fortran中的模板?

Class Fortran中的模板?,class,templates,fortran,Class,Templates,Fortran,我有一个模块,它定义了三种类型和一些操作 在一个单独的模块中,我想定义一个算法,使用模块中定义的操作对这些类型中的任何一种进行操作。无论类型如何,算法都是相同的。我可以重载它,但我想知道通过定义某种模板算法是否可以节省大量的输入。我的想法是C++中的类模板。 感谢Fortran没有模板,但是您可以将处理不同类型函数的通用代码放在一个包含文件中,作为一个混合代码来模拟模板,如下代码所示: ! file "cumul.inc" ! function cumul(xx) result(yy) ! re

我有一个模块,它定义了三种类型和一些操作

在一个单独的模块中,我想定义一个算法,使用模块中定义的操作对这些类型中的任何一种进行操作。无论类型如何,算法都是相同的。我可以重载它,但我想知道通过定义某种模板算法是否可以节省大量的输入。我的想法是C++中的类模板。
感谢Fortran没有模板,但是您可以将处理不同类型函数的通用代码放在一个包含文件中,作为一个混合代码来模拟模板,如下代码所示:

! file "cumul.inc"
! function cumul(xx) result(yy)
! return in yy(:) the cumulative sum of xx(:)
! type, intent(in) :: xx(:)
! type             :: yy(size(xx))
integer :: i,n
yy = 0
n  = size(xx)
if (n < 1) return
yy(1) = xx(1)
do i=2,n
   yy(i) = yy(i-1) + xx(i)
end do
return
! end function cumul
! end file "cumul.inc"

module foo
implicit none
integer, parameter :: sp = kind(1.0), dp = kind(1.0d0)
interface cumul
   module procedure cumul_double,cumul_real,cumul_int
end interface cumul
contains
!
function cumul_double(xx) result(yy)
real(kind=dp), intent(in) :: xx(:)
real(kind=dp)             :: yy(size(xx))
include "cumul.inc"
end function cumul_double
!
function cumul_real(xx) result(yy)
real(kind=sp), intent(in) :: xx(:)
real(kind=sp)             :: yy(size(xx))
include "cumul.inc"
end function cumul_real
!
function cumul_int(xx) result(yy)
integer, intent(in) :: xx(:)
integer             :: yy(size(xx))
include "cumul.inc"
end function cumul_int
end module foo

program xcumul
use foo, only: cumul
print*,cumul([10,20,30])
print*,cumul(sin([10.0,20.0,30.0]))
print*,cumul(sin([10.0d0,20.0d0,30.0d0]))
end program xcumul
! output:
! 10 30 60
! -0.5440211 0.36892414 -0.6191075
! -0.5440211108893698 0.3689241398382579 -0.6191074842546039
!文件“cumul.inc”
! 函数累计(xx)结果(yy)
! 在yy(:)中返回xx(:)的累计和
! 类型、意图(in)::xx(:)
! 类型::yy(尺寸(xx))
整数::i,n
yy=0
n=尺寸(xx)
如果(n<1)返回
yy(1)=xx(1)
i=2,n吗
yy(i)=yy(i-1)+xx(i)
结束
返回
! 端函数累积
! 结束文件“cumul.inc”
模块foo
隐式无
整数,参数::sp=kind(1.0),dp=kind(1.0d0)
接口积云
模块程序cumul\u double、cumul\u real、cumul\u int
端接口
包含
!
函数累计双(xx)结果(yy)
真实(种类=dp),意图(单位):xx(:)
实际(种类=dp)::yy(尺寸(xx))
包括“cumul.inc”
端函数cumul_双
!
函数累积实(xx)结果(yy)
真实(种类=sp),意图(单位):xx(:)
实物(种类=sp)::yy(尺寸(xx))
包括“cumul.inc”
端函数cumul_实
!
函数累计整(xx)结果(yy)
整数,意图(in)::xx(:)
整数::yy(大小(xx))
包括“cumul.inc”
端函数cumul_int
端模块foo
程序xcumul
使用foo,仅限:cumul
打印*,千分位数([10,20,30])
打印*,单位(sin([10.0,20.0,30.0]))
打印*,单位体积(sin([10.0d0,20.0d0,30.0d0]))
结束程序xcumul
! 输出:
! 10 30 60
! -0.5440211 0.36892414 -0.6191075
! -0.5440211108893698 0.3689241398382579 -0.6191074842546039
论文中提到的工具

汽车,大卫和迈克尔名单(2010年)。PyF95++:Fortran 95/2003语言的模板功能。ACM Fortran论坛29(1),2-20


你可能会感兴趣。我没有尝试过。

我的答案与@Fortranner的答案类似,但我通常将整个实现放在include文件中。 它的优点是,一个包含文件可以处理多个过程,并且更易于维护,例如。 你可以看到整个过程的定义,等等

需要一些预处理器伏都教(请参见粘贴、CONCATHELP等),但它可以工作。 @Fortranner给出的相同示例可以写成如下

主文件
main.f90

program main
  use cumul_m, only: cumul
  implicit none

  print *, cumul([1,     2,     3    ])     ! output: 1   3   6
  print *, cumul([1.1,   2.2,   3.3  ])     ! output: 1.1 3.3 6.6
  print *, cumul([1.1d0, 2.2d0, 3.3d0])     ! output: 1.1 3.3 6.6
end program
module cumul_m
  use iso_fortran_env, only: real32, real64
  implicit none

  private
  public cumul

  interface cumul
    module procedure :: cumul_int, cumul_sp, cumul_dp
  end interface

contains

#define T int
#define TT integer
#include "cumul_imp.f90.inc"

#define T sp
#define TT real(real32)
#include "cumul_imp.f90.inc"

#define T dp
#define TT real(real64)
#include "cumul_imp.f90.inc"

end module
模块文件
cumul.f90

program main
  use cumul_m, only: cumul
  implicit none

  print *, cumul([1,     2,     3    ])     ! output: 1   3   6
  print *, cumul([1.1,   2.2,   3.3  ])     ! output: 1.1 3.3 6.6
  print *, cumul([1.1d0, 2.2d0, 3.3d0])     ! output: 1.1 3.3 6.6
end program
module cumul_m
  use iso_fortran_env, only: real32, real64
  implicit none

  private
  public cumul

  interface cumul
    module procedure :: cumul_int, cumul_sp, cumul_dp
  end interface

contains

#define T int
#define TT integer
#include "cumul_imp.f90.inc"

#define T sp
#define TT real(real32)
#include "cumul_imp.f90.inc"

#define T dp
#define TT real(real64)
#include "cumul_imp.f90.inc"

end module
实现的include文件
cumul_imp.f90.inc

#define PASTE(X)         X
#define PASTE2(X)        PASTE(X)_
#define CONCATHELP(X, Y) PASTE2(X)Y
#define CONCAT(X, Y)     CONCATHELP(X,Y)

#define CUMUL            CONCAT(cumul,T)

function CUMUL(x) result(y)
  !! the cumulative sum of x

  TT, intent(in) :: x(:)
    !! array of values
  TT             :: y(size(x))
    !! cumulative sum of x

  integer :: i, n

  n = size(x)
  if (n < 1) return

  y(1) = x(1)
  do i = 2, n
    y(i) = y(i-1) + x(i)
  end do
end function

#undef T
#undef TT

#undef PASTE
#undef PASTE2
#undef CONCATHELP
#undef CONCAT

#undef CUMUL
新兴项目使用@BálintAradi的预处理器进行模板化

例如,您可以定义应为其生成子程序的类型和种类,并在
For
循环中循环所有这些选定的类型和种类:

#:set REAL_KINDS = ["sp", "dp", "qp"]
#:set REAL_TYPES = ["real({})".format(k) for k in REAL_KINDS]

...

#:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES

#:for k1, t1 in RCI_KINDS_TYPES
      module procedure trace_${t1[0]}$${k1}$
#:endfor

为方便起见,参考文献如下。