Функция/подпрограмма Фортрана, которая может возвращать вещественное число, целое число или строку.

Я хотел бы знать, как создать функцию, которая возвращает вещественное число, целое число или строку.

Например, вызов будет write(*,*)dt%get(), где get() будет возвращаться:

  • целое число, если dt%isInteger = .true.
  • реальный, если dt%isReal = .true.
  • символ, если dt%isStr = .true.

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

Вот соответствующий код:

type :: dt
    real(dp) :: realValue
    integer :: integerValue
    character(*) :: strValue
    logical :: isReal, isInteger, isStr
    procedure(intf), pointer :: get
contains
    procedure :: getReal, getInteger, getStr
end type

abstract interface
    function intf(self)
        import dt
        class(dt) :: self
        ??? :: intf
    end function
end interface

Есть идеи ?


person yolegu    schedule 18.01.2018    source источник


Ответы (1)


Это просто невозможно в Фортране.

Вы можете использовать универсальный интерфейс с различными специфическими функциями, но эти функции должны иметь аргументы разных типов (посмотрите, как некоторые встроенные функции, такие как transfer(), используют аргумент mold). Это называется разрешением ТКР (тип, вид, ранг). Общие функции нельзя отличить по значению аргумента.

type :: dt
    real(dp) :: realValue
    integer :: integerValue
    character(*) :: strValue             !!!! <= THIS IS WRONG !!!!
    logical :: isReal, isInteger, isStr
contains
    generic :: get => getReal, getInteger, getStr
    procedure :: getReal, getInteger, getStr
end type

function getReal(self, mold)
  class(dt) :: self
  real, intent(in) :: mold
end function

function getInteger(self, mold)
  class(dt) :: self
  integer, intent(in) :: mold
end function

function getString(self, mold)
  class(dt) :: self
  character(*), intent(in) :: mold
end function

Как видите, вы должны знать правильный тип при вызове get(). Вы называете это как

real_variable = object%get(1.0)
integer_variable = object%get(1)

Будьте также осторожны со строками разной длины. Я отметил это выше. Вы, вероятно, хотите character(:), allocatable.


Вы также можете создать функцию, которая возвращает общий контейнер, а затем извлекает значение из контейнера. Извлечение может быть выполнено даже напрямую с использованием перегруженного присваивания для контейнера.

Вы также можете просто вернуть неограниченную полиморфную переменную (class(*)).

person Vladimir F    schedule 18.01.2018
comment
У вас есть короткий пример, иллюстрирующий использование class(*) в этом контексте? - person yolegu; 26.01.2018
comment
Ну, делайте это, только если вы уже это знаете. К сожалению, в основных компиляторах все еще есть ошибки компилятора, поэтому у меня возникают проблемы с подготовкой чего-либо. Контейнер, содержащий class(*), будет лучше. - person Vladimir F; 26.01.2018