#arrays #fortran90 #generic-programming
#массивы #fortran90 #generic-программирование
Вопрос:
У меня есть блок интерфейса для определения универсальной подпрограммы, которая имеет массив предполагаемого размера в качестве фиктивного аргумента (чтобы иметь возможность воздействовать на «середину» переданного массива, например, указатель C), и он не компилируется. Вот простой пример:
module foo
interface sub
module procedure isub
module procedure dsub
end interface
contains
subroutine isub(a,n)
integer, intent(in) :: a(*), n
integer :: i
print*, 'isub'
do i=1,n
print*, a(i)
enddo
end subroutine isub
subroutine dsub(a)
real(8), intent(in) :: a(*)
integer, intent(in) :: n
integer :: i
print*, 'dsub'
do i=1,n
print*, a(i)
enddo
end subroutine dsub
end module foo
program test
use foo
implicit none
integer :: ai(4)
real(8) :: ad(4)
ai=(/1,2,3,4/)
ad=(/1.,2.,3.,4./)
call sub(ai,3)
call sub(ad,3)
call isub(ai(2),3)
!call sub(ai(2),3)
end program test
Закомментированная строка не компилируется, тогда как это нормально при непосредственном вызове подпрограммы с call isub(ai(2),3)
помощью (проверено с помощью gfortran и ifort). Почему и возможно ли с ней работать call sub(ai(2),3)
?
редактировать: с помощью ifort в нем говорится:
$ ifort overload.f90
overload.f90(37): error #6285: There is no matching specific subroutine for this generic subroutine call. [SUB]
call sub(ai(2),3)
-------^
compilation aborted for overload.f90 (code 1)
Спасибо
Ответ №1:
Вы передаете скаляр функции, которая ожидает массив. Попробуйте
call sub(ai(2:2))
которая передает массив длиной один. Мне интересно, почему call isub(ai(2))
это принято…
Чтобы ответить на ваш новый вопрос (частично в комментариях):
Если вы ограничиваетесь непрерывными массивами, вы можете использовать call sub(ai(2:4))
без потери производительности использование отложенных массивов формы:
subroutine isub(a)
integer,intent(in) :: a(:)
integer :: i
print*, 'isub'
do i=1,size(a)
print*, a(i)
enddo
end subroutine isub
Временных массивов, созданных с ifort
помощью or, нет gfortran
. Вы можете проверить это с помощью:
-
ifort -check arg_temp_created
-
gfortran -Warray-temporaries
Комментарии:
1. Мой пример был не очень хорош (я его сейчас отредактировал), но в моем реальном приложении я не хочу передавать ни одного элемента, кроме адреса любого элемента массива вызывающего, из которого подпрограмма начнет обрабатывать, как я бы сделал с указателем C. И я не хочу использовать фрагменты, которые включают временную копию
2. Почему? Вы программируете на Fortran, а не на C ?!
3. Вы пытаетесь написать подпрограмму для массивов разных размеров (например, векторов и матриц)?
4. Вы знаете, что Fortran обычно передает аргументы по ссылке, верно? Нет необходимости в указателях на то, чего (я думаю) вы пытаетесь достичь…
5. Да, я знаю. При создании
call sub(ai(2),3))
я просто хочу передать подпрограмме isub адрес или ссылку на второй элемент ai. И я не хочу использовать предполагаемый массив формы в подпрограммах из-за проблем с производительностью (и я не могу использовать НЕПРЕРЫВНЫЙ атрибут, потому что я застрял в f95). Но это не работает…