Search code examples
arraysfortran90generic-programming

How to have generic subroutine to work in fortran with assumed size array


I have an interface block to define a generic subroutine which have an assumed size array as dummy argument (in order to be able to act on 'the middle' of a passed array, like a C pointer) and it does not compile. Here is simple exemple:

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

The commented line does not compile, whereas it is ok when calling directly the subroutine with call isub(ai(2),3) (tested with gfortran and ifort). Why and is it possible to have it to work with call sub(ai(2),3)?

edit: with ifort, it says:

$ 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)

Thanks


Solution

  • You are passing a scalar to a function that is expecting an array. Try

    call sub(ai(2:2))
    

    which is passing an array of length one. I'm wondering why call isub(ai(2)) is accepted, though...

    To answer your new question (partly in the comments):

    If you restrict yourself to contiguous arrays, you can use call sub(ai(2:4)) without loss of performance using deferred shape arrays:

    subroutine isub(a)
      integer,intent(in) :: a(:)
      integer            :: i
    
      print*, 'isub'
      do i=1,size(a)
        print*, a(i)
      enddo
    end subroutine isub
    

    There are no temporary arrays created with ifort or gfortran. You can check for this using:

    • ifort -check arg_temp_created

    • gfortran -Warray-temporaries