Именованные константы как компоненты производного типа данных

Кажется, Fortran 90 не позволяет использовать именованные константы в производных типах данных. Это правда? Следующий код не работает.

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

Компилятор говорит, что оператор параметра не разрешен в определениях производных типов.

Когда я удаляю ключевое слово parameter, все работает нормально. Но тогда как я могу убедиться, что компонент a нигде не изменен?


person user1318806    schedule 06.10.2013    source источник
comment
... как я могу убедиться, что a нигде не изменено? Вы имеете в виду, кроме как не использовать его? :D   -  person Kyle Kanos    schedule 07.10.2013
comment
В Fortran 2003 есть много других возможностей. Это может быть частная переменная с методами установки/получения. Это может быть защищенный компонент...   -  person Vladimir F    schedule 07.10.2013


Ответы (4)


Сделайте константу (параметр) локальным объектом основной программы, а не типом. Если вы хотите больше контролировать видимость и область действия идентификатора константы, поместите константу в модуль.

person IanH    schedule 06.10.2013
comment
Спасибо. вы предлагаете альтернативные решения, которые решают мою проблему. Можете ли вы сказать «да» или «нет» по поводу того, что конструкция параметра не разрешена внутри производного типа данных? Нужна конформация, чтобы знать, что это не зависит от компилятора. - person user1318806; 07.10.2013
comment
Это прямое следствие правил языка. Это не зависит от компилятора. - person IanH; 07.10.2013

По Стандарту это не допускается. Спецификатор атрибута компонента может быть только pointer и dimension для Fortran 90/95 (раздел 4.4.1), дополнительно allocatable в Fortran 2003 (раздел 4.5.3) и дополнительно codimension и contiguous для Fortran 2008 (раздел 4.5.4.1).

Вы можете получить документы здесь.

Я столкнулся с аналогичной проблемой со спецификатором target, который также не разрешен.

РЕДАКТИРОВАТЬ: Почему бы не попробовать компоненты private?

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
person Alexander Vogt    schedule 07.10.2013
comment
Большой! частный путь. Всего одно уточнение. В вашем коде выше «класс (мой_тип), намерение (в) :: сложный_тип» вместо этого должен говорить «тип (мой_тип), намерение (в) :: сложный_тип». По крайней мере, на Фортране 90! - person user1318806; 08.10.2013
comment
Начиная с Fortran 2003, фиктивный аргумент должен быть полиморфным (4.3.1.3) тогда и только тогда, когда определяемый тип является расширяемым (my_type является расширяемым). Таким образом, использование type вместо class приведет к ошибке при использовании Fortran 2003 и выше. - person Alexander Vogt; 08.10.2013

Вопрос: зачем вы хотите это сделать?

Представьте, вы хотите создать массив из 1000 значений my_type. В результате значение a было бы сохранено 1000 раз. Это пустая трата почти 4 КБ памяти (при условии, что int4). Лучшим способом было бы определить параметр в соответствующем модуле.

Кстати, в книге Modern Fortran от Клермана и Спектора правило номер 133 гласит, что вы должны определять каждый производный тип в своем собственном модуле. Это было бы отличным местом для такой константы.

person Stefan    schedule 07.10.2013
comment
У меня не будет больше одного экземпляра. Я использую его так же, как вы использовали бы enumerate в c. У меня есть система дифференциальных уравнений. Вместо того, чтобы называть вектор «Y (0), Y (1)» и т. д., я хочу называть их «Y (var1), Y (var2)» и т. д. 'var1, var2' и т. д. будут постоянными параметрами в новом типе данных. - person user1318806; 08.10.2013

Вы можете определить его как частный и создать функцию get(), но не функцию set(). Таким образом, ваши данные будут хорошо инкапсулированы.

person user3795362    schedule 01.07.2014