Chang
Chang

Reputation: 416

User defined constructor for Fortran derived type instance

This is my second question related to Fortran (I use C++, so forgive me my way of thinking).

I want to use OOP, to say, derived type in Fortran whenever appropriate. In C++, you can use user defined constructor such as https://msdn.microsoft.com/en-us/library/s16xw1a8.aspx

Here in Fortran, things are different. The first thing I tried is from here: https://www.ibm.com/developerworks/community/blogs/b10932b4-0edd-4e61-89f2-6e478ccba9aa/entry/object_oriented_fortran_user_defined_constructors2?lang=en

Link is broken, so I pasted it here:

module m
  !...
  interface base
    module procedure new_base
  end interface

contains
  !...
  function new_base(I)
    integer, intent(in) :: I
    type(base) new_base

    allocate(new_base%data(I))
    new_base%data = I
  end function
  !...
end module

The interface above defines a user-defined constructor for type base. It is used in a similar way to a structure constructor. It can even take argument keywords.

Then I found some other ways to do it. Here I listed a few approaches seemly to work but I only tested the first and second:

  1. generic interface with the same name as the derived type they're supposed to construct, see link above;

  2. use type-bound procedure (This is not even a "traditional" constructor)

    MODULE mymod
      TYPE mytype
        Private
        INTEGER :: x
        CONTAINS
        PROCEDURE, PASS :: init
      END TYPE
    CONTAINS
      SUBROUTINE init(this, i)
        CLASS(mytype), INTENT(OUT) :: this
        INTEGER, INTENT(IN) :: i
        write(*,*) this%x
        IF(i > 0) THEN
          this%x = 1
        ELSE
          this%x = 2
        END IF
        write(*,*) this%x
      END SUBROUTINE init
    END
    PROGRAM test
      USE mymod
      TYPE(mytype) :: y
      CALL y%init(1)
    END PROGRAM
    
  3. use Static Constructors or Structure Constructors (http://www.lahey.com/docs/lfenthelp/NLMOvUsInvConst.htm) But it appears that this is NOT for general Fortran http://www.lahey.com/docs/lfenthelp/NLMGSWhatIs.htm

So I haven't understood well enough what is most preferred and flexible approach to initialize/construct a derived type in practice, especially when I use nested derived type in development. I hope I can organize this topic with some help.

Upvotes: 8

Views: 5673

Answers (1)

OK, so I will assume you read well the answers at How to override a structure constructor in fortran and I will answer your problem raised in the comment. There is not enough place in the comment to answer that.

You can also make constructors in Fortran which accept variable number of arguments.

It is even possible with the default structure constructors which every derived type has by default. If you default-initialize a component, it is optional in the constructor. The same holds for allocatable and pointer components.

For type

type t1
  integer :: i = 1
  integer, pointer :: ip => null()
  integer, allocatable :: ap
end type

you can call the default constructor just as

instance = t1()

and it is perfectly legal, i will be 1, ip will point to null and ap will not be allocated.

Or you can call it as

 instance = t1(ap=5)

and the ap component will be allocated and set to 5 and the other components will be left default.


You can achieve similar stuff with user defined constructors just by making the arguments optional.

function t1_user(ap, i) result(res)
  type(t1) :: res
  integer, allocatable :: ap !this argument MUST be passed,
                             ! it does not have to be allocated
  integer, optional    :: i ! this argument is optional

  if (present(i)) then
    ...
  end if
end function

any type-bound procedure can of-course also have optional arguments.


As for the nested types, that is really best done with constructors as functions, no matter if they are default or user defined:

type inner
  real :: x, y
end type

type outer
  type(inner), allocatable :: in
  real :: z
end type

instance1 = outer(inner(1., 2.), 3.)

instance2 = outer(z=4.)

Upvotes: 8

Related Questions