Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Function Overload

Blane_J_
New Contributor I
318 Views

Hi, everyone. There is a problem a I'm not quite understand about optional dummy argument. Here is the code:

MODULE Test
    IMPLICIT NONE

    TYPE :: MyType
        INTEGER :: a
    CONTAINS
        GENERIC, PUBLIC :: Set => SetBy2Arguments,&
                                  SetBy3Arguments
        PROCEDURE, PASS :: SetBy2Arguments
        PROCEDURE, PASS :: SetBy3Arguments
    END TYPE MyType

    CONTAINS

    FUNCTION SetBy2Arguments(this, arg1, arg2)
        IMPLICIT NONE

        INTEGER :: SetBy2Arguments
        CLASS(MyType), INTENT(IN) :: this
        INTEGER,       INTENT(IN) :: arg1
        INTEGER,       INTENT(IN) :: arg2

        SetBy2Arguments = this%a + arg1 + arg2

        RETURN
    END FUNCTION SetBy2Arguments

    FUNCTION SetBy3Arguments(this, arg1, arg2, arg3)
        IMPLICIT NONE

        INTEGER :: SetBy3Arguments
        CLASS(MyType),     INTENT(IN) :: this
        INTEGER,           INTENT(IN) :: arg1
        INTEGER,           INTENT(IN) :: arg2
        INTEGER, OPTIONAL, INTENT(IN) :: arg3

        SetBy3Arguments = this%a + arg1 + arg2 + arg3

        RETURN
    END FUNCTION SetBy3Arguments

END MODULE Test

When compiling, The compiler generates a warning message saying that:

warning #8449: The type/rank/keyword signature for this specific procedure matches another specific procedure that shares the same generic binding name.   [SETBY3ARGUMENTS]

So why are these 2 binding procedures matches each other ? And How is the compiler treat a dummy argument that has an OPTIONAL attribute ? Appriciate any replies, thanks.

0 Kudos
3 Replies
mecej4
Honored Contributor III
318 Views

Consider a call to SET(arg1, arg2, arg3) from some other part of your code. How does the compiler know whether to direct the call to SetBy2Arguments or to SetBy3Arguments? By looking at the number and types of the actual arguments used. If the optional argument is left out, the remaining three arguments of the latter match exactly with the three arguments of the former. Therefore, the compiler would not be able to decide which to choose -- there would be an ambiguity that it could not resolve.

0 Kudos
IanH
Honored Contributor II
318 Views

Given the following code:

TYPE(MyType) :: x
PRINT *, x%Set(1, 2)

which specific binding and procedure do you expect to be invoked?  Is it going to be `SetBy2Arguments`with all of its arguments, or is if going to be `SetBy3Arguments` with the last optional argument missing?

 

 

The two specific bindings are not distinguishable, hence this is not permitted.

Optional arguments are arguments that don't have to be present when the procedure is invoked.  Inside a procedure with an optional argument, you can test whether the argument was present or not using the PRESENT intrinsic.  If the actual argument was present, then the dummy argument is pretty much just like a normal argument.  If the actual argument was not present, then you cannot define or reference the dummy argument, bar using it as the argument to PRESENT, or passing it on as an actual argument to another procedure with a corresponding optional argument.

If the actual argument corresponding to `arg3` was not present in a call to `SetBy3Arguments`, then your code has a problem, as you are including it in the sum regardless of whether the actual argument is present or not.  Correct handling of an optional argument would be something like:

    FUNCTION SetBy3Arguments(this, arg1, arg2, arg3)
        INTEGER :: SetBy3Arguments
        CLASS(MyType),     INTENT(IN) :: this
        INTEGER,           INTENT(IN) :: arg1
        INTEGER,           INTENT(IN) :: arg2
        INTEGER, OPTIONAL, INTENT(IN) :: arg3

        IF (PRESENT(arg3)) THEN
          ! arg3 is present, we can reference it.
          SetBy3Arguments = this%a + arg1 + arg2 + arg3
        ELSE
          ! arg3 is not present, don't touch it!
          SetBy3Arguments = this%a + arg1 + arg2
        END IF
    END FUNCTION SetBy3Arguments

Edit: mecej4 beat me to it, but I enjoy hearing the sound of my own keyboard.

0 Kudos
Blane_J_
New Contributor I
318 Views

Thank you all, lanH and mecej4. now I quite understand the compiler's behavior.

PS: I was intended to use the PRESENT intrinsic but only to find it was missing when I've posted. Thanks for your remind, lanH.

0 Kudos
Reply