I want to overcome the lousy and non-intuitive string handling in fortran by writing a more pythonic string type, but I stumpled across a mean issue with derived-type (overloaded) assignment. The main type should look like
TYPE t_string
CHARACTER(:), ALLOCATABLE :: str
contains
...
END TYPE t_string
with its power in the derived-type procedures. Of course the new string type should be as indistinguishable from the intrinsic CHARACTER(len=*)
type as possible. Especially I want to use intrinsic routines (which use the character
type) without any extra type conversions. Therefore I defined an assignment operator between CLASS(t_string)
and CHARACTER(len=*)
. E.g. open
ing a file with the new type should look like this:
type(t_string) :: filename
filename = '...'
open(file = filename, ...)
! ^ assignment here
Since there is an assignment file=filename
between t_string
and CHARACTER(len=*)
there should be no problem in the call to open
. But I get an error due to mismatch in types.
I guess the problem is, that the assignment in the subroutine call is not really an assignment but just some syntax convention.
- Any ideas how to fix this?
- What is the reason (in term of design of the fortran language) for the "subroutine assignment" not to be a real assignment?
- I do not want to call
open(file = filename%str, ...)
Here is a mwe:
MODULE m_string
IMPLICIT NONE
SAVE
INTERFACE ASSIGNMENT(=)
MODULE PROCEDURE :: string_operator_equal_s, string_operator_equal_c
END INTERFACE ASSIGNMENT(=)
TYPE t_string
CHARACTER(:), ALLOCATABLE :: str
END TYPE t_string
CONTAINS
ELEMENTAL SUBROUTINE string_operator_equal_s(lhs,rhs)
IMPLICIT NONE
CLASS(t_string), INTENT(inout) :: lhs
CLASS(t_string), INTENT(in) :: rhs
lhs%str = rhs%str
END SUBROUTINE string_operator_equal_s
ELEMENTAL SUBROUTINE string_operator_equal_c(lhs,rhs)
IMPLICIT NONE
CLASS(t_string), INTENT(inout) :: lhs
CHARACTER(len=*), INTENT(in) :: rhs
lhs%str = rhs
END SUBROUTINE string_operator_equal_c
SUBROUTINE routine(char)
CHARACTER(len=*) :: char
END SUBROUTINE routine
END MODULE m_string
PROGRAM test
USE m_string
TYPE(t_string) :: str
CHARACTER(len=10) :: char
CALL routine(char) ! no error
CALL routine(char=str) ! error: #6633: The type of the actual argument differs from the type of the dummy argument. [STR]
END PROGRAM test
No such assignment is present. You are only using the specifier name to specify which argument of the statement you are passing (similar to keyword/named arguments in Python, but not the same).
open
is in fact not a procedure, it is a statement, but it also has its "arguments" (specifiers) distinguished by their names.Hence no derived assignment shall be invoked. You must convert to
character
yourself.