1

I have a base type which contains a procedure that takes a user defined function as input. User defined functions are defined in extended types. The following compiles with ifort-13.1.3 but fails with 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 produces

     call this%use_f(f)
                1
Error: Interface mismatch in dummy procedure 'func' at (1): Type/rank mismatch in argument 'this'

I have also tried using procedure pointers, but still ifort compiles while gfortran fails. Now, if instead of an interface block I put

external func

into use_f the code compiles successfully with both ifort and gfortran. But isn't the EXTERNAL keyword becoming obsolescent? Is there a more standard-conforming approach that works?

4

1 回答 1

6

提供的程序有误。虽然从技术上讲,编译器不需要发出诊断,但我希望 ifort 应该这样做,尽管在某些情况下这可能是一个合理的扩展。我建议向英特尔报告错误。

正如 gfortran 错误消息所暗示的那样,实际过程参数和虚拟过程参数的特征并不相同。F2008 的 12.5.2.9p1 要求它们在 dummy 的接口是显式的情况下相同,除非有一些这里不相关的例外。过程的特征包括其参数的特征。虚拟数据参数的特征包括其类型。

实际过程中extended哑元的类型是 ,哑过程中哑元的类型是base

这个问题可能令人困惑的是,如果您实际上是使用所描述的接口调用一个过程,func那么将一个类型的对象extended作为实际参数传递给该过程是有效的。但是仅仅因为 typebase是 type compatible withextended并不会使类型相同。

当虚拟过程参数的接口是隐式的(比如说因为您使用了 EXTERNAL 语句),那么围绕匹配特征的规则就会放宽。也就是说,具有多态参数的过程必须具有显式接口,因此无法使用虚拟过程参数。

external 语句不是过时的,但如果始终提供显式接口,则不需要它(这是一种很好的做法)。

请注意,您将 f 作为模块过程的绑定extended和模块过程。当您引用f作为实际过程参数时,您指的是模块过程,而不是绑定。在您显示的代码中,没有任何意义f作为绑定。为了确保没有混淆 - Fortran 中的过程和绑定到过程的类型之间的关系性质与其他语言(例如 C++)中使用的模型不同。过程永远不是类型的成员,绑定是。完全不同类型的绑定可以引用相同的过程。

于 2013-09-08T12:41:53.300 回答