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

Help with dynamic assignment and select type

Walt_Brainerd
Beginner
479 Views

 

 

 

 

 

 

 

 

 

 

 

I need some help figuring out this new-fangled stuff.

Version 18.0.1.156 Build 20171018

I have tried to cut down the example as much as possible.

The commented-out assignment gives a syntax error. What is wrong? (The allocate works.)

And the program prints "Vehicle". I was expecting "Car". What is wrong there?

Thanks for the help.

module vehicle_module

implicit none

   private

   type, public :: vehicle_type
      real :: weight
   end type vehicle_type

   type, public, extends(vehicle_type) :: car_type
      logical :: is_a_taxi
   end type car_type

end module vehicle_module

program test

   use vehicle_module
   implicit none
   class(vehicle_type), dimension(:), allocatable :: aa
   class(vehicle_type), allocatable :: v

!aa = [ vehicle_type :: ]
   allocate (vehicle_type :: aa(0))

   v = car_type(2000.0, .false.)
   aa = [ aa, v ]

      select type (temp_v=>aa(1))
         type is (car_type)
            write (unit=*, fmt="(a9)", advance="no") "Car:"
         class default
            write (unit=*, fmt="(a9)", advance="no") "Vehicle:"
      end select

end program test

0 Kudos
8 Replies
Steve_Lionel
Honored Contributor III
479 Views

Syntax error: This is a compiler bug - the syntax is correct (and creates an empty array of type vehicle_type). This error sounds very familiar - I thought it had been fixed a long time ago. Please report this through the Intel Online Service Center.

For your second question, different elements of an array can't have different types.  In the array constructor [aa,v], each "ac-spec" must have the same declared type and type parameters (F08 C4103). They do here - vehicle_type - and that is the type of the constructor (4.8p2)

For the assignment to v in line 27, the standard requires that the variable be "type-compatible" with the expression. The standard says: "A polymorphic entity that is not an unlimited polymorphic entity is type compatible with entities of the same declared type or any of its extensions." (4.3.1.3p4) Since car_type is an extension of vehicle_type, this is ok. This assignment reallocates v to be of car_type. But from the previous paragraph, the array constructor ends up being vehicle_type and thus the SELECT TYPE reveals that.

0 Kudos
IanH
Honored Contributor II
479 Views

The issue with the assignment statement is a compiler "bug" - the syntax for zero length array constructors for derived types is not yet supported (as of 18.0, I haven't tried the new beta yet but the ticket I raised is still open).

The dynamic type of an array constructor is the same as its declared type (F2008 4.8p4).  In the absence of a `type-spec ::` thing out the front of the element sequence, the declared type of the array constructor is the same as the declared type of the element sequence expressions (which are constrained to all have the same declared type).  In the example code, those elements have a declared type of vehicle. 

Note that all elements of an array have the same dynamic type as the array itself - array elements may only differ in value, not type or type parameters.  To store objects of differing dynamic type (or type parameters) in an array, the variation in type must occur at the level of a component of the elements in the array - you typically introduce a wrapper type with an allocatable component.

 

0 Kudos
Steve_Lionel
Honored Contributor III
479 Views

So glad to see that Ian and I agree here!

0 Kudos
IanH
Honored Contributor II
479 Views

I didn't get up early enough.

0 Kudos
Steve_Lionel
Honored Contributor III
479 Views

FWIW, the empty array bug is still there in the first 2019 beta.

0 Kudos
Walt_Brainerd
Beginner
479 Views

OK, I thought having the different types (of the class) in the same array was illegal (thanks Steve for the reference), so I first tried the wrapper scheme than IanH mentioned (see below). When it didn't work, I wandered into the weeds and produced the thing I posted above. Sorry, I should have posted the original (cut down version below). It works if the second assignment to vv is commented out. What is wrong with using a structure constructor? (This time I did look and couldn't see anything preventing this, but I don' find stuff as easily any more ... :-(). As is, the following prints "Vehicle:"

module vehicle_module

implicit none

   private

   type, public :: vehicle_type
      real :: weight
   end type vehicle_type

   type, public, extends(vehicle_type) :: car_type
      logical :: is_a_taxi
   end type car_type

   type, public :: vehicle_struct
      class(vehicle_type), allocatable :: v
   end type vehicle_struct

end module vehicle_module

program test

   use vehicle_module
   implicit none
   class(vehicle_type), allocatable :: aa
   type(vehicle_struct) :: vv

   aa = car_type(2000.0, .false.)
   vv%v = aa
   vv = vehicle_struct(aa)

   select type (temp_v=>vv%v)
      type is (car_type)
         write (unit=*, fmt="(a9)") "Car:"
      class default
         write (unit=*, fmt="(a9)") "Vehicle:"
   end select

end program test

0 Kudos
FortranFan
Honored Contributor II
479 Views

Walt Brainerd wrote:

..the original (cut down version below). It works if the second assignment to vv is commented out. What is wrong with using a structure constructor? (This time I did look and couldn't see anything preventing this, but I don' find stuff as easily any more ... :-(). As is, the following prints "Vehicle:" ..

@Walt Brainerd,

Which version of Intel Fortran compiler are you using?  With version 18.0 update 2, the code you posted prints "Car:" as you would expect it to.  Note this is when the optimization is enabled, strangely with /Od compiler option to disable optimization, the program encounters a run-time exception at the second assignment, vv = vehicle_struct(aa).  If that's what you're running into, you may want to report the problem at the Intel Online Service Center https://supporttickets.intel.com/?lang=en-US

Re: "What is wrong with using a structure constructor?" - nothing wrong with it as far as your code is concerned; reliable and robust compiler support for it is a different matter though!

0 Kudos
Walt_Brainerd
Beginner
479 Views

With two modifications to get around the bugs (in my version), my complete example works as expected.

As indicated in the first post, I have 18.1 and my license is expired :-(.

The strange thing is that when I created the example while authoring my book, I got it exactly right (with no compiler to check it).

I went astray revisiting it to see if it works and trying different ways of doing it.

Thank you for your comments that got me back on track.

0 Kudos
Reply