Фортран производные типы

Мне было интересно, возможно ли каким-то образом определить производный тип в Fortran, который автоматически возвращает правильный тип, без специального вызова типа, например. var%real? Вот пример, чтобы объяснить, что я имею в виду:

module DervType

  implicit none

  type, public :: mytype
    real(8) :: r
    integer :: i
    logical :: l
  end type

end module DervType

program TestType

  use DervType

  implicit none

  type(mytype) :: test

  test = 1.                   !! <-- I don't want to use test%r here

end program TestType

Возможно ли это, определив какое-то назначение интерфейса (перегрузите =) или что-то в этом роде? Это вообще возможно?

Спасибо! Любая помощь приветствуется!


person Florian Ragossnig    schedule 26.09.2018    source источник
comment
Да, можно иметь определенное назначение. Можете ли вы попробовать это, чтобы увидеть, делает ли это то, что вы хотите? Я предполагаю, что это связано с вашим предыдущим вопросом, но вы можете сделать это без полиморфизма.   -  person francescalus    schedule 26.09.2018
comment
См. также: этот вопрос.   -  person francescalus    schedule 26.09.2018
comment
Но это очень специфический аспект вашего вопроса. То есть test = x можно сделать так, чтобы компонент множества test каким-то образом определялся типом x. Однако это ли вы имеете в виду? Часть, которая автоматически возвращает правильный тип, предполагает, что вам может понадобиться сделать что-то более экзотическое (например, call sub(test) действует как call sub(test%r), если аргумент реален и т. д.).   -  person francescalus    schedule 26.09.2018
comment
Спасибо за ответ! Да, я думаю, это все связано, хотя я отказался от других вещей... Если я скомпилирую вышеприведенное, я получу: Error: Can't convert REAL(4) to TYPE(mytype), так что это не работает. Извините, я посмотрел пример по вашей ссылке, но я не понимаю его. Мне нужен интерфейс, верно?   -  person Florian Ragossnig    schedule 26.09.2018
comment
Да, сообщение Error: Can't convert REAL(4) to TYPE(mytype) касается внутреннего назначения. Вам нужно будет настроить определенное назначение, как описано в других вопросах. Этот может помочь.   -  person francescalus    schedule 26.09.2018
comment
Так что мне придется определить пару функций (реальные, int, логические) и назначить их через интерфейс? Попробую это! Спасибо!   -  person Florian Ragossnig    schedule 26.09.2018
comment
Вы также хотите, чтобы x = test работало, где x — вещественное число, а фактическая операция будет x = test%r? Я не думаю, что это возможно, но это приходит на ум при чтении вашего вопроса.   -  person Pierre de Buyl    schedule 27.09.2018
comment
Эй, Пьер! Да, это именно то, что я хочу. Думаю, это можно сделать, переопределив «=», но я все еще играю с этим.   -  person Florian Ragossnig    schedule 27.09.2018


Ответы (1)


Нашел решение этой проблемы, и это было на самом деле довольно просто. Вот код:

module DervType

  implicit none

  type, public :: mytype
    real(8)                       :: r
    integer                       :: i
    character(len=:), allocatable :: c
    logical :: l
  end type

  interface assignment(=)                 // overload = 
    module procedure equal_func_class
  end interface

contains

  subroutine equal_func_class(a,b)

    implicit none

    type(mytype), intent(out) :: a
    class(*), intent(in)      :: b

    select type (b)
        type is (real)
            print *, "is real"
            a%r = b
        type is (integer)
            print *, "is int"
            a%i = b
        type is (character(len=*))
            print *, "is char"
            a%c = b
        type is (logical)
            print *, "is logical"
            a%l = b 
    end select

    return

  end subroutine equal_func_class  

end module DervType

program TestType

  use DervType

  implicit none

  type(mytype) :: test

  test = 1.      // assign real 
  test = 1       // assign integer
  test = "Hey"   // assign character
  test = .true.  // assign logical

  print *, "Value (real)      : ", test%r
  print *, "Value (integer)   : ", test%i
  print *, "Value (character) : ", test%c
  print *, "Value (logical)   : ", test%l

end program TestType

Сейчас я пытаюсь использовать переменные в программе (например, выполнять некоторые арифметические вычисления и т. д.), но это кажется довольно сложным, если не невозможным. Я мог бы начать другой вопрос об этом.

person Florian Ragossnig    schedule 02.10.2018
comment
Это плохая идея. Когда кто-то ссылается на test, у вас нет возможности узнать, какое значение ему нужно — действительное, целое, логическое или символьное. Таким образом, ваше назначение выглядит иначе, чем ваш доступ к значению, что сбивает с толку. - person zmbq; 02.10.2018
comment
Ну, я думаю, это зависит от того, как вы хотели бы его использовать. На данный момент я согласен, что это так, но это не было частью этого вопроса. Я просто хотел узнать, как и возможно ли присвоить значение отложенному типу, не зная типа ввода. В данный момент я работаю наоборот. - person Florian Ragossnig; 02.10.2018
comment
На самом деле, решение со многими процедурами внутри интерфейса имеет то преимущество, что если вы попытаетесь присвоить непокрытый тип, вы получите ошибку времени компиляции. Otoh, используя класс (*) с типом выбора, лучшее, что у вас может быть, - это ошибка времени выполнения (рассмотрите возможность использования предложения select по умолчанию) - person Rodrigo Rodrigues; 02.10.2018