>EDIT以提供更多细节:
1(提供库的代码不能(容易(更改,因此profile_v1_type
和profile_v2_type
应该被认为是不可变的。
我已经实现了@francescalus建议,它适用于我的小型测试用例,但我认为我对这个问题不够清楚。原因是我只能修改我的代码,而不能修改来自库的代码/类型。问题在于,两者都会在导入的profile_type中t
,这与父类型冲突。
但是,我将实现一些东西,其中我复制所需的派生类型的内容,然后使用指针和类型绑定过程指向要使用的profile_type版本的组件。它没有我想要的那么干净,但它比我现在好多了。
我支持一个与另一个具有 2 个版本的代码接口的代码 - 这两个版本在接口上非常相似,尽管输入和输出在属性上相同,但它们显然是不同的派生类型(它们来自不同的库,并且其中包含的变量略有不同。这些类型中的大多数变量名称都是相同的,但至关重要(。
(显然(有必要在运行时同时支持两者,否则我将在编译时预处理这一切。
目前,我已经懒惰地将每个版本(以及它使用的派生类型的所有版本(的相同代码复制并粘贴到单独的子例程(*_v1.f90,*_v2.f90(中。
这很烦人,而且不太易于维护。
我希望能够做的是使用某种不关心它所指向什么的指针(或者更确切地说,从它指向的内容中获取其类型信息,并且足够聪明,可以知道里面有什么(。
正如我上面所说,名称大多相同,例如(t,表示温度,例如(
从库的 v1
:TYPE profile_v1_type
REAL :: t
! loads of other stuff
END TYPE profile_v1_type
从库的 v2
:TYPE profile_v2_type
REAL :: t
! loads of other stuff, more than the first version
END TYPE profile_v2_type
在我的代码中:
TYPE profile_container_type
TYPE(profile_v1_type) :: profile_v1
TYPE(profile_v2_type) :: profile_v2
! other arrays that are common inputs to both
END TYPE
! It's actually USE'd then allocated and initialised elsewhere, but I hope you get the idea
!USE profile_container_mod, ONLY : profile_container
TYPE(profile_container_type), TARGET :: profile_container
TYPE(*) :: p
REAL :: t1
!Version determined by a namelist
IF (Version == 1) THEN
p => profile_container % profile_v1
ELSE IF (Version == 2) THEN
p => profile_container % profile_v2
ENDIF
t1 = p % t + 1
.
.
.
ifort 19 给出了以下(预期(错误:
test.f90(24): error #8776: An assumed type object must be a DUMMY argument. [P]
TYPE(*), POINTER :: p
--------------------^
test.f90(24): error #8772: An assumed type object must not have the ALLOCATABLE, CODIMENSION, POINTER, INTENT(OUT) or VALUE attribute. [P]
TYPE(*), POINTER :: p
--------------------^
test.f90(39): error #6460: This is not a field name that is defined in the encompassing structure. [T]
t1 = p % t + 1
---------^
compilation aborted for test.f90 (code 1)
将 TYPE(*( 替换为 CLASS(*( 给出(仍然是预期的(:
test2.f90(39): error #6460: This is not a field name that is defined in the encompassing structure. [T]
t1 = p % t + 1 ! or some clever function...
---------^
compilation aborted for test2.f90 (code 1)
这是通过选择您要处理的类型来解决的,但我的观点是我想对 v1 和 v2 代码做同样的事情(永远不会两者兼而有之(。我想做很多次,不是在这个例程中,而是在十几个例程中。
如果响应者能够提供一个简单的示例来遵循,我愿意使用 C 指针。我已经尝试(不是最近(使用 C 互操作性解决这个问题,但显然没有成功!
无限的多态实体在这里不是正确的方法。
相反,我们可以定义一个基本类型,其中包含所有通用数据和各种其他类型的处理。 在这里,我们将这个基本类型称为profile_base_type
:
type profile_base_type
real t
end type
其他两个特定配置文件可以扩展此基础:
type, extends(profile_base_type) :: profile_v1_type
! v1 specific parts
end type
type, extends(profile_base_type) :: profile_v2_type
! v2 specific parts
end type
然后我们可以声明一个基类型的多态指针
class(profile_base_type), pointer :: p
可以指向任一扩展类型的目标:
p => profile_container%profile_v1
p => profile_container%profile_v2
现在,我们可以访问类型profile_base_type
中的p
组件
t1 = p%t + 1
无需使用选择类型构造。
当然,扩展类型的这些特定方面不能以这种方式访问,但还有其他注意事项。