【问题标题】:Two derived types sharing same subroutine共享相同子例程的两个派生类型
【发布时间】:2015-07-16 13:40:52
【问题描述】:

我在一个模块中有两个派生类型,IntervalInrset。两者具有相同的功能,但是一个对实数进行操作,另一个对整数进行操作。

遇到的问题如下

lib/interval.f:85:11:

Procedure :: eptset => inrval_set
        1
Error: Argument 't' of 'inrval_set' with PASS(t) at (1) 
must be of the derived-type 'inrset'

lib/interval.f:55:11:

Procedure :: eptset => inrval_set
        1
Error: Argument 't' of 'inrval_set' with PASS(t) at (1) 
must be of the derived-type 'interval'

这里是Interval 派生类型

Type Interval

Real (Real32) :: inf, sup

Contains
  Procedure :: eptset => inrval_set

End Type Interval

这是Intrset 派生类型

Type Inrset

Integer (Int32) :: inf, sup

Contains
  Procedure :: eptset => inrval_set

End Type Inrset

这应该是设置infsup的通用子程序。

Subroutine inrval_set  &
  (                    &
    t, inf, sup        &
  )

Class (*), Intent (InOut) :: t
Class (*), Intent (In) :: inf, sup

!!$--------------------------------------------------
!!$ Sets t% inf = inf;  t% sup = sup

Select Type (t)
Type Is (Interval)
  Call numtrf (t% inf, inf)
  Call numtrf (t% sup, sup)

Type Is (Inrset)
  Call numtrf (t% inf, inf)
  Call numtrf (t% sup, sup)

End Select 

End Subroutine inrval_set

【问题讨论】:

  • 您想知道为什么您尝试做的事情是错误的,还是另一种方法来做您想做的事情?
  • 我正在寻找一种可行的方法。我已经为每种有效的类型设置了单独的例程。不过,这将有助于理解这段代码发生了什么。
  • 要求我对每种情况都有单独的子例程。有没有好的解决方法,还是我必须重新考虑方法?
  • 好吧,如果你有不同的类型,你需要两个不同的类型绑定过程,每个都有正确的传递虚拟参数。这就是错误所说的。如何最好地设计你的程序是一个不同的问题。

标签: fortran derived-types


【解决方案1】:

诚然,错误消息并不总是有用的。在这种情况下,这是一个很好的提示。

您的派生类型Interval 有一个类型绑定过程,绑定名称为eptset,接口与过程inrval_set 相同。这是你的难处。

我想你心里想着这样的电话

type(Interval) range
call range%eptset(1._real32, 15._real32)

这是一个合理的目标。

但是,您依赖于传递对象的虚拟参数,因此在inrval_set 中,您的第一个虚拟参数t 是动态类型range。这是有缺陷的。

正如错误消息所示,Interval 中的类型绑定过程的接口必须,因为它没有NOPASS 属性,所以有一个Interval 类型的虚拟参数。 class(*) 的伪参数不是这样的。

您不想使用NOPASS 执行此方法。

你当然可以

call inrval_set(range, 1._real32, 15._real32)

作为一种选择。但是有类型绑定的方式吗?

是的。

你可以考虑templating。或者,有一个(抽象的)父类。或者提供具有适当接口的类型绑定过程 - 每种类型一个。

本质上,您是在重复 select type 块中的代码,因此您不妨改为使用通用/动态分辨率重复代码。

【讨论】:

  • 我明白了。注意到在模板化时,.inc 文件中没有分配任何类型。
  • 你能给我解释一下NOPASS这个想法吗?
  • 您可以在通常的参考资料中了解nopass。我不会在这里解释,因为这真的不是你想做的事情。 nopass 只是意味着被调用的过程不会有传递对象的虚拟参数。但这就是您想要的,因为您想设置该对象的值。它确实允许你做call range%eptset(range, ..., ...)(可能),但那一点你也可以只做call inrval_set(range, ..., ...)
  • 是的。当我对一些运算符进行编码时,我使用了 pass,其中第一个虚拟参数没有键入派生类型名称。我跟你说我想要一个类型绑定的过程而不是调用inrval_set(range, ..., ...)
  • 更多关于模板的信息也在这里stackoverflow.com/questions/24979199/stl-analogue-in-fortran/…。您将看到如何使用 #include 而不是 include 为类型获取权力。
猜你喜欢
  • 2014-12-01
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多