【问题标题】:Conflict between defined assignment and intrinsic assignment (with nagfor)?定义的赋值和内在赋值之间的冲突(使用 nagfor)?
【发布时间】:2018-11-20 09:50:18
【问题描述】:

内在多态赋值是一些 Fortran 编译器(例如 ifort 18、nagfor 6.2)的最新功能,在旧版本(例如 ifort 17、gfortran 6.3)中不可用。与这些旧版本一起使用的一个众所周知的解决方案是使用如下示例中定义的分配(取自 Chivers 和 Sleightholme 的书并改编自):

module deftypes  
   type, abstract :: shape_t  
      integer :: x = 0, y = 0  
   end type shape_t  

   type, extends(shape_t) :: circle_t  
      integer :: radius = 0  
   end type circle_t  

   interface assignment(=)
      module procedure generic_shape_assign
   end interface   

contains  
   subroutine generic_shape_assign ( lhs, rhs )  
      class(shape_t),              intent(in ) :: rhs  
      class(shape_t), allocatable, intent(out) :: lhs  
      print*,' --> in generic_shape_assign'  
      allocate(lhs, source = rhs)  
   end subroutine generic_shape_assign
end module deftypes  

program check_assign  
   use deftypes  
   implicit none  
   class(shape_t), allocatable :: myshape
   type (circle_t)             :: mycirc1, mycirc2  

   mycirc1 = circle_t ( 1, 2, 3 )    

   print*,'A polymorphic assignment: myshape = mycirc1'  
   myshape = mycirc1  

   print*,'An intrinsic assignment: mycirc2 = mycirc1'   
   mycirc2 = mycirc1
end program check_assign

此示例编译并与 ifort 15.0.3 和 gfortran 6.3.0 配合使用。但是使用 nagfor 6.2 在编译过程中出现以下错误(mycirc2=mycirc1 行):

Error: check_assign.f90, line 41: Incorrect data type CIRCLE_T (expected SHAPE_T) for argument LHS (no. 1) of GENERIC_SHAPE_ASSIGN  

我不清楚为什么这个编译器试图使用指令mycirc2 = mycirc1 中定义的赋值,而这两个变量不是可分配的多态变量。

当然,如果我删除定义的赋值,它适用于 nagfor,但不适用于其他旧编译器。知道这个错误来自哪里以及如何解决它吗?

【问题讨论】:

    标签: fortran polymorphism gfortran intel-fortran nag-fortran


    【解决方案1】:

    我相信编译器拒绝这个程序是正确的。但是,如果您与 NAG 签订了支持合同,我强烈建议您询问他们是否将我的 cmets 视为最终决定。

    我会证明我的推理。

    很明显,具体程序参考generic_shape_assign就好了

    type(circle_t) mycirc1, mycirc2
    call generic_shape_assign(mycirc2, mycirc1)
    

    无效。它失败是因为实际参数mycirc2,对应于可分配的多态伪参数lhs

    • 不可分配;
    • 与相应的虚拟参数的声明类型不同;
    • 不是多态的。

    您引用的错误消息涵盖了因违反这一秒而被拒绝的程序。

    那么,这意味着generic_shape_assign 不是具有通用规范assignment(=) 的有效特定过程(用于此参考),对吧?因此没有选择定义的赋值,编译器应该回退到内在赋值?

    这就是事情变得模糊的地方(至少对我而言)。

    我认为特定的子程序 generic_shape_assign 被选择用于定义的赋值,因此编译器拒绝你的程序是正确的,因为你没有正确调用这个特定的子程序。

    让我们进一步看一下,使用 Fortran 2008 7.2.1.4,其中定义了赋值语句何时是已定义的赋值语句。

    要确定子程序generic_shape_assign 是否定义了定义的赋值语句mycirc2=mycirc1,我们查看给定点:

    1. generic_shape_assign 是一个带有两个虚拟参数的子程序(lhsrhs 这里);
    2. 接口块为generic_shape_assign 提供通用规范assignment(=)
    3. lhsshape_t 类型)与mycirc2(动态类型circle_t)的类型兼容; rhs 类似;
    4. 没有用于虚拟或实际参数的类型参数;
    5. 虚拟参数和实际参数的等级(标量)匹配。

    我们满足定义赋值的所有要求:没有要求说明定义的赋值要求所选子例程是可调用的!

    总结:

    我不清楚为什么这个编译器试图使用指令mycirc2 = mycirc1 中定义的赋值,而这两个变量不是可分配的多态变量。

    因为是否使用定义的赋值与左右两边是多态的还是可分配的无关。

    最后,我认为无论我的推理是否正确,编译器的诊断信息都可以改进。

    【讨论】:

    • “因此没有选择定义的赋值,编译器应该退回到内在赋值?”是的,这就是我的想法。我刚刚检查了最近的编译器 ifort 18 和 gfortran 8.1(即使定义的赋值在这里是多余的,因为这些编译器允许多态赋值与 nag one 一样)并且我没有收到任何错误消息并且结果是正确的。是的,我买了这个编译器(我只用了试用版)后,会在接下来的几天里询问 nag 支持,我会在这里报告他们的答案。谢谢 francescalus。
    • 我很想听听编译器开发人员的回答。专家们也聚集在 comp.lang.fortran 新闻组上。
    • 我应该补充一点,如果我是正确的并且程序无效,它不是无效的,因为编译器需要检测/诊断。
    • 抱歉这么长时间。正如承诺的那样,我请求了 Nag 的支持,他们完全证实了你的分析。他们“同意编译器信息可以改进,并相信标准中的措辞将得到改进,以更好地指导编译器编写者和用户。”再次感谢您的帮助。
    • 感谢您的更新。很高兴知道这个答案没有错。
    猜你喜欢
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2018-06-25
    • 2015-02-10
    • 2011-07-13
    • 2018-12-15
    相关资源
    最近更新 更多