我在子程序中有两个派生类型的多态数组(obj1和obj2)。基于子程序的使用,虽然两个数组的类型可能不同,但两个数组都是相同的类型;例如,类型A或两者都是类型B.在下面的示例代码中,我只显示抽象类(模型)的一个子类型,而实际上,我希望这可以在多个子类型上工作。此外,在生产代码中,在此副本之前已修改了model1的元素。
program test
use env_kindtypes, only: si, dp
use abs_obj_model, only: model
use obj_linearDivisionModel, only: linearDivisionModel
implicit none
class(model),allocatable :: model1(:), model2(:)
allocate(linearDivisionModel::model1(10))
!want e.g. model2 = model1([1,4,6,2])
![...]
给定obj1,obj2(类型A)(在示例代码中给出为model1,类型为linearDivisionMode的model2)和一组索引,我想将指定的元素从obj1传递到obj2,在进程中分配obj2。 / p>
我尝试了很多方法,但似乎都没有。
首先,我尝试使用向量下标直接赋值;这失败了,抱怨说还不支持直接分配可分配的多态数组。
indices = [ 1 , 2 ]
model2 = model1(indices)
结果:
model2 = model1(indices)
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet supported
其次,我尝试使用源分配。如果我尝试使用数组切片表示法,它可以工作(但我的问题不能单独用这样的范围表达)。如果我尝试对源数组进行矢量索引,它会编译,但是在运行时我会因内存不足而出错(考虑到系统,这是不现实的。)
allocate(model2,source=model1(indices))
运行时结果:
Operating system error: Cannot allocate memory
Memory allocation failed
Error termination. Backtrace:
#0 0x434471 in __obj_lineardivisionmodel_MOD___copy_obj_lineardivisionmodel_Lineardivisionmode
at build/processed_src/obj_linear_model.f90:462
#1 0x436c75 in cg_charge_fit
at build/processed_src/test.f90:37
#2 0x403019 in main
at build/processed_src/test.f90:22
有效,但不足以达到我的目的。
allocate(model2,source=model1(1:2))
第三,我已经能够分配多态数组,希望手动转移子元素:但是,当我尝试这样做的时候,我会收到有关多态对象和内部赋值的抱怨,我将在后面再次讨论这个问题。交。
indices = [ 1 , 2 ]
allocate(model2(size(indices)),source=model1(1))
do i=1,size(indices)
model2(i) = model1(indices(i))
enddo
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator.
我尝试使用类型select语句来删除多态上下文,但错误仍然存在。
select type (POBJECT => model1)
TYPE IS (linearDivisionModel)
allocate(linearDivisionModel::model2(size(indices)))
do i=1,size(indices)
model2(i) = POBJECT(indices(i))
enddo
end select
结果:
model2(i) = model1(indices(i))
1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator
作为一种解决方法,我希望使用一个中间指针对象,并从中获取资源。由于f2008标准(这里强制执行),我不能指定一个指向矢量索引数组的指针。有趣的是,如果我创建一个指针,向量索引指针,编译器会出现段错误,表明存在奇怪的事情。
为了解决编译器关于内在赋值的抱怨,我考虑过编写赋值例程;然而,这引出了一系列新的担忧:这些例程继承自的父类型是抽象的,我似乎无法在该类中指定通用的延迟赋值运算符,从而导致复杂的父类这需要很多私有方法来复制,因为它没有指定私有变量。此外,子类A和B之间的转换定义不明确。这仍然是唯一剩下的出路,而且似乎很复杂。
如何有效地传输指定的多态子阵列?
我正在使用gfortran版本6.1.1。
答案 0 :(得分:1)
完全支持F2008,这只是一个赋值语句。
在该编译器的约束下,您可能需要考虑嵌套的SELECT TYPE构造,这样可以消除赋值左侧和右侧的多态性。
module my_types
implicit none
type, abstract :: model
end type
type, extends(model) :: linearDivisionModel
character :: comp
end type linearDivisionModel
end module my_types
program p
use my_types
implicit none
class(model),allocatable :: model1(:), model2(:)
integer, allocatable :: indicies(:)
! define model1.
block
type(linearDivisionModel), allocatable :: tmp(:)
allocate(tmp(10))
tmp%comp = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
call move_alloc(tmp, model1)
end block
indicies = [1, 2, 4, 6]
! allocate model2.
allocate(model2(size(indicies)), mold=model1)
! define model2
select type (model1)
type is (linearDivisionModel)
select type (model2)
type is (linearDivisionModel)
model2 = model1(indicies)
end select
end select
! display results.
select type (model2)
type is (linearDivisionModel)
print *, model2%comp
end select
end program p
以上似乎适用于当前的gfortran主干。