gfortran 指针过程类型问题
gfortran pointer procedure type issue
我尝试拥有一个无需使用通用过程即可接受不同输入类型的过程。事实上,(在这种情况下)我更喜欢手动设置过程指针的目标来定义要使用的过程而不是通用过程。
这就是我对以下几乎最小的示例所做的。
module mo
implicit none
type :: TypeB
character(len=5) :: info='Hello'
contains
procedure, pass(fd) :: say_hello
end type TypeB
type :: TypeA
character(len=4) :: txt='Hola'
!type(TypeB) :: Tb
end type TypeA
type, extends(TypeA) :: TypeC
character(len=4) :: tt='Hey!'
type(TypeB) :: Tb
end type TypeC
type, extends(TypeA) :: TypeD
character(len=3) :: tt='Ho!'
character(len=3) :: ti='you'
!type(TypeB) :: Tb
end type TypeD
type(TypeC) :: Tc
type(TypeD) :: Td
procedure(), pointer :: proc
class(TypeA), allocatable :: CA
contains
subroutine say_hello(fd)
implicit none
! type(TypeB), intent(inout) :: fd
class(TypeB), intent(inout) :: fd
print *, fd%info
end subroutine say_hello
subroutine procC(fd, args)
implicit none
! class(TypeC), intent(inout) :: fd
type(TypeC), intent(inout) :: fd
real :: args
print*, args
print*, fd%tt
call fd%Tb%say_hello()
end subroutine procC
subroutine procD(fd, args)
implicit none
! class(TypeD), intent(inout) :: fd
type(TypeD), intent(inout) :: fd
! class(TypeA), intent(inout) :: fd
real :: args
print*, args
print*, fd%tt
print*, fd%ti
end subroutine procD
end module mo
program p
use mo
implicit none
print* , 'START'
print *, Tc%tb%info
print *, Tc%txt
call Tc%Tb%say_hello()
call procC(Tc, 1.0)
call procD(Td, 2.0)
print*, 'OK'
allocate(TypeD :: CA)
proc =>procD
call proc(CA, 3.0)
deallocate(CA)
allocate(TypeC :: CA)
proc =>procC
call proc(CA, 4.0)
deallocate(CA)
print*, 'END'
end program p
当我在 Linux 上使用 ifort 编译时,我得到了预期的结果,但是当我在 Windows 或 Linux 上使用 gfortran (MinGW 6.2.0) 编译时(gfortran 5.5. 0 和 6.4.0),我得到一些奇怪的东西:
START
Hello
Hola
Hello
1.00000000
Hey!
Hello
2.00000000
Ho!
you
OK
3.00000000
@R
4.00000000
ÇR@
END
当我在出现分段错误的大程序中使用此方法时,情况变得更糟。
那么,有没有办法避免这些问题呢?这是gfortran的错误吗?还是我误会了什么?
这里你的程序有问题。
考虑部分
proc =>procD
call proc(CA, 3.0)
我首先考虑的是
call procD(CA,3.0)
子例程 procD
的第一个伪参数声明为 type(typeD)
。这是一个非多态实体,具有动态和声明类型 typeD
。主程序的实参CA
是动态类型typeD
的多态实体,但声明类型typeA
.
在过程引用中,每个伪参数都必须与其关联的实际参数类型兼容。这里不是这种情况:非多态对象仅与与其自身声明类型相同的实体类型兼容。它与多态实体类型不兼容,虽然具有相同的动态类型但声明的类型不同。
在工作版本中
call procD(Td, 2.0)
实参 Td
的声明类型为 typeD
,因此类型兼容。
在此处使用带有隐式接口的过程指针会使编译器更难检测程序中的此错误(不需要这样做)。
我尝试拥有一个无需使用通用过程即可接受不同输入类型的过程。事实上,(在这种情况下)我更喜欢手动设置过程指针的目标来定义要使用的过程而不是通用过程。
这就是我对以下几乎最小的示例所做的。
module mo
implicit none
type :: TypeB
character(len=5) :: info='Hello'
contains
procedure, pass(fd) :: say_hello
end type TypeB
type :: TypeA
character(len=4) :: txt='Hola'
!type(TypeB) :: Tb
end type TypeA
type, extends(TypeA) :: TypeC
character(len=4) :: tt='Hey!'
type(TypeB) :: Tb
end type TypeC
type, extends(TypeA) :: TypeD
character(len=3) :: tt='Ho!'
character(len=3) :: ti='you'
!type(TypeB) :: Tb
end type TypeD
type(TypeC) :: Tc
type(TypeD) :: Td
procedure(), pointer :: proc
class(TypeA), allocatable :: CA
contains
subroutine say_hello(fd)
implicit none
! type(TypeB), intent(inout) :: fd
class(TypeB), intent(inout) :: fd
print *, fd%info
end subroutine say_hello
subroutine procC(fd, args)
implicit none
! class(TypeC), intent(inout) :: fd
type(TypeC), intent(inout) :: fd
real :: args
print*, args
print*, fd%tt
call fd%Tb%say_hello()
end subroutine procC
subroutine procD(fd, args)
implicit none
! class(TypeD), intent(inout) :: fd
type(TypeD), intent(inout) :: fd
! class(TypeA), intent(inout) :: fd
real :: args
print*, args
print*, fd%tt
print*, fd%ti
end subroutine procD
end module mo
program p
use mo
implicit none
print* , 'START'
print *, Tc%tb%info
print *, Tc%txt
call Tc%Tb%say_hello()
call procC(Tc, 1.0)
call procD(Td, 2.0)
print*, 'OK'
allocate(TypeD :: CA)
proc =>procD
call proc(CA, 3.0)
deallocate(CA)
allocate(TypeC :: CA)
proc =>procC
call proc(CA, 4.0)
deallocate(CA)
print*, 'END'
end program p
当我在 Linux 上使用 ifort 编译时,我得到了预期的结果,但是当我在 Windows 或 Linux 上使用 gfortran (MinGW 6.2.0) 编译时(gfortran 5.5. 0 和 6.4.0),我得到一些奇怪的东西:
START
Hello
Hola
Hello
1.00000000
Hey!
Hello
2.00000000
Ho!
you
OK
3.00000000
@R
4.00000000
ÇR@
END
当我在出现分段错误的大程序中使用此方法时,情况变得更糟。
那么,有没有办法避免这些问题呢?这是gfortran的错误吗?还是我误会了什么?
这里你的程序有问题。
考虑部分
proc =>procD
call proc(CA, 3.0)
我首先考虑的是
call procD(CA,3.0)
子例程 procD
的第一个伪参数声明为 type(typeD)
。这是一个非多态实体,具有动态和声明类型 typeD
。主程序的实参CA
是动态类型typeD
的多态实体,但声明类型typeA
.
在过程引用中,每个伪参数都必须与其关联的实际参数类型兼容。这里不是这种情况:非多态对象仅与与其自身声明类型相同的实体类型兼容。它与多态实体类型不兼容,虽然具有相同的动态类型但声明的类型不同。
在工作版本中
call procD(Td, 2.0)
实参 Td
的声明类型为 typeD
,因此类型兼容。
在此处使用带有隐式接口的过程指针会使编译器更难检测程序中的此错误(不需要这样做)。