Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Constructor for extended types

Jens_Bloch_H_
Beginner
568 Views

Hi, I'm not sure if this is a bug or a feature of 16-upd3, but I have a problem applying a constructor for extended types as demonstrated by this code:

module foo_def
    type, abstract :: foo
        real x
    end type foo
end module foo_def
    
module foo2_def
    use foo_def
    type, extends(foo) :: foo2
        real y
    end type foo2
    interface foo
        module procedure constructor
    end interface
    contains
    function constructor(x, y) result(self)
        real, intent(in)  :: x, y
        type(foo2) :: self
        self % x = 2.3
        self % y = 1.1
    end function constructor
end module foo2_def

program test
use foo_def
use foo2_def
class(foo), allocatable :: f
allocate(foo2::f)
f = foo(x, y)
print*, f%x, f%y
end program test

I get the error codes:

1>F:\test.f90(29): error #6197: An assignment of different structure types is invalid.
1>F:\test.f90(29): error #8304: In an intrinsic assignment statement, variable shall not be polymorphic.   
1>F:\test.f90(30): error #6460: This is not a field name that is defined in the encompassing structure.   

Based on above error messages I guess the compiler first deallocates f in line 29. Hence it is not of type foo2 anymore which leads to type mismatch regarding the foo2 result from the constructor. Is this a bug or a feature? Are assignments prohibited for allocated polymorphic objects? If I statically declare f to be of type(foo2) the code works as expected.

I know that constructors are not a part of Fortran but the trick of introducing a generic interface with the same name as the type name seems to be a standard trick working for all cases I have encountered except for allocated polymorphic variables. Any good work arounds?

Best regards,

Jens B. Helmers

 

 

 

0 Kudos
2 Replies
Steven_L_Intel1
Employee
568 Views

The real problem is that you're relying on a Fortran 2008 feature we don't yet support - intrinsic assignment to an allocatable polymorphic variable. This should be implemented in the next major release (second half of 2017.)

0 Kudos
FortranFan
Honored Contributor II
568 Views

@Jens B. Helmers,

Look into:

  • SOURCEd allocation facility introduced with Fortran 2003 and its caveats and advantages relative to what you're trying to do,
  • whether it makes sense to have a generic interface with the same name as that of the abstract type whose extension type is the result of the underlying function of the interface,
  • SELECT TYPE construct, for otherwise how the compiler can cast the polymorphic variable of an abstract type to access members of the dynamic type which could be any extension, and
  • what is intended for the dummy arguments in the constructor function that are not utilized nor defined in the caller.

With a few changes along the above lines, you can do the following:

module foo_def
   type, abstract :: foo
      real x
   end type foo
end module foo_def
module foo2_def
   use foo_def
   type, extends(foo) :: foo2
      real y
   end type foo2
   interface foo2
      module procedure constructor
   end interface
contains
   function constructor() result(self)
      type(foo2) :: self
      self % x = 2.3
      self % y = 1.1
   end function constructor
end module foo2_def
program test
   use foo_def
   use foo2_def
   class(foo), allocatable :: f
   allocate( f, source=foo2() )
   select type ( f )
      type is ( foo2 )
         print*, f%x, f%y
   end select
end program test

The above compiles with no errors or warnings: upon execution,

 2.300000 1.100000

 

0 Kudos
Reply