6
votes

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?

4
...how can I make sure that a is not modified elsewhere? You mean besides not using it? :D - Kyle Kanos
In Fortran 2003 there are many other possibilities. It can be a private variable with setter/getter methods. It can be a protected component... - Vladimir F

4 Answers

5
votes

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.

5
votes

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
3
votes

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.

1
votes

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.