Fortran procedure pointer to subroutines in derived type

前端 未结 2 926
礼貌的吻别
礼貌的吻别 2020-12-28 11:08

In Fortran, I need a procedure pointer inside a derived type that can point to one of several subroutines. This problem seems to be common on SO:

Fortran save proced

相关标签:
2条回答
  • 2020-12-28 11:26

    Procedure pointers were not part of the standard language until Fortran 2003, so if you want to use them at all, then Fortran 95 compatibility is irrelevant.

    An internal compiler error is a error with the compiler, regardless of the source provided to the compiler.

    There is no such thing as a type bound procedure pointer. You either have a type bound procedure - which is a thing declared after the CONTAINS in a derived type construct, or you have a procedure pointer - which can be a component of a type or a stand-alone object. A procedure pointer that is a component is part of the value of an object of the derived type - it can be associated with different procedures at runtime. A type bound procedure is a fixed property of the type declaration.

    If you want a procedure pointer (or dummy procedure) to have an explicit interface, then you must provide an interface name inside the parenthesis of the procedure declaration statement.

    procedure(interface_name_goes_here) [, pointer, ...] :: thing_being_declared
    

    The interface name provided can be the name of an accessible specific procedure (including one previously declared by a different procedure declaration statement), or the name of an abstract interface.

    (If the interface name in a procedure declaration statement is a type, as it is for the component in your example code, the procedure that is declared is a function with a result of the given type, with an implicit interface.

    If the interface name in a procedure declaration statement is completely missing, the procedure that is declared may be a function or subroutine (its subsequent use in that must be consistent with one or the other) with an implicit interface.)

    So assuming you want to declare a procedure pointer component with an explicit interface to a function (contrary to the question title) with the same characteristics as add or mult in your second stretch of code:

    TYPE type_A
      PROCEDURE(the_interface), POINTER, NOPASS :: op
    END TYPE type_A
    
    ABSTRACT INTERFACE
      FUNCTION the_interface(x, y, z) RESULT(tf)
        IMPLICIT NONE
        ! function modifying arguments - poor style!!!
        INTEGER, INTENT(INOUT) :: x
        INTEGER, INTENT(IN) :: y, z
        LOGICAL :: tf
      END FUNCTION the_interface
    END INTERFACE
    

    If you want the procedure pointer to be a subroutine with an explicit interface (which is preferable to a function that modifies its arguments) - change the abstract interface appropriately.

    The dummy procedure in the init subroutine does not have to be a pointer - inside init you are not changing what the op thing references - you are merely pointing another pointer at it:

    PROCEDURE(the_interface) :: op
    

    When your dummy procedures and procedure pointers are declared with an explicit interface, I would expect a reasonable compiler to diagnose any mismatches in characteristics.

    0 讨论(0)
  • 2020-12-28 11:38

    Here's my working example:

    module obj_mod
        integer, parameter :: n = 5
    
        type obj_type
            procedure(sub_interface), pointer, nopass :: obj_sub => NULL()
        end type
    
        interface
            subroutine sub_interface(y, x)
                import n
                double precision, dimension(n) :: x, y
            end subroutine sub_interface
        end interface
    
    contains 
        subroutine sq_sub(x, y)
            double precision, dimension(n) :: x, y
            y = x ** 2
        end subroutine
    
        subroutine exp_sub(x, y)
            double precision, dimension(n) :: x, y
            y = exp(x)
        end subroutine
    
    end module 
    
    program member_subroutine
        use obj_mod
        type(obj_type) obj
        double precision, dimension(n) :: x, y
    
        x = (/ 1, 2, 3, 4, 5 /)
        write(*,*) 'x =', x
    
        obj%obj_sub => sq_sub
        call obj%obj_sub(x, y)
        write(*,*) 'y1 =', y
    
        obj%obj_sub => exp_sub
        call obj%obj_sub(x, y)
        write(*,*) 'y2 =', y
    end program member_subroutine
    
    0 讨论(0)
提交回复
热议问题