Named constants as components of a derived data type
Asked Answered
A

4

6

It seems Fortran 90 does not allow named constants in derived data types. Is this true? The following code does not work.

program my_prog
implicit none
   type :: my_type
      integer, parameter :: a = 1
      real(kind(1.d0))   :: b
   end type my_type
   type (my_type) :: complex_type
end program my_prog

The compiler says parameter statement is not permitted in derived type definitions.

When I remove the parameter keyword everything works fine. But then how can I make sure that the component a is not modified elsewhere?

Aborn answered 6/10, 2013 at 22:11 Comment(2)
...how can I make sure that a is not modified elsewhere? You mean besides not using it? :DNeelon
In Fortran 2003 there are many other possibilities. It can be a private variable with setter/getter methods. It can be a protected component...Grandmamma
H
5

Make the constant (the parameter) a local entity of the main program rather than the type. If you want more control over the visibility and scope of the identifier for the constant, then put the constant in a module.

Hyperspace answered 6/10, 2013 at 23:24 Comment(2)
Thank you. you are offering alternative solutions which solves my problem. Can you orate a yay or nay on the parameter construct not being allowed inside a derived data type? Need a conformation to know that it is not compiler specific.Aborn
It is a direct consequence of the rules of the language. It is not compiler specific.Hyperspace
T
5

According to the Standard, it is not allowed. The component attribute specifier may only be pointer, and dimension for Fortran 90/95 (section 4.4.1), additionally allocatable in Fortran 2003 (Section 4.5.3), and additionally codimension, and contiguousfor Fortran 2008 (section 4.5.4.1).

You can get the documents here.

I ran into a similar problem with the target specifier, that is also not allowed.

EDIT: Why not try private components?

module typedef
  type :: my_type
    integer, private :: a_int = 1
    real(kind(1.d0)) :: b
  contains
    procedure :: a
  end type my_type

contains
  function a(complex_type)
    class(my_type),intent(in) :: complex_type
    integer :: a
    a = complex_type%a_int
  end function
end module

program my_prog
  use typedef
  implicit none

  type (my_type) :: complex_type

  complex_type%b = 2.d0 ! This should work
  write(*,*) complex_type%a(), complex_type%b

!  complex_type%a_int = 3    ! This should fail

end program my_prog
Testy answered 7/10, 2013 at 9:27 Comment(2)
Great! private is the way to go. Just one clarification. In your code code above 'class(my_type), intent(in) :: complex_type' should instead say 'type(my_type), intent(in) :: complex_type'. In Fortran 90 at least!Aborn
Starting with Fortran 2003 the dummy argument shall be polymorphic (4.3.1.3) if and only if the type being defined is extensible (my_type is extensible). So using type instead of class will produce an error when using Fortran 2003 and higher.Testy
G
3

The question is: Why do you want to do this?

Imagine, you want to create an array of 1000 values my_type. The result would be, that the value of a would have been stored 1000 times. This is a waste of nearly 4kb of memory (assuming int4). The better way would be to define the parameter in an according module.

Btw, in the book Modern Fortran from Clerman and Spector, rule number 133 states, that you should define every derived type in its own module. This would be a great place for such a constant.

Greenwald answered 7/10, 2013 at 12:1 Comment(1)
I will not have more than one copy. I am using it the way you'd use enumerate in c. I have a system of differential equations. Instead of referring to the vector as 'Y(0), Y(1)' etc. I want to refer to them as 'Y(var1), Y(var2)' and so on. 'var1, var2' and so on will be constant parameters in the new type data type.Aborn
C
1

You can define it as private and produce a get() function, but not a set() function. In this way your data will be well encapsulated.

Christi answered 1/7, 2014 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.