Jim
Jim

Reputation: 11

Conditional fortran record variable selection

I have a structure defined:

STRUCTURE /IOA/
  INTEGER*2 ID
  .....
END STRUCTURE

I need to create another structure, IOB. IOB contains all the same fields as IOA but with many more.

STRUCTURE /IOB/
  INTEGER*2 ID
  .....
END STRUCTURE

My program currently has:

RECORD /IOA/ A
RECORD /IOB/ B

The program will either use A or B depending on a user input.

Is there any way to have some sort of conditional in the code to use A or B depending on what's required? For example, is it possible to create a placeholder record (variable?) "IO" and define it based on the input?:

If user input = 1, IO = A
else IO = B
.....

IO.ID = 30

Thank you.

Upvotes: 1

Views: 106

Answers (2)

That's what polymorphism in modern Fortran (2003 and further) is for.

   use iso_fortran_env, only: int16

   implicit none

    type IOA
      integer(int16) :: ID
    end type


    type, extends(IOA) :: IOB
      integer :: extendedID
    end type

    class(IOA), allocatable :: IO

    integer :: user_input = 2

    if (user_input == 1) then
      allocate(IOA :: IO)
    else
      allocate(IOB :: IO)
    end if

    IO%ID = 30

    select type (IO)
      type is (IOB)
        IO%extendedID = 42
      class default !just an illustration
        continue
    end select
end

You can't do this with the obsolete DEC extensions STRUCTURE and RECORD. A advise against using these extensions. They are not part of standard Fortran.

Upvotes: 3

Jack
Jack

Reputation: 6158

My recommendation is to make the type IO_TYPE in a module, and have it contain a POINTER to a type with the extra stuff you may or may not need:

MODULE IO_TYPES
  TYPE EXTRA_STUFF
     INTEGER :: AGE
     INTEGER :: HEIGHT
     INTEGER :: WIEGHT
  END type EXTRA_STUFF
  TYPE IO_TYPE
     INTEGER :: ID
     TYPE(EXTRA_STUFF), POINTER :: EXT
  END type IO_TYPE

END MODULE IO_TYPES

Then, in your program, which will have USE IO_TYPES, of course, you can decide whether to allocate that pointer:

TYPE (IO_TYPE) :: IO
INTEGER        :: IERR_ALLOC

IF ( USER_INPUT .EQ. 1 ) ALLOCATE( IO%EXT, STAT=IERR_ALLOC )
IF ( IERR_ALLOC .NE. 0 ) STOP 1

(Always check the results of ALLOCATE statements.)

Upvotes: 0

Related Questions