fortran - 定义的赋值和内在赋值(使用 nagfor)之间有冲突吗?

标签 fortran polymorphism gfortran intel-fortran nag-fortran

内在多态赋值是某些 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 一起使用,但不能与其他旧编译器一起使用。知道这个错误从何而来以及如何解决它吗?

最佳答案

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

我将展示我的推理。

很明显,具体过程引用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. 接口(interface) block 提供了generic_shape_assign通用规范assignment(=)
  3. lhs(shape_t 类型)与 mycirc2(动态类型 circle_t)类型兼容; rhs 类似;
  4. 没有虚拟参数或实际参数的类型参数;
  5. 虚拟参数和实际参数的排名(标量)匹配。

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

总结:

It's not clear to me why this compiler is trying to use the defined assignment in the instruction mycirc2 = mycirc1 while these two variables are not allocatable polymorphic ones.

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

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

关于fortran - 定义的赋值和内在赋值(使用 nagfor)之间有冲突吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53390274/

相关文章:

fortran - 编译 Fortran 是否需要接口(interface) block ?

oop - Fortran 构造函数返回指向已分配对象的指针

floating-point - 比较浮点加法的存储结果与 Fortran 中的临时结果

c++ - 如何清理虚拟成员函数分配的资源

c++ - 使用 gfortran 链接 c++ 时 std::basic_string 的 undefined symbol ?

fortran - 如何从 sublime 文本运行 gfortran 代码?

Fortran "Error: Two main PROGRAMs at (1) and (2)"

visual-studio-code - 如何在VSCODE中设置tasks.json文件来编译Fortran程序?

c++ - 如果存在具有不同参数的继承成员,为什么对 C++ 结构的函数的调用会模棱两可?

java - 泛型多态混淆?