2015-11-10 3 views
4

Я пытаюсь создать гетерогенные массивы, содержащие переменные разных типов, например, [ 1.0, 7, "hi" ]. Я попытался включить class(*) или type(*) в конструктор массива (см. Конец следующего кода), но gfortran5.2 просто рассматривает его как синтаксическую ошибку. Есть ли способ сделать такой массив с конструктором массива или необходимо использовать другой подход (например, определить тип, содержащий каждый элемент отдельно)?Создание гетерогенных массивов в Fortran


Подробнее:

Следующий код является примером, почему я хочу создать такой массив. Процедура checktype_multi принимает несколько аргументов с ключевым словом optional, но этот подход явно ограничен из-за фиксированного количества аргументов. Чтобы разрешить произвольное количество аргументов, я попробовал процедуру checktype_array, но, похоже, невозможно передать массив с разными типами ... Более практичным case может быть создание подпрограммы для печати переменного количества аргументов с различными типами.

module mymod 
    implicit none 
contains 

    subroutine checktype (x) 
     class(*) :: x 

     select type (x) 
      type is (integer)  ; print *, "int : ", x 
      type is (real)   ; print *, "real : ", x 
      type is (character(*)) ; print *, "string : ", x 
     endselect 
    end subroutine 

    subroutine checktype_multi (x1, x2, x3) 
     class(*), optional :: x1, x2, x3 

     print * 
     if (present(x1)) call checktype (x1) 
     if (present(x2)) call checktype (x2) 
     if (present(x3)) call checktype (x3) 
    end subroutine 

    subroutine checktype_array (a) 
     class(*) :: a(:) 
     integer :: k 

     print * 
     do k = 1, size(a) 
      call checktype (a(k)) 
     enddo 
    end subroutine 

end module 

program main 
    use mymod 

    call checktype_multi (1.0) 
    call checktype_multi (1.0, 7) 
    call checktype_multi (1.0, 7, "hi") 

    ! call checktype_array ([ 1.0, 7, "hi" ]) !! error (this is to be expected) 

    !>>> Here is the problem. 
    ! call checktype_array ([ type(*) :: 1.0, 7, "hi" ]) !! this is also an error 
    ! call checktype_array ([ class(*) :: 1.0, 7, "hi" ]) !! this too 
end program 

ответ

4

Элементы массива могут отличаться друг от друга только по значению. Они не могут отличаться по типу или любому другому атрибуту.

Вместо этого используйте оболочку производного типа вокруг неограниченного полиморфного выделяемого компонента. Динамический тип компонента затем считается частью значения объекта типа обертки.

TYPE :: wrapper 
    CLASS(*), ALLOCATABLE :: item 
END TYPE wrapper 

CALL sub([wrapper(1), wrapper(2.0), wrapper('3')]) 

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

+0

Привет @IanH, спасибо очень много для вас информации. Поскольку подпрограмма 'checktype_multi' могла получать литералы разных типов (например, 1.0 и 7) непосредственно в качестве фактических аргументов, я представил себе, что они могут быть преобразованы внутри (внутри компилятора) в некоторые внутренние объекты C, которые представляют эти данные (например , что-то вроде 'struct', состоящего из указателя на необработанные данные и некоторой информации времени выполнения). (продолжение) – roygvib

+0

Итак, я задавался вопросом, есть ли какие-либо удобные способы прямого создания массива гетероформатов Fortran, например массив, состоящий из внутренних объектов, на которые ссылается класс (*) (как некоторая новая функция Fortran). Но, по вашему мнению, это не так. Большое спасибо :) – roygvib

+0

И еще один вопрос: gfortran5.2 все еще дает ошибку с вашим кодом («Невозможно преобразовать целое число в класс (*)» и т. Д.), Но является ли это тем, что gfortran5.2 все еще находится за последним стандартом? Поскольку у меня есть только ifort14 (и не могу установить более новые версии в моей среде), я задался вопросом, не компилируется ли код с более новыми компиляторами. (Если нужны более явные коды, я сделаю это вопросом.) – roygvib

Смежные вопросы