【问题标题】:Fortran OOP circular dependency handling, interfacesFortran OOP 循环依赖处理、接口
【发布时间】:2012-07-17 23:44:13
【问题描述】:

编译器:ifort 版本 12.1.5

我正在编写一些 Fortran 代码,我想利用一些 F2003 OOP 功能,但我遇到了一些绊脚石。简化示例,我希望有两个派生类型 A 和 B,每个类型都有一个指向另一个实例的指针。在 Fortran 中,明确不允许模块之间的循环依赖关系,因此这两种类型必须驻留在同一个模块中。这样编译:

module testModule
implicit none

type A
 type(B),pointer :: b1
end type A

type B
 type(A),pointer :: a1
end type B

contains
[some possibly type-bound procedures]
end module

现在,我想为这些类型实现一些构造函数,并尝试以下代码:

module testModule
implicit none

type A
 type(B),pointer :: b1
end type A

interface A
 module procedure A_ctor
end interface

type B
 type(A),pointer :: a1
end type B

interface B
 module procedure B_ctor
end interface

contains
function A_ctor()
 type(A),target :: A_ctor
end function
function B_ctor()
 type(B),target :: B_ctor
end function
end module

现在,这不编译,抛出错误

这不是派生类型名称。 [乙]

在上面的第 5 行。为什么添加接口会报错?在 Fortran 中如何处理派生类型中的循环依赖,就像在 C++ 中使用前向类声明一样?

【问题讨论】:

  • ifort 13.0.0.041 编译你的模块没有错误,只对没有定义返回值的函数发出警告。
  • 太好了,谢谢马克,我会更新的。

标签: oop constructor module fortran circular-dependency


【解决方案1】:

您的代码是正确的 Fortran 2003。您正在以正确的方式处理循环类型依赖项。编译器出错了。

我已经经历并看到其他人报告了 ifort 12.1.5 和程序员重写结构构造函数的问题(其中有一个泛型接口到具有派生类型结果的函数,该接口与派生类型具有相同的名称- 就像你在这里一样)。这种情况的解决方法是将构造函数的泛型接口(和后续引用)重命名为与派生类型不同的名称。

【讨论】:

  • 所以你说最好的解决方法是简单地拥有一个单独的初始化例程(一些私有子例程)来处理所有构造/分配职责,而忘记任何 RAII 想法?你将如何为这样的派生类型编写私有函数,最好返回一个指向对象的指针?
  • interface A 改为interface ConstructA,然后用ConstructA() 替换function references 到A()。对 B 重复。除了使用的名称外,您的方法不需要更改。
【解决方案2】:

尽管 2003 听起来很久以前,但在大多数编译器中,fortran 2003 的实现仍然是一个持续的过程。在处理新功能时很可能仍然存在遗漏或错误。

如果这是一个已知问题,请与编译器的支持团队联系,如果是,是否有更新的版本可以解决此问题。

作为支持 - 虽然不是决定性的 - 证明此代码符合标准的证据,gfortran 编译它没有错误(只有两个关于未设置函数返回值的警告)。

【讨论】:

  • 有趣,感谢您提供的信息,我还没有尝试使用最新的 gfortran,因为性能通常太慢,无法选择。
  • 如果您使用这些现代功能和指针,则并非总是如此。我发现英特尔在 Fortran 和 C 的二叉树枪战基准测试中比 GCC 慢得多。一般来说,当使用最先进的功能时,你不能指望可实现的最佳性能。
猜你喜欢
  • 2011-07-26
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 2015-07-06
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
相关资源
最近更新 更多