问题
I'm trying to write a routine that is able to convert a string into different kinds of data type, based on unlimited polymorphism. The idea is the user call this routine, passing the variable where it wants to store the data, and the routine to define the conversion based on the variable/argument type.
An excerpt of this routine is here:
subroutine GetAsScalar (this, value, status)
!Arguments-------------------------------------------------------------
class(TKeyword) :: this
class(*) :: value
logical, optional :: status
!Local-----------------------------------------------------------------
integer :: stat
!----------------------------------------------------------------------
stat = 0
select type (value)
type is (REAL(real32)) !single precision
read (this%fValue, *, IOSTAT = stat) value
type is (REAL(real64)) !double precision
read (this%fValue, *, IOSTAT = stat) value
type is (LOGICAL)
read (this%fValue, *, IOSTAT = stat) value
type is (INTEGER(int32)) !integer
read (this%fValue, *, IOSTAT = stat) value
type is (INTEGER(int64)) !long integer
read (this%fValue, *, IOSTAT = stat) value
type is (CHARACTER(*))
value = this%fValue
class default
this%Message = "Invalid data type"
status = .false.
return
end select
if (present (status)) then
if (stat /= 0) then
status = .false.
else
status = .true.
endif
endif
end subroutine GetAsScalar
"this%fValue" is a "character(len=:), allocatable" string. When I try to use this routine passing an allocatable string, it exit with success, no error/exceptions raise:
character(len=:), allocatable :: value
call keyword%GetAsScalar(value)
But the string "value" is always empty. Even inside the routine, after the assign "value = this%fValue", value is empty (len(value) is 0).
It seems that the compiler is unable to detected that the argument is of type character(len=:), allocatable, and so, is unable to assign the value to it.
Of course I have some alternatives, but the idea of being able to use a single rountine and without optional arguments for different kind of data is really nice.
I can use a user defined type that I create to handle strings, for example.
But I would like to know if this is the default behaviour in Fortran 2008. And also, if there is a way to accomplish this, using this routine, with a single "class(*)" dummy argumment, to convert different types including the referred allocatable character. There is a way to force the allocation inside the routine, for example?
I'll appreciate your comments. Cheers, Eduardo
回答1:
In a select type (or associate) construct, the associate name never has the allocatable attribute (16.5.1.6p2), regardless of whether the select has that attribute.
In your case, the selector is also lacking that attribute - the value
dummy argument is not declared to be allocatable. You are not permitted to associate an unallocated actual argument with a non-optional non-allocatable dummy argument. Beyond that, you are not permitted to use an unallocated selector in a select type or associate construct.
You need to allocate the value
actual argument to some length before the call, the value
associate name will then have that fixed length inside the select type construct. Alternatively, wrap the allocatable character variable as a component in a derived type.
来源:https://stackoverflow.com/questions/27693240/passing-an-allocatable-character-to-a-subroutine-with-unlimited-polymorphic-dumm