Может ли форма массива в интерфейсе соответствовать нескольким фиксированным размерам массива?
У меня есть несколько подпрограмм с параметром р, который является массивом явного размера, как
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, чтобы использовать предполагаемый размер массива (*) вместо фиксированного размера массива, но
как будто я теряю некоторую информацию только для того, чтобы сделать компилятор счастливым, не добавляя никакой защиты
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 действительно важно.
- Если интерфейс фиктивной процедуры является явным, его характеристики как процедуры (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, кажется, счастливо скомпилировать и запустить код, как у вас есть...