接口中数组的形状是否可以匹配多个固定数组大小?
Can the shape of an array in an interface match multiple fixed array size?
我有多个带有参数 p 的子例程,它是一个明确大小的数组,如
subroutine foo(p)
integer,dimension(2),intent(in) ::p
end subroutine foo
subroutine bar(p)
integer,dimension(3),intent(in) ::p
end subroutine bar
我想通过间接调用来调用这两个函数,但找不到一种方法来声明与 foo 和 bar 签名都匹配的接口...
例如,在界面中使用假定的数组大小是行不通的:
subroutine indirect(f,p)
integer,dimension(*),intent(in):p
interface
subroutine f(p)
integer,dimension(*),intent(in) :: p
end subroutine f
end interface
call f(p)
end subroutine indirect
当我间接调用 foo 或 bar 时,编译器 (gfortran 4.9.2) 抱怨 f 的第一个参数 p 的形状不匹配...
integer,dimension(2) :: pfoo
integer,dimension(3) :: pbar
pfoo = (/ 0,1 /)
pbar = (/ 1,2,3 /)
call foo(pfoo) ! direct call is OK
call bar(pbar)
call indirect(foo,pfoo) ! compiler complains about foo signature
call indirect(bar,pbar) ! same for bar...
编译器错误类似于:
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'p'
当然,我可以修改 foo 和 bar 签名以使用假定的数组大小 (*) 而不是固定的数组大小,但是
就好像我为了制作编译器而丢失了一些信息
不增加任何安全措施就很开心
foo 和 bar 不是我的代码,我不想更改它们...
我找到了一个解决方法,但它包括为每个子例程 foo 和 bar 编写一个假定大小的包装器
call indirect(foo_wrapper,pfoo) ! compiler complains about foo signature
call indirect(bar_wrapper,pbar) ! same for bar...
subroutine foo_wrapper(p)
integer,dimension(*),intent(in) ::p
call foo(p)
end subroutine foo_wrapper
subroutine bar_wrapper(p)
integer,dimension(*),intent(in) ::p
call bar(p)
end subroutine bar_wrapper
或者最终,用间接和包装器中的延迟大小替换所有假定大小,以便有机会进行运行时检查,这也有效,但这不是重点...
关键是,因为我有很多这样的 foo/bar 没有办法正确声明接口(我的意思是没有包装器或其他人工制品)。
我无法破译标准(我使用了 http://www.j3-fortran.org/doc/year/10/10-007.pdf - 我假设它在 12.5.2.9 与虚拟过程实体相关的实际参数 §2 左右),所以不知道是不是gfortran的限制。现在我没有任何其他可用的编译器,但我想知道是否有其他编译器可以编译(英特尔? - 我在 windows 7 64 位)。
我会看看 gfortran 的投诉是否正确,无论如何,有哪些选项可以解决投诉。参考是 Fortran 2008。
12.5.2.9确实很重要
- If the interface of a dummy procedure is explicit, its characteristics as a procedure (12.3.1) shall be the same as those of its effective argument, except that [inapplicable things]
f
in indirect
是一个带有显式接口的虚拟过程(通过接口块;12.4.2.1)。查看参考12.3.1我们看到
The characteristics of a procedure are .. , the characteristics of its dummy arguments, ..
foo
、bar
和 f
都是带有单个伪参数的过程(碰巧都称为 p
)。所以,如果 foo
想成为与 f
相关的有效参数,那么 foo
的 p
必须匹配 f
的 p
的特征].每个 p
都是一个虚拟数据对象,因此 12.3.2.2 变得相关:
The characteristics of a dummy data object are its type, its type parameters (if any), its shape, ... If a shape, size, or type parameter is assumed or deferred, it is a characteristic.
我们发现类型和类型参数匹配。但是,f
中的 p
具有假定的大小。 foo
中的p
没有这个匹配特征。然后,不允许在对 indirect
的调用中将 foo
与 f
相关联。 bar
.
也是如此
这种要求dummy data对象的匹配特征必须具有相同的形状,自然而然会得出另外一个结论:foo
和bar
不具备作为过程的匹配特征。对于第三个程序来匹配两者的形状特征必须被忽略。
可以使用包装器子例程,但我也会考虑是否可以更改各种子例程以采用假定形状参数。这比假定大小要好得多。但是,正如您所说,我也不愿意更改该代码。
对于子例程foo
和bar
,因为您有它们,还有另一个可用的选项。这些子例程不需要调用者为它们提供显式接口 (12.4.2.2)。因此,在 indirect
中,您可以只废弃接口块:有关匹配的规则要宽松得多(12.5.2.9 的其他部分)。但是,对于其他程序,这可能是不可能的。
综上所述,ifort 似乎可以愉快地编译并且 运行 您拥有的代码...
我有多个带有参数 p 的子例程,它是一个明确大小的数组,如
subroutine foo(p)
integer,dimension(2),intent(in) ::p
end subroutine foo
subroutine bar(p)
integer,dimension(3),intent(in) ::p
end subroutine bar
我想通过间接调用来调用这两个函数,但找不到一种方法来声明与 foo 和 bar 签名都匹配的接口...
例如,在界面中使用假定的数组大小是行不通的:
subroutine indirect(f,p)
integer,dimension(*),intent(in):p
interface
subroutine f(p)
integer,dimension(*),intent(in) :: p
end subroutine f
end interface
call f(p)
end subroutine indirect
当我间接调用 foo 或 bar 时,编译器 (gfortran 4.9.2) 抱怨 f 的第一个参数 p 的形状不匹配...
integer,dimension(2) :: pfoo
integer,dimension(3) :: pbar
pfoo = (/ 0,1 /)
pbar = (/ 1,2,3 /)
call foo(pfoo) ! direct call is OK
call bar(pbar)
call indirect(foo,pfoo) ! compiler complains about foo signature
call indirect(bar,pbar) ! same for bar...
编译器错误类似于:
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'p'
当然,我可以修改 foo 和 bar 签名以使用假定的数组大小 (*) 而不是固定的数组大小,但是
就好像我为了制作编译器而丢失了一些信息 不增加任何安全措施就很开心
foo 和 bar 不是我的代码,我不想更改它们...
我找到了一个解决方法,但它包括为每个子例程 foo 和 bar 编写一个假定大小的包装器
call indirect(foo_wrapper,pfoo) ! compiler complains about foo signature
call indirect(bar_wrapper,pbar) ! same for bar...
subroutine foo_wrapper(p)
integer,dimension(*),intent(in) ::p
call foo(p)
end subroutine foo_wrapper
subroutine bar_wrapper(p)
integer,dimension(*),intent(in) ::p
call bar(p)
end subroutine bar_wrapper
或者最终,用间接和包装器中的延迟大小替换所有假定大小,以便有机会进行运行时检查,这也有效,但这不是重点...
关键是,因为我有很多这样的 foo/bar 没有办法正确声明接口(我的意思是没有包装器或其他人工制品)。
我无法破译标准(我使用了 http://www.j3-fortran.org/doc/year/10/10-007.pdf - 我假设它在 12.5.2.9 与虚拟过程实体相关的实际参数 §2 左右),所以不知道是不是gfortran的限制。现在我没有任何其他可用的编译器,但我想知道是否有其他编译器可以编译(英特尔? - 我在 windows 7 64 位)。
我会看看 gfortran 的投诉是否正确,无论如何,有哪些选项可以解决投诉。参考是 Fortran 2008。
12.5.2.9确实很重要
- If the interface of a dummy procedure is explicit, its characteristics as a procedure (12.3.1) shall be the same as those of its effective argument, except that [inapplicable things]
f
in indirect
是一个带有显式接口的虚拟过程(通过接口块;12.4.2.1)。查看参考12.3.1我们看到
The characteristics of a procedure are .. , the characteristics of its dummy arguments, ..
foo
、bar
和 f
都是带有单个伪参数的过程(碰巧都称为 p
)。所以,如果 foo
想成为与 f
相关的有效参数,那么 foo
的 p
必须匹配 f
的 p
的特征].每个 p
都是一个虚拟数据对象,因此 12.3.2.2 变得相关:
The characteristics of a dummy data object are its type, its type parameters (if any), its shape, ... If a shape, size, or type parameter is assumed or deferred, it is a characteristic.
我们发现类型和类型参数匹配。但是,f
中的 p
具有假定的大小。 foo
中的p
没有这个匹配特征。然后,不允许在对 indirect
的调用中将 foo
与 f
相关联。 bar
.
这种要求dummy data对象的匹配特征必须具有相同的形状,自然而然会得出另外一个结论:foo
和bar
不具备作为过程的匹配特征。对于第三个程序来匹配两者的形状特征必须被忽略。
可以使用包装器子例程,但我也会考虑是否可以更改各种子例程以采用假定形状参数。这比假定大小要好得多。但是,正如您所说,我也不愿意更改该代码。
对于子例程foo
和bar
,因为您有它们,还有另一个可用的选项。这些子例程不需要调用者为它们提供显式接口 (12.4.2.2)。因此,在 indirect
中,您可以只废弃接口块:有关匹配的规则要宽松得多(12.5.2.9 的其他部分)。但是,对于其他程序,这可能是不可能的。
综上所述,ifort 似乎可以愉快地编译并且 运行 您拥有的代码...