将 Fortran 指针作为模块过程传递给子例程
Passing Fortran POINTER to SUBROUTINES as MODULE PROCEDURE
我的第一个问题是,“能否将 POINTER 传递给 INTENT 旁边的子程序?”
尽管使用 INTENT(IN) 或 INTENT(INOUT) 传递 Fortran POINTER 似乎是一种常见的做法,但 Intel for Fortran POINTER 的文档说(https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference/a-to-z-reference/o-to-p/pointer-fortran.html)
The pointer cannot be declared with the INTENT or PARAMETER attributes
这让我很困惑。
我的第二个问题与以下代码有关。
我尝试用 write_matrix_2d
重载 write_matrix
- 用于二维数组 - 和 write_matrix_2d_ptr
- 用于二维 Fortran 指针。
原来代码无法通过
编译
Ambiguous generic interface WRITE_MATRIX: previously declared specific procedure WRITE_MATRIX_2D is not distinguishable from this declaration. [WRITE_MATRIX_2D_PTR]
如果我评论 (1)
然后它符合要求,并且运行良好(但我认为这是不好的做法,因为 POINTER 参数进入需要数组输入的子程序 write_matrix_2d
。)
有没有办法像 C/C++ 一样仅通过参数的数据类型来重载 Fortran 子例程?
module mod_write
implicit none
interface write_matrix
module procedure write_matrix_2d
(1) !module procedure write_matrix_2d_ptr
end interface
contains
subroutine write_matrix_2d(a)
implicit none
real, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in ARRAY printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
subroutine write_matrix_2d_ptr(a)
implicit none
real, pointer, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in POINTER printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
end module
program test
use mod_write
implicit none
real, dimension(9) :: b = (/21, 22, 23, 24, 25, 26, 27, 28, 29/)
real, dimension(3,3) :: c
real, dimension(3,3), target :: ct(3,3)
real, dimension(:,:), pointer :: cptr(:,:)
c = reshape( b, (/3, 3/) )
write(*,*)
write(*,*) 'c'
call write_matrix(c)
(2) !call write_matrix_2d(c)
ct = c
cptr => ct(2:3,2:3)
write(*,*)
write(*,*) 'ct'
call write_matrix(ct)
(2,3)!call write_matrix_2d_ptr(ct)
write(*,*) 'cptr'
call write_matrix(cptr)
(2) !call write_matrix_2d_ptr(cptr)
end program
我的第三个问题又和附上的代码有关。重载不是什么大问题,因为我可以在代码中单独使用 write_matrix_2d
和 write_matrix_2d_ptr
作为 (2)
。但是,正如您在 (3)
看到的那样,call write_matrix_2d_ptr(ct)
使用 target
输入 ct
运行良好,而 write_matrix_2d_ptr
需要 pointer
输入。这样可以吗,还是我应该再做一个 write_matrix_2d_target
?
谢谢。
(1) 意图限制是一些复制和粘贴错误,或者是在一些我不明白的奇怪上下文中。 Fortran 90中就有这样的重写
(2) “但我认为这是不好的做法,因为 POINTER 参数进入需要数组输入的子程序 write_matrix_2d。”
将 Fortran 指针变量作为普通变量传递没有什么不好。默认的参数传递机制是使用正常的 non-ointer 机制传递指针的目标。只有在有特定理由的情况下,才会使用 pinter 虚拟参数。大多数情况下,tbat 意味着比一个在子例程中使用关联状态。还有一些其他用途,但你需要一个特定的理由来将你的参数声明为指针,否则它只会使事情复杂化。
(3) target
可以传递给 Fortran 2008 中的 pointer, intent(in)
。
编译器文档有误(或严重过时)。作为指针的虚拟参数也可以具有 intent 属性。该属性适用于参数的指针关联状态,而不是目标。
如果伪参数可区分,则可以重载通用接口中的过程。如果虚拟参数具有不同的类型、种类或级别,则它们是可区分的。某物是否是指针不是其类型的一部分。 (为了完整起见,如果一个参数是没有 intent(in) 的指针,而另一个是可分配的,那么参数也是可区分的。)通用接口中不同过程的可区分伪参数的要求意味着特定通用过程所围绕的规则参考解析为非常简单。
您的重载示例将是模棱两可的 - 将(n 关联的)指针实际参数传递给 non-pointer 虚拟参数是可以的 - 实际参数指定指针的目标。还允许将具有目标属性的 non-pointer 实际值传递给 intent(in) 指针虚拟对象。
是否为指针与是否为数组完全正交。
Fortran 中的指针主要用于在程序执行期间引用不同的事物(目标)。
如果您需要在与指针的关联状态相关的过程中执行某些操作,则伪参数只需要是一个指针 - 也许您想要测试关联状态,或者将指针与其他东西相关联。
我的第一个问题是,“能否将 POINTER 传递给 INTENT 旁边的子程序?”
尽管使用 INTENT(IN) 或 INTENT(INOUT) 传递 Fortran POINTER 似乎是一种常见的做法,但 Intel for Fortran POINTER 的文档说(https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference/a-to-z-reference/o-to-p/pointer-fortran.html)
The pointer cannot be declared with the INTENT or PARAMETER attributes
这让我很困惑。
我的第二个问题与以下代码有关。
我尝试用 write_matrix_2d
重载 write_matrix
- 用于二维数组 - 和 write_matrix_2d_ptr
- 用于二维 Fortran 指针。
原来代码无法通过
编译Ambiguous generic interface WRITE_MATRIX: previously declared specific procedure WRITE_MATRIX_2D is not distinguishable from this declaration. [WRITE_MATRIX_2D_PTR]
如果我评论 (1)
然后它符合要求,并且运行良好(但我认为这是不好的做法,因为 POINTER 参数进入需要数组输入的子程序 write_matrix_2d
。)
有没有办法像 C/C++ 一样仅通过参数的数据类型来重载 Fortran 子例程?
module mod_write
implicit none
interface write_matrix
module procedure write_matrix_2d
(1) !module procedure write_matrix_2d_ptr
end interface
contains
subroutine write_matrix_2d(a)
implicit none
real, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in ARRAY printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
subroutine write_matrix_2d_ptr(a)
implicit none
real, pointer, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in POINTER printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
end module
program test
use mod_write
implicit none
real, dimension(9) :: b = (/21, 22, 23, 24, 25, 26, 27, 28, 29/)
real, dimension(3,3) :: c
real, dimension(3,3), target :: ct(3,3)
real, dimension(:,:), pointer :: cptr(:,:)
c = reshape( b, (/3, 3/) )
write(*,*)
write(*,*) 'c'
call write_matrix(c)
(2) !call write_matrix_2d(c)
ct = c
cptr => ct(2:3,2:3)
write(*,*)
write(*,*) 'ct'
call write_matrix(ct)
(2,3)!call write_matrix_2d_ptr(ct)
write(*,*) 'cptr'
call write_matrix(cptr)
(2) !call write_matrix_2d_ptr(cptr)
end program
我的第三个问题又和附上的代码有关。重载不是什么大问题,因为我可以在代码中单独使用 write_matrix_2d
和 write_matrix_2d_ptr
作为 (2)
。但是,正如您在 (3)
看到的那样,call write_matrix_2d_ptr(ct)
使用 target
输入 ct
运行良好,而 write_matrix_2d_ptr
需要 pointer
输入。这样可以吗,还是我应该再做一个 write_matrix_2d_target
?
谢谢。
(1) 意图限制是一些复制和粘贴错误,或者是在一些我不明白的奇怪上下文中。 Fortran 90中就有这样的重写
(2) “但我认为这是不好的做法,因为 POINTER 参数进入需要数组输入的子程序 write_matrix_2d。”
将 Fortran 指针变量作为普通变量传递没有什么不好。默认的参数传递机制是使用正常的 non-ointer 机制传递指针的目标。只有在有特定理由的情况下,才会使用 pinter 虚拟参数。大多数情况下,tbat 意味着比一个在子例程中使用关联状态。还有一些其他用途,但你需要一个特定的理由来将你的参数声明为指针,否则它只会使事情复杂化。
(3) target
可以传递给 Fortran 2008 中的 pointer, intent(in)
。
编译器文档有误(或严重过时)。作为指针的虚拟参数也可以具有 intent 属性。该属性适用于参数的指针关联状态,而不是目标。
如果伪参数可区分,则可以重载通用接口中的过程。如果虚拟参数具有不同的类型、种类或级别,则它们是可区分的。某物是否是指针不是其类型的一部分。 (为了完整起见,如果一个参数是没有 intent(in) 的指针,而另一个是可分配的,那么参数也是可区分的。)通用接口中不同过程的可区分伪参数的要求意味着特定通用过程所围绕的规则参考解析为非常简单。
您的重载示例将是模棱两可的 - 将(n 关联的)指针实际参数传递给 non-pointer 虚拟参数是可以的 - 实际参数指定指针的目标。还允许将具有目标属性的 non-pointer 实际值传递给 intent(in) 指针虚拟对象。
是否为指针与是否为数组完全正交。
Fortran 中的指针主要用于在程序执行期间引用不同的事物(目标)。
如果您需要在与指针的关联状态相关的过程中执行某些操作,则伪参数只需要是一个指针 - 也许您想要测试关联状态,或者将指针与其他东西相关联。