Fortran 2003中的内在赋值和多态性

Fortran 2003中的内在赋值和多态性,fortran,polymorphism,intel-fortran,Fortran,Polymorphism,Intel Fortran,我尝试向中添加一个由编写的过程,该过程在Fortran 2003中实现了一个通用链表。为了方便起见,我希望能够将列表的内容输出为数组,因此我将以下过程添加到名为lists.f90的文件中的列表模块中: subroutine list_as_array(self, arrayOut) class(list),intent(inout) :: self class(*),dimension(1:self%length),intent(out) :: arrayOut in

我尝试向中添加一个由编写的过程,该过程在Fortran 2003中实现了一个通用链表。为了方便起见,我希望能够将列表的内容输出为数组,因此我将以下过程添加到名为
lists.f90
的文件中的列表模块中:

  subroutine list_as_array(self, arrayOut)
    class(list),intent(inout) :: self
    class(*),dimension(1:self%length),intent(out) :: arrayOut
    integer :: i
    type(list_node), pointer :: nodeIter
    nodeIter = self%first
    do i = 1,self%length
      arrayOut(i) = nodeIter%item  ! <---ERROR here
      if (i<self%length) then
        nodeIter = nodeIter%next
      end if
    end do
  end subroutine list_as_array

我不熟悉F2003+中的多态性,所以我不理解错误消息或其上下文。出了什么问题,如何解决

错误消息的意思是它所说的。Fortran 2008标准描述了内在赋值语句,它说:“如果变量是多态的,那么它应该是可分配的,而不是一个并行的”数组是
类(*)
,这使得它是多态的。只能将可分配的多态性分配给


至于“如何修复”,这需要更多的上下文。

首先,关于错误消息。在没有某些已定义赋值的情况下,语句

arrayOut(i) = nodeIter%item
是一个内在赋值语句

Fortran 2008(不是Fortran 2003)允许此语句左侧的变量具有多态性<代码>排列(i)这里是(无限)多态的。然而,在允许对多态变量赋值时存在一个限制(F2008,7.2.1.1(1)):

如果变量是多态的,它应该是可分配的,而不是一个协数组

本例中的编译器正在抱怨,因为
arrayOut(i)
不可分配。但是,即使使
arrayOut
可分配也无济于事:
arrayOut(i)
是数组的一个元素,永远不可分配

你想在这里简单地做的事是做不到的。这一点应该很清楚,在分配给数组元素时,并不能保证数组中的每个元素都与其他元素的类型完全相同。这是Fortran数组的一个要求,甚至是多态数组

关于如何做自己想做的事情,有两种方法:

  • 说服编译器所有元素都是相同类型的
  • 使用数组容器
后者,比如

type stuff
  class(*), allocatable :: item
end type stuff
type(stuff) arrayOut(length)
在这里的问答中出现了其他上下文


为了“令人信服”,您需要使左侧非多态。

我认为其他答案很好地描述了这个问题。不能分配给多态的不可分配变量。而且数组元素永远不可分配

我曾经考虑过如何做这样的事情,但是我没有找到一个令人满意的解决方案,如何在库中创建这样一个函数。主要的问题是,没有类型保护程序只检查两个实体的动态类型是否相同。必须在“选择类型”中指定实际类型

作为库的用户,一旦知道所有元素都是同一类型的,就有两种可能

  • 在同一库中使用参数化列表

  • 为数组中可能出现的每种类型创建自己的函数。不是在库中,而是在您自己的代码中。您必须保证所有元素都属于该类型

    subroutine integer_list_as_array(self, arrayOut)
      class(list),intent(inout) :: self
      integer,dimension(1:self%length),intent(out) :: arrayOut
      ...
    end subroutine integer_list_as_array
    

  • 如果有人知道这样做的诀窍,只是假设所有元素都是相同的类型,但不指定类型,我想知道。

    Tagging@VladimirF,因为他们是模块的作者。顺便说一句,这没什么用。他们以前一定和帖子有过互动。@francescalus:谢谢你找到我的复制/粘贴错误。修复了错误消息。谢谢,尽管我不理解“内在赋值”。我澄清了上面问题中的链接,因此该链接现在直接将您带到我添加例程的文件。这是一个单链接列表的类。(这就是上下文。)如果我将
    arrayOut
    改为可分配,你是说这就足够了吗?“内在赋值”是编译器提供的赋值语句(=运算符,尽管在Fortran中它实际上不是运算符)。您可以使用用户定义的分配来扩展此功能。使ArrayYout可分配将不起作用,因为您正在分配给单个元素。我也想知道。。。只需提到,
    与(a,b)
    固有的类型相同,可以确定
    a
    b
    是否属于同一类型。但正如@VladimirF所写,这仍然不能给你一个类型的守卫。
    subroutine integer_list_as_array(self, arrayOut)
      class(list),intent(inout) :: self
      integer,dimension(1:self%length),intent(out) :: arrayOut
      ...
    end subroutine integer_list_as_array