问题
Basis: I want to write a procedure which make some operation for any input array type: integer, real(4), real(8)
, etc. The only idea i read on StackOverflow is to imitate C++ templates, using generic procedures for overriding and preprocessor for including duplicating code.
But searching for API of popular I/O software, i found this in manual:
function nf90_put_var(ncid, varid, values, start, count, stride, map)
integer, intent(in) :: ncid, varid
any valid type, scalar or array of any rank, intent(in) :: values
...
And it really works normally for every array type of every rank, passed to values
.
Question: They can't predict any rank, so they cant make explicit templates for every case. How i can build the same friendly interface?
回答1:
This is the same situation as with the MPI procedures. The key is (at least in Fortran 2008 and older) to use implicit interface to the routine. In that case no argument checking takes place and you can pass whatever you want. You have the implicit interface if the procedure is external.This is the same situation as with the MPI procedures. The key is (at least in Fortran 2008 and older) to use implicit interface to the routine. In that case no argument checking takes place and you can pass whatever you want. You have the implicit interface if the procedure is external.
Example:
subroutine store(A,count,sizeof)
use iso_fortran_env, only: int8
integer, intent(in) :: count, sizeof
integer(int8) :: A(count*sizeof)
integer :: u
!here you can treat A just as an array of count*sizeof bytes
open(newunit=u,file=out.bin,access=stream)
write(u) A
close(u)
end subroutine
program p
real :: A(5,6)
call store(A, size(A), storage_size(A(1,1))/8)
end program
When you need the explicit interface, you could (untested) do something like (not supported by many compilers, beyond Fortran 2008):
subroutine typebound(self, A, count, sizeof)
class(my_class) :: self
TYPE(*),DIMENSION(..) :: A
integer, intent(in) :: count, sizeof
!subroutine
call store(A, count, sizeof)
or use the directives which a few compilers support:
!GCC$ attributes no_arg_check::A
!DEC$ attributes no_arg_check::A
this disables the check of the arguments.
回答2:
To complement the last part of Vladimir's answer: The mpi_f08
module defines most routines with the following unportable part, which seems to suit most compilers (but most likely, not all):
!DEC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf, recvbuf
!GCC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf, recvbuf
!$PRAGMA IGNORE_TKR sendbuf, recvbuf
!DIR$ IGNORE_TKR sendbuf, recvbuf
!IBM* IGNORE_TKR sendbuf, recvbuf
(Adjust the variable names according to your needs.)
来源:https://stackoverflow.com/questions/26032511/procedure-for-any-type-of-array-in-fortran