1

我在子例程中有两个派生类型多态数组(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、model2 类型为 linearDivisionMode)和一组索引,我想将指定的元素从 obj1 转移到 obj2,在此过程中分配 obj2。

我已经尝试了很多方法来做到这一点,但似乎都没有奏效。

首先,我尝试使用向量下标直接赋值;这失败了,抱怨不支持直接分配可分配多态数组。

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 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 版。

4

1 回答 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 主干。

于 2016-06-23T23:05:36.813 回答