定义的分配和内部分配之间的冲突(使用 nagfor)?
Conflict between defined assignment and intrinsic assignment (with nagfor)?
内在多态赋值是某些 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 签订了支持合同,我强烈建议您询问他们,而不是将我的意见视为最终意见。
我来论证一下。
很清楚,具体程序参考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
我们看给定的点:
generic_shape_assign
是一个带有两个伪参数的子例程(此处为 lhs
和 rhs
);
- 接口块给出
generic_shape_assign
通用规范 assignment(=)
;
lhs
(类型shape_t
)与mycirc2
(动态类型circle_t
)类型兼容; rhs
同样;
- 没有虚拟参数或实际参数的类型参数;
- 虚拟参数和实际参数的等级(标量)匹配。
我们满足了定义赋值的所有要求:没有要求声明定义赋值要求所选择的子程序是可调用的!
总结:
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 编译器(例如 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 签订了支持合同,我强烈建议您询问他们,而不是将我的意见视为最终意见。
我来论证一下。
很清楚,具体程序参考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
我们看给定的点:
generic_shape_assign
是一个带有两个伪参数的子例程(此处为lhs
和rhs
);- 接口块给出
generic_shape_assign
通用规范assignment(=)
; lhs
(类型shape_t
)与mycirc2
(动态类型circle_t
)类型兼容;rhs
同样;- 没有虚拟参数或实际参数的类型参数;
- 虚拟参数和实际参数的等级(标量)匹配。
我们满足了定义赋值的所有要求:没有要求声明定义赋值要求所选择的子程序是可调用的!
总结:
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.
因为是否使用定义赋值与左右端是多态的还是可分配的无关。
最后,无论我的推理是否正确,我认为来自编译器的诊断消息都可以改进。