接口中数组的形状可以匹配多个固定数组大小吗? [英] Can the shape of an array in an interface match multiple fixed array size?

查看:263
本文介绍了接口中数组的形状可以匹配多个固定数组大小吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个带有参数p的子例程,它是一个显式大小的数组,如

 子程序foo(p)
integer,dimension(2),intent(in):: p
结束子程序foo

子程序栏(p)
整数,维度(3),意图):: p
结束子程序吧

我想通过调用这两个函数一个间接的调用,但找不到一种方法来声明一个匹配foo和bar签名的接口......



在界面中使用假定的数组大小(b)




$ b $ p
接口
子程序f(p)
整数,维(*),意图(in):: p
结束子程序f
结束接口
调用f(p)
结束子程序间接

当我通过间接调用foo或bar时,编译器(gfortran 4.9.2)抱怨f的第一个参数p的形状不匹配...

p>

 整数,维(2):: pfoo 
整数,维(3):: pbar

pfoo =(/ 0,1 /)
pbar =(/ 1,2,3 /)

呼叫foo(pfoo)!直接呼叫OK
呼叫栏(pbar)

呼叫间接(foo,pfoo)!编译器抱怨foo签名
调用间接(bar,pbar)!同样的吧...

编译器错误是这样的:

 错误:假过程'f'中的接口不匹配(1):参数'p'的维1中的形状不匹配

当然,我可以修改foo和bar签名以使用假定数组大小(*)而不是固定数组大小,但是


  1. 这就像我丢失一些信息,只是为了让编译器
    快乐而不添加任何安全性

  2. >
  3. foo和bar不是我的代码,我宁愿不改变它们...


我找到了一个解决方法,但它包括为每个子例程foo和bar编写一个假定大小的包装器

 调用间接(foo_wrapper,pfoo)!编译器抱怨foo签名
间接调用(bar_wrapper,pbar)! bar同样...

子程序foo_wrapper(p)
整数,维(*),intent(in):: p
调用foo(p)
结束子程序foo_wrapper

子程序bar_wrapper(p)
整数,维(*),意图(in):: p
调用栏(p)
结束子程序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是否是正确的抱怨,并且无论如何,有什么选择来解决抱怨。


    12.5.2.9确实很重要。
  1. 如果伪过程的接口是显式的,则作为过程(12.3.1)的特征应与其有效参数的特征相同,除了[不适用的东西]


f 间接是一个具有显式接口的虚拟过程(通过接口块; 12.4.2.1)。查看参考文献12.3.1,我们看到


过程的特点是,它的虚拟参数的特性,...


foo bar f 都是具有单个伪参数的过程(所有这些过程都巧合地称为 p )。因此,如果 foo 想要成为与 f 相关的有效参数,那么 foo ' p 必须匹配 f p 。每个 p 都是一个虚拟数据对象,所以12.3.2.2变得相关:


虚拟数据对象的特征是它的类型,它的类型参数(如果有的话),它的形状......如果一个形状,大小或类型参数被假定或推迟,它就是一个特征。


我们知道类型和类型参数是匹配的。但是, f 中的 p 的大小已假定。 p foo 中没有此匹配特征。因此,不允许在调用间接 foo 时将 f / code>。这同样适用于 bar



虚拟数据对象具有相同形状自然导致另一个结论: foo bar 与过程没有匹配的特征。对于第三种匹配形状特征的程序必须忽略。

使用包装子程序是可能的,但我也想想是否可以更改各种子程序采取假设性的论点。这比假设大小好得多。但是,正如你所说,我也不愿意改变这些代码。



对于子程序 foo bar 就像您拥有它们一样,还有另一个可用选项。这些子程序没有任何要求调用者为它们提供明确的接口(12.4.2.2)。因此,在间接中,您可以取消接口块:关于匹配的规则要放松得多(12.5.2.9的其他部分)。然而,对于其他程序来说,这可能是不可能的。



尽管如此,ifort似乎很乐意编译和运行代码,

I have multiple subroutines with a parameter p which is an array of explicit size like

subroutine foo(p)
integer,dimension(2),intent(in) ::p
end subroutine foo

subroutine bar(p)
integer,dimension(3),intent(in) ::p
end subroutine bar

I'd like to call these two functions through an indirect call, but could not find a way to declare an interface that matches both foo and bar signature...

Using an assumed array size in the interface for example does not work:

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

When I invoke foo or bar thru indirect, the compiler (gfortran 4.9.2) complains about shape mismatch for first argument p of f...

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...

Compiler error is something like:

Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'p'

Of course, I could modify foo and bar signature to use assumed array size (*) instead of fixed array size, but

  1. it's like I'm loosing some information just for making the compiler happy without adding any kind of security

  2. foo and bar are not my code and I'd rather not change them...

I've found a workaround, but it consist of writing an assumed size wrapper for each subroutine foo and 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

or eventually, replacing all assumed size by deferred size in indirect and wrapper, so as to give a chance to runtime checks, also works, but that's not the point...

The point is, since I have many such foo/bar isn't there a way to declare the interface properly (I mean without wrappers or other artefacts).

I couldn't decipher the standard (I used http://www.j3-fortran.org/doc/year/10/10-007.pdf - I presume it's around 12.5.2.9 Actual arguments associated with dummy procedure entities §2), so I don't know if it's a limitation of gfortran. Right now i haven't any other compiler available, but I'd like to know if some other compiler would compile (intel? - I'm on windows 7 64 bits).

解决方案

I'll look at whether gfortran is correct to complain and, regardless, what options there are to work around the complaint. References are to Fortran 2008.

12.5.2.9 is indeed important.

  1. 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 is a dummy procedure with an explicit interface (through the interface block; 12.4.2.1). Looking at the reference 12.3.1 we see

The characteristics of a procedure are .. , the characteristics of its dummy arguments, ..

foo, bar and f are all procedures with a single dummy argument (all called p, by coincidence). So, if foo wants to be the effective argument associated with f then foo's p must match the characteristics of f's p. Each p is a dummy data object, so 12.3.2.2 becomes relevant:

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.

We have that the type and type parameters match. However, p in f has its size assumed. p in foo does not have this matching characteristic. It is, then, not allowed to associate foo with f in the call to indirect. The same holds for bar.

This requirement for matching characteristics of the dummy data objects to have the same shape also leads naturally to another conclusion: foo and bar don't have matching characteristics as procedures. For a third procedure to match both the shape characteristic must be ignored.

Using a wrapper subroutine is possible, but I'd also think about whether I could change the various subroutines to take assumed-shape arguments. This is much better than assumed-size. But, as you say, I'd also be reluctant to change that code.

For the subroutines foo and bar as you have them, there is another available option. Nothing about those subroutines requires a caller to have an explicit interface for them available (12.4.2.2). So, in indirect you could just scrap the interface block: the rules about matching are much more relaxed (other parts of 12.5.2.9). For other procedures this may not be possible, though.

All that said, ifort appears to happily compile and run the code as you have it...

这篇关于接口中数组的形状可以匹配多个固定数组大小吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆