Search code examples
fortranintel-fortran

Missing actual argument when calling a subroutine with optional arguments


My IDE is Visual Studio 2010 with integrated Intel Fortran compiler. The version of compiler is: Intel Parallel Studio XE 2011.

I am not experienced programer in Fortran so I need a little help about using optional argument in public procedure from derived type. This is my example code:

MODULE DERIVED_TYPE

 TYPE , PUBLIC :: SOME_TYPE

  INTEGER , PRIVATE :: V_INT

   CONTAINS

      PROCEDURE , PUBLIC :: CALL_V_INT => CALL_DATA_V_INT
      PROCEDURE , PUBLIC :: TAKE_V_INT => TAKE_DATA_V_INT

 END TYPE SOME_TYPE

 PRIVATE :: CALL_DATA_V_INT
 PRIVATE :: TAKE_DATA_V_INT

CONTAINS

! PUBLIC PROCEDURES

  SUBROUTINE CALL_DATA_V_INT( THIS , IA , IB , IC )

    CLASS( SOME_TYPE ) :: THIS
    INTEGER , INTENT( IN ) :: IA , IC
    INTEGER , INTENT( IN ) , OPTIONAL :: IB

    IF( .NOT. PRESENT( IB ) ) THEN

        THIS%V_INT = IA + IC

    ELSE

        THIS%V_INT = IA + IB + IC

    END IF

  END SUBROUTINE CALL_DATA_V_INT

  FUNCTION TAKE_DATA_V_INT ( THIS ) RESULT( RES )

    CLASS( SOME_TYPE ) :: THIS
    INTEGER :: RES

    RES = THIS%V_INT

  END FUNCTION TAKE_DATA_V_INT

END MODULE DERIVED_TYPE

PROGRAM OPTIONAL_ARG

USE , NON_INTRINSIC :: DERIVED_TYPE

IMPLICIT NONE

INTEGER :: I
INTEGER , PARAMETER :: N = 3

CLASS( SOME_TYPE ) , POINTER :: P_SOME_TYPE

TYPE( SOME_TYPE ) , DIMENSION( N ) , TARGET :: ARR_V_INT

DO I = 1 , N

   P_SOME_TYPE => ARR_V_INT( I )

   CALL P_SOME_TYPE%CALL_V_INT( I , 5 )

   WRITE( * , * ) P_SOME_TYPE%TAKE_V_INT()

END DO

END PROGRAM OPTIONAL_ARG

At the end of compiling proces i got this kind of message in build window: Missing actual argument for argument 'ic'

What is wrong with this example?

I also try to move optional argument to latest position in argument list and in that case there is no error message.

Can I get detail explanation for optional argument position in argument list?


Solution

  • You should normally try to put optional arguments at the end of the argument list. What happens when you do call such as

      subroutine sub (a, b, c)
        real :: a, c
        real, optional :: b
    
      ...
    
      call sub(1.,2.)
    

    is that the compiler must assume that the 1. is for a and the 2. is for b. Then the argument for c is missing.

    Instead one can use named arguments after the missing optional one

      call sub(1, c=2.)
    

    So in your case you could do

    CALL P_SOME_TYPE%CALL_V_INT( I , IC = 5 )
    

    if you don't want to have the optional IB at the end of the argument list.