Может ли форма массива в интерфейсе соответствовать нескольким фиксированным размерам массива?

У меня есть несколько подпрограмм с параметром р, который является массивом явного размера, как

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 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) жалуется на несоответствие формы для первого аргумента 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...

Ошибка компилятора выглядит примерно так:

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

Конечно, я мог бы изменить подпись foo и bar, чтобы использовать предполагаемый размер массива (*) вместо фиксированного размера массива, но

  1. как будто я теряю некоторую информацию только для того, чтобы сделать компилятор счастливым, не добавляя никакой защиты

  2. 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. Прямо сейчас у меня нет другого доступного компилятора, но я хотел бы знать, скомпилируется ли другой компилятор (intel? - Я на Windows 7 64 бит).

1 ответ

Решение

Я посмотрю, правильно ли gfortran жаловаться и, независимо от того, какие есть варианты, чтобы обойти жалобу. Ссылки на Фортран 2008.

12.5.2.9 действительно важно.

  1. Если интерфейс фиктивной процедуры является явным, его характеристики как процедуры (12.3.1) должны быть такими же, как у ее эффективного аргумента, за исключением того, что [неприменимые вещи]

f в indirect является фиктивной процедурой с явным интерфейсом (через блок интерфейса; 12.4.2.1). Глядя на ссылку 12.3.1 мы видим

Характеристики процедуры:.., характеристики ее фиктивных аргументов,..

foo, bar а также f все процедуры с одним фиктивным аргументом (все они называются p, по стечению обстоятельств). Так что если foo хочет быть эффективным аргументом, связанным с f затем foo"s p должны соответствовать характеристикам f"s p, каждый p является фиктивным объектом данных, поэтому 12.3.2.2 становится релевантным:

Характеристики фиктивного объекта данных - это его тип, параметры его типа (если есть), его форма,... Если предполагается, что параметр формы, размера или типа задан или отложен, это характеристика.

У нас есть, что тип и параметры типа совпадают. Тем не мение, p в f имеет предполагаемый размер. p в foo не имеет этой характеристики соответствия. Таким образом, не разрешается связывать foo с f в призыве к indirect, То же самое относится и к bar,

Это требование для сопоставления характеристик фиктивных объектов данных, имеющих одинаковую форму, также естественно приводит к другому выводу: foo а также bar не имеют соответствующих характеристик в качестве процедур. Чтобы третья процедура соответствовала обеим характеристикам формы, ее следует игнорировать.

Возможно использование подпрограммы-обертки, но я бы также подумал о том, могу ли я изменить различные подпрограммы для принятия аргументов предполагаемой формы. Это намного лучше, чем предполагаемый размер. Но, как вы говорите, я бы тоже не хотел менять этот код.

Для подпрограмм foo а также bar как у вас есть, есть еще один доступный вариант. Ничто в этих подпрограммах не требует, чтобы вызывающая сторона имела явный интерфейс для них (12.4.2.2). Итак, в indirect Вы можете просто удалить интерфейсный блок: правила сопоставления гораздо более мягкие (другие части 12.5.2.9). Однако для других процедур это может быть невозможно.

Все, что сказал, ifort, кажется, счастливо скомпилировать и запустить код, как у вас есть...

Другие вопросы по тегам