将多态数组的子集复制到目标多态数组中
Copying subsets of polymorphic arrays into target polymorphic arrays
我在子例程中有两个派生类型多态数组(obj1 和 obj2)。基于子程序的使用,虽然两个数组的类型可能不同,但两个数组的类型相同;例如,A 型或B 型。在下面的示例代码中,我只展示了抽象class(模型)的一个子类型,而实际上,我希望它适用于多个子类型。此外,在生产代码中,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,model2,类型为linearDivisionMode)和一组索引,我想将指定的元素从obj1转移到obj2,在此过程中分配obj2 .
我已经尝试了很多方法,但 none 似乎有效。
首先,我试过使用向量下标直接赋值;这失败了,抱怨还不支持直接分配可分配的多态数组。
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))
第三,我已经能够分配多态数组,希望能够手动传输子元素:但是,当我尝试这样做时,我收到了关于多态对象和内部赋值的投诉,我稍后会回过头来在这个 post.
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 标准(此处强制执行),我无法将指针分配给向量索引数组。有趣的是,如果我创建一个指针、向量索引该指针,编译器会出现段错误,表明发生了一些奇怪的事情。
为了解决编译器对内部赋值的抱怨,我考虑过编写赋值例程;然而,这引起了一系列新的担忧:这两个例程继承自的父类型是抽象的,我似乎无法在 class 中指定通用 deferred 赋值运算符,导致复杂的父级 class 需要相当多的私有方法来复制,因为它没有指定私有变量。此外,subclasses A 和 B 之间的转换定义不明确。这似乎仍然是唯一剩下的出路,而且似乎很复杂。
如何有效传输指定的多态子数组?
我使用的是 gfortran 版本 6.1.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 trunk。
我在子例程中有两个派生类型多态数组(obj1 和 obj2)。基于子程序的使用,虽然两个数组的类型可能不同,但两个数组的类型相同;例如,A 型或B 型。在下面的示例代码中,我只展示了抽象class(模型)的一个子类型,而实际上,我希望它适用于多个子类型。此外,在生产代码中,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,model2,类型为linearDivisionMode)和一组索引,我想将指定的元素从obj1转移到obj2,在此过程中分配obj2 .
我已经尝试了很多方法,但 none 似乎有效。
首先,我试过使用向量下标直接赋值;这失败了,抱怨还不支持直接分配可分配的多态数组。
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))
第三,我已经能够分配多态数组,希望能够手动传输子元素:但是,当我尝试这样做时,我收到了关于多态对象和内部赋值的投诉,我稍后会回过头来在这个 post.
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 标准(此处强制执行),我无法将指针分配给向量索引数组。有趣的是,如果我创建一个指针、向量索引该指针,编译器会出现段错误,表明发生了一些奇怪的事情。
为了解决编译器对内部赋值的抱怨,我考虑过编写赋值例程;然而,这引起了一系列新的担忧:这两个例程继承自的父类型是抽象的,我似乎无法在 class 中指定通用 deferred 赋值运算符,导致复杂的父级 class 需要相当多的私有方法来复制,因为它没有指定私有变量。此外,subclasses A 和 B 之间的转换定义不明确。这似乎仍然是唯一剩下的出路,而且似乎很复杂。
如何有效传输指定的多态子数组?
我使用的是 gfortran 版本 6.1.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 trunk。