0

Is there a way to have an argument for a subroutine have different types in different situations?

I have a simple subroutine that reads a line from a csv file and puts the value after the comma into a variable. (It does a few other things, hence making it a subroutine, but those things do not affect what I'm trying to do). Sometimes, that variable is a integer, and sometimes it is a real. Is there a way to allow the variable type to be dynamically chosen? Or set outside of the subroutine?

Obviously, I could create two different versions of my subroutine, one for ints and one for reals, but I'd like to avoid that.

I am using Intel Visual Fortran.

program myProgram

    implicit none
    integer :: fileID, variableINT
    real :: variableREAL

    open(fileID,'SomeFile.csv')

    call readerSub(fileID, variableINT)
    call readerSub(fileID, variableREAL)

    close(fileID)

end program


subroutine readerSub(fID, outvar)
    integer, intent(in) :: fID
    XXXXXXX, intent(out) :: outvar
    
    character(100)   :: line
    integer :: com_pos
    
    read(fID, "(A)")line
    com_pos = index(line, ",")
    
    read(line(pos+1:),*)outvar 
    
end subroutine

Updated with francescalus' suggestion of polymorphism. Seems to work pretty well!

subroutine readerSub(fID, outvar)
    integer, intent(in) :: fID
    class(*),intent(out) :: outvar
    
    character(100)   :: line
    integer :: com_pos
    
    read(fID, "(A)")line
    com_pos = index(line, ",")
    
    select type(outvar)
    type is(integer)
        read(line(pos+1:),*)outvar 
    type is(real)
        read(line(pos+1:),*)outvar 
    end select
    
end subroutine
MSiegmund
  • 11
  • 2
  • Do you know how generic interfaces work? Is that an acceptable solution? The subroutine must know what it is dealing with to be able to work with it (print it, read it). Some freedom could be achieved with polymorphism and user-defined IO for derived types, but it has limits. – Vladimir F Героям слава Oct 20 '21 at 17:00
  • As Vladimir F comments, perhaps _polymorphism_ is one way to handle this (contrasting with the linked question), but at some point you are going to need to work with concrete types. _Templating_ is seen by many as a way to do what you want, but Fortran has no such thing: the linked question covers similar approaches. – francescalus Oct 20 '21 at 17:16
  • You can see a related example using (unlimited) polymorphism in [this other question](https://stackoverflow.com/q/27325019/3157076). (Seeing that, you'll possibly conclude that you do want to stick to writing "different versions of [your] subroutine, one for ints and one for reals".) – francescalus Oct 20 '21 at 17:24
  • @francescalus - unlimited polymorphism actually worked out really well! I'll update my post with what I settled on. Are there any major pitfalls I'll need to watch for? For what it's worth, 'outvar' will only ever be a real or an integer. Thanks – MSiegmund Oct 21 '21 at 13:46
  • It is just a design question. Overuse of `select type` is frowned upon but if it solves your problem here, you can surely use it. Many will prefer writing two separate subroutines with a generic interface, but it is subjective to decide what is better. – Vladimir F Героям слава Oct 21 '21 at 14:12

0 Answers0