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