Sine
Sine

Reputation: 45

Derived-type custom constructor not being called in Fortran

I'm trying to make a custom data-type constructor by overloading the type name. However, when making the call, the default constructor gets called instead. I cannot understand what I am doing wrong.

Here's a code snippet that has the problem.

    module test

    type, public :: foo
        character(512)   ::  str
        logical          ::  flag1
        logical          ::  flag2
    end type

    ! overload foo data-type
    interface foo
        module procedure make_foo
    end interface

    contains

    ! custom constructor
    function make_foo(str, flag1) result(self)
        implicit none
        type(foo)  ::  self
        character(512), intent(in)      :: str
        logical, intent(in), optional   :: flag1

        self % str  = str       ! this needs to be passed

        self % flag1 = .false.  ! this needs to be optional, and is false by default
        if (present(flag1)) self % flag1 = flag1

        self % flag2 = .false.  ! this cannot be passed and is always false by default

    end function

end module

program tmp
    use test
    implicit none 
    type(foo) :: a

    a = foo("hello") ! error here
end program

I want to have a custom constructor that requires str to be passed, that allows for the optional specification of flag1 and that deals with flag2 always by itself. When testing the data-type using its constructor, it uses the default constructor and it complains for missing components.

No initializer for component 'flag1' given in the structure constructor at (1)

I am using gfortran 10.2.0

Upvotes: 3

Views: 196

Answers (1)

francescalus
francescalus

Reputation: 32366

The assignment statement

a = foo("hello")

is taken to be a reference to the generic foo if possible, and a reference to the default structure constructor for the type foo otherwise.

In the case here, the generic foo has one specific interface: make_foo. For reference to the generic foo we need foo("hello") to be consistent with make_foo.

The dummy argument str is declared as character(512) and so we are not allowed to reference it with actual argument the literal constant "Hello": that constant is (much) too short.1

The compiler falls back to the default structure constructor, and then (rightly) complains that there are components without default initialization which haven't been given values.

This reference can be fixed in one of two ways:

  • provide an actual argument of length at least 512
  • make str shorter, or better, assumed length

To address a concern about assumed length str: even if it's length 5, it still can be used in the assignment self%str = str as it will be padded with blanks at the end to make its length up to the 512 of self%str.


Whether that's strictly sufficient to deem the reference "inconsistent" is irrelevant: in trying to do this one doesn't have a Fortran program, so one can't demand the compiler tries that reference.

Upvotes: 3

Related Questions