Daniel
Daniel

Reputation: 105

Create a user defined type that depends on one of its element

I'm trying to define a user defined type that one of its elements depends on another. This is a test code that summarises the way I tried;

module def
  type vector
    integer, parameter :: long
    real,dimension(1:long) :: vec
  end type vector
end module def

program main
  use def
  implicit none

  type(vector) :: y
  y%long = 2
  y%vec = (/1.0d0, 2.0d0/)

  print*, y

end program main

But it seems that it can't be done in this way, because when I compile it in gfortran, I have the following error:

integer, parameter :: long
                  1
Error: Attribute at (1) is not allowed in a TYPE definition
testmodule.f03:4:17:

How should this be done?

Upvotes: 0

Views: 80

Answers (1)

Rodrigo Rodrigues
Rodrigo Rodrigues

Reputation: 8576

How should this be done?

In fact, there is a pretty direct response to this question: parameterized derived type.

@HighPerformanceMark is right in saying that today (2019), despite this feature having been presented in a standard 16 years ago, it was barely and lately covered by compilers.

Although, and in fact this is the reason I decided to write this answer despite some existing questions about this matter, I want leave aside the controversy around this feature and present a sharp, ultimate suggestion: USE IT.

There are at least 5 major compilers that implemented this feature today (Cray, GNU, IBM, Intel, PGI). Most of them still have bugs, but they need to be used and, therefore, tested. Then, when/if you find a bug, please report to the vendor. Only this way this feature will break the stigma created over it and become popular.

I know we all have serious business to do and don't have time to spend with "fancy new untested stuff" and want proven, efficient, mathematically sensible solutions. That is why we chose Fortran, after all. I wouldn't had recommended it for this people (us) a few years ago, but now most implementations reached a level of usability that worths the bet, and the usage is the only way to trim the rough edges.

Parameterized derived types translate, intuitively, the real problem you described. It provides an automatic (and elegant) way to model the domain of the type, considering math and programming aspects at once. The correct syntax for your program is:

module def
  type vector(long)
    integer, len :: long
    real, dimension(long) :: vec
  end type vector
end module def

program main
  use def
  implicit none

  type(vector(2)) :: y
  y%vec = [1.0, 2.0]

  print*, y

end program main

You can find more information about it here and also all over the internet, or in you favorite Modern Fortran book.

Upvotes: 4

Related Questions