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.
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.
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.
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.