【问题标题】:Intrinsic Assignment and Polymorphism in Fortran 2003Fortran 2003 中的内在赋值和多态性
【发布时间】:2018-04-02 18:09:22
【问题描述】:

我尝试向this module 添加一个由@VladimirF 编写的过程,该过程在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

ifort 18.0.0 给出以下错误:

lists.f90(324): error #8304: In an intrinsic assignment statement, variable shall not be a non-allocatable polymorphic.   [ARRAYOUT]
      arrayOut(i) = nodeIter%item
------^

我是 F2​​003+ 中的多态性新手,所以我不理解错误消息或其上下文。出了什么问题,如何解决?

【问题讨论】:

  • 标记@VladimirF,因为他们是模块的作者。
  • 顺便说一句,这不会做任何事情。他们之前必须与帖子进行过互动。
  • @francescalus:感谢您找到我的复制/粘贴错字。修复了错误信息。

标签: fortran polymorphism intel-fortran


【解决方案1】:

错误消息的意思是它所说的。描述内在赋值语句的 Fortran 2008 标准说:“如果变量是多态的,它应该是可分配的,而不是 coarray”arrayOut 是 CLASS(*),它是多态的。只能分配可分配的多态。

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

【讨论】:

  • 谢谢,虽然我不明白“内在分配”。我澄清了上述问题中的链接,因此该链接现在将您直接带到我添加例程的文件。这是一个单链表的类。 (这就是上下文。)如果我改为将arrayOut 设为可分配,你是说这就足够了吗?
  • “内在赋值”是编译器提供的赋值语句(= 运算符,尽管在 Fortran 中它不是真正的运算符)。您可以使用用户定义的分配来扩展它。使 arrayOut 可分配是行不通的,因为您正在分配给单个元素。
【解决方案2】:

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

arrayOut(i) = nodeIter%item

是一个内在的赋值语句。

Fortran 2008(不是 Fortran 2003)允许该语句左侧的 变量 是多态的。 arrayOut(i) 这里是(无限)多态的。但是,在允许对多态变量赋值时有一个限制(F2008, 7.2.1.1 (1)):

如果变量是多态的,它应该是可分配的而不是coarray

这种情况下的编译器会抱怨,因为arrayOut(i) 是不可分配的。但是,即使使 arrayOut 可分配也无济于事:arrayOut(i) 是数组的一个元素,永远不会可分配。

你想在这里简单地做的,是做不到的。从以下事实可以清楚地看出这一点,即在分配给数组元素时,您不能保证数组的每个元素都与其他元素的类型完全相同。这是 Fortran 数组的要求,甚至是多态数组。

至于如何做你想做的事,有两种方法:

  • 让编译器相信所有元素都属于同一类型;
  • 使用数组容器

后者,像

type stuff
  class(*), allocatable :: item
end type stuff
type(stuff) arrayOut(length)

已在其他情况下出现在此处的问题和答案中。

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

【讨论】:

    【解决方案3】:

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

    我已经考虑过如何做这样的事情,但我没有想出一个令人满意的解决方案,即如何在库中通用地创建这样的函数。主要问题是没有类型保护可以检查两个实体的动态类型是否相同。您必须在 SELECT TYPE 中指定实际类型。

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

    1. 在同一个库中使用参数列表

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

      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
      

    如果有人知道通用的技巧并假设所有元素都属于同一类型,但没有指定类型,我想知道。

    【讨论】:

    • 我也想知道...只是提到有SAME_TYPE_AS(a,b) 内在函数,可以确定ab 是否属于同一类型。但是,正如@VladimirF 所写的那样,这仍然没有给你一个类型保护。
    猜你喜欢
    • 2013-02-22
    • 1970-01-01
    • 2019-04-24
    • 2013-12-02
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    相关资源
    最近更新 更多