0
votes

My first question is, "Can POINTER be passed to subroutines next to INTENT?"

Although passing Fortran POINTER with INTENT(IN) or INTENT(INOUT) seems to be a common practice, the documentation of Intel for Fortran POINTER says(https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference/a-to-z-reference/o-to-p/pointer-fortran.html)

The pointer cannot be declared with the INTENT or PARAMETER attributes

which confuses me a lot.

My second question is related to following code.

I tried overloading write_matrix with write_matrix_2d - which is for 2d arrays - and write_matrix_2d_ptr - which is for 2d Fortran POINTERs.

It turned out the code fails to compile with

Ambiguous generic interface WRITE_MATRIX: previously declared specific procedure WRITE_MATRIX_2D is not distinguishable from this declaration. [WRITE_MATRIX_2D_PTR]

If I comment (1) then it complies, and runs fine ( but I suppose this is bad practice since POINTER arguments going into subroutien write_matrix_2d which expects array input.)

Is there any way to overload Fortran subroutines just by their arguments' datatype just like C/C++?

module mod_write

    implicit none

    interface write_matrix
        module procedure write_matrix_2d
(1)     !module procedure write_matrix_2d_ptr
    end interface

contains

    subroutine write_matrix_2d(a)

        implicit none
        real, intent(in) :: a(:,:)
  
        ! local variables
        integer :: i, j

        print *, "in ARRAY printing subroutine"
        do i = lbound(a,1), ubound(a,1)
            write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
        enddo
  
    end subroutine

    subroutine write_matrix_2d_ptr(a)

        implicit none
        real, pointer, intent(in) :: a(:,:)
  
        ! local variables
        integer :: i, j

        print *, "in POINTER printing subroutine"
        do i = lbound(a,1), ubound(a,1)
            write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
        enddo
  
    end subroutine

end module

program test

    use mod_write

    implicit none

    real, dimension(9)            :: b = (/21, 22, 23, 24, 25, 26, 27, 28, 29/)
    real, dimension(3,3)          :: c
    real, dimension(3,3), target  :: ct(3,3)
    real, dimension(:,:), pointer :: cptr(:,:)

    c = reshape( b, (/3, 3/) )

    write(*,*)
    write(*,*) 'c'
    call write_matrix(c)
(2) !call write_matrix_2d(c)

    ct = c
    cptr => ct(2:3,2:3)

    write(*,*)
    write(*,*) 'ct'
    call write_matrix(ct)
(2,3)!call write_matrix_2d_ptr(ct)

    write(*,*) 'cptr'
    call write_matrix(cptr)
(2) !call write_matrix_2d_ptr(cptr)

end program

My third question is again related to the attached code. Overloading is not that big a deal since I can just use write_matrix_2d and write_matrix_2d_ptr separately as (2)s in the code. But, as you can see at (3), call write_matrix_2d_ptr(ct) runs fine with the target input ct while write_matrix_2d_ptr expects pointer input. Is this okay, or should I make another write_matrix_2d_target?

Thank you.

2
Why do you need the dummy argument to be a pointer? - IanH
@IanH Currently I'm trying to import C/C++ functions into Fortran by iso_c_binding. Since there are many POINTER related stuffs in doing so, I'm just trying to figure their properties to prevent making mistakes in real practice. Apparently there's no reason I should pass arguments as POINTER, but I'm doing this kind of stuff to know what would happen if I pass arguments as POINTER and so on. - Sangjun Lee
Please ask one single question per post here, unless they are very tightly connected that they are just two points of a single question. - Vladimir F
@VladimirF I'll keep it mind next time, sorry - Sangjun Lee

2 Answers

3
votes

The compiler documentation is wrong (or badly out of date). A dummy argument that is a pointer can also have the intent attribute. The attribute applies to the pointer association status of the argument, not the target.

Procedures in a generic interface can be overloaded if their dummy arguments are distinguishable. Dummy arguments are distinguishable if they have different type, kind or rank. Whether something is a pointer or not is not part of its type. (To be complete, arguments are also distinguishable if one is a pointer without intent(in) and the other is allocatable.) The requirements for distinguishable dummy arguments for different procedures in a generic interface mean that the rules around which specific procedure a particular generic reference resolves to are very simple.

Your example of overloading would be ambiguous - it is fine to pass a(n associated) pointer actual argument to a non-pointer dummy - the actual argument designates the target of the pointer. It is also permitted to pass a non-pointer actual with the target attribute to an intent(in) pointer dummy.

Whether something is a pointer or not is completely orthogonal to whether it is an array or not.

Pointers in Fortran are primarily used to reference different things (targets) during program execution.

Dummy arguments only need to be a pointer if you need to do something inside the procedure that relates to the association status of the pointer - perhaps you want to test the association status, or associate the pointer with something else.

2
votes

(1) The intent restriction is some copy and paste error or it is in some strange context I do not understand. There was such a resteiction in Fortran 90.

(2) "but I suppose this is bad practice since POINTER arguments going into subroutien write_matrix_2d which expects array input."

There is nothing bad about passing a Fortran pointer variable as an ordinary variable. The default argument passing mechanism is that the target of thee pointer is passed using the normal non-ointer mechanism. One only uses pinter dummy arguments if one has specific reasons to do so. Most often tbat means than one works with the association status inside the subroutine. There are some other uses but you need a specific reason to declare your argument as pointer, otherwise it just complicates things.

(3) target can be passed to pointer, intent(in) in Fortran 2008.