Using user-defined derived type assignments in subroutine calls

117 Views Asked by At

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

There are 1 best solutions below

6
On BEST ANSWER

Since there is an assignment file=filename between t_string and CHARACTER(len=*) there should be no problem in the call to open.

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.