我有一个基类型,其中包含一个将用户定义的函数作为输入的过程。用户定义的函数在扩展类型中定义。以下使用ifort-13.1.3进行编译,但使用gfortran-4.8.1进行编译:
module m
implicit none
type, abstract :: base
contains
procedure :: use_f
end type base
type, extends(base) :: extended
contains
procedure :: f
procedure :: test ! calls use_f which takes f as argument
end type extended
contains
subroutine f(this)
class(extended) :: this
end subroutine f
subroutine use_f(this, func)
class(base) :: this
interface
subroutine func(this)
import :: base
class(base) :: this
end subroutine func
end interface
end subroutine use_f
subroutine test(this)
class(extended) :: this
call this%use_f(f) ! This is the important part!
end subroutine test
end module m
program a
end program a
gfortran生产
call this%use_f(f)
1
Error: Interface mismatch in dummy procedure 'func' at (1): Type/rank mismatch in argument 'this'
我也尝试过使用过程指针,但是当gfortran失败时仍然编译ifort。现在,如果不是接口块我放
external func
进入use_f代码使用ifort和gfortran成功编译。但是,EXTERNAL关键字不会变得过时吗?是否有更符合标准的方法有效?
答案 0 :(得分:6)
提出的程序有误。虽然从技术上讲,编译器不需要发出诊断,但我希望ifort应该,但在某些情况下这可能是合理的扩展。我建议向英特尔报告错误。
正如gfortran错误消息所暗示的那样,实际过程参数和虚拟过程参数的特征并不相同。当假人的界面是明确的时,它们必须与F2008的12.5.2.9p1相同,这里禁止一些例外情况。过程的特征包括其参数的特征。伪数据参数的特征包括其类型。
实际过程中伪参数的类型为extended
,虚拟过程中伪参数的类型为base
。
可能令人困惑的问题是,如果您实际上使用func
描述的接口调用过程,则将extended
类型的对象作为实际参数传递给该过程是有效的程序。但仅仅因为base
类型与extended
类型兼容,才会使类型相同。
当伪过程参数的接口是隐式的(比如因为您使用了EXTERNAL语句),则放宽了匹配特性的规则。也就是说,具有多态参数的过程必须具有显式接口,因此无法使用伪过程参数。
外部语句不是过时的,但如果始终提供显式接口则不需要(这是一种很好的做法)。
请注意,您将f作为extended
的绑定和模块过程。当您引用f
作为实际过程参数时,您指的是模块过程,而不是绑定。在您显示的代码中,没有必要将f
作为绑定。为了确保没有混淆 - 过程与绑定到过程的类型之间关系的性质在Fortran中与其他语言(如C ++)中使用的模型不同。程序永远不是类型的成员,绑定是。完全不同类型的绑定可以参考相同的过程。