В проекте, над которым я работаю, мне часто приходится изменять размеры массивов объектов по мере создания новых объектов и уничтожения старых.Это происходит с многочисленными различными производными типами в коде, большинство из которых не имеют отношения друг к другу.Написание кода для изменения размера этих массивов для уникального производного типа утомительно, поэтому я подумал, что попробую написать пару подпрограмм-помощников, использующих неограниченные полиморфные фиктивные аргументы, чтобы любой массив производного типа мог использовать эти подпрограммы.
ЧтоЯ обнаружил, что моя неограниченная полиморфная процедура может быть скомпилирована и вызвана с помощью CLASS(*),INTENT(INOUT) :: val
.Этот фиктивный аргумент будет принимать целое число, выделяемое целое число или указатель на целое число.Однако, как только я пытаюсь добавить атрибуты ALLOCATABLE
или POINTER
, подпрограмма компилируется правильно, но я не могу вызвать ее, не получив ошибку компилятора.Поскольку моя цель состоит в том, чтобы иметь возможность изменять размеры массивов производных типов, эти атрибуты необходимы для того, чтобы подпрограмма могла освобождать / распределять / ассоциировать значения.
Вот некоторый тестовый код, который даже не пытаетсяна самом деле делать что угодно, но не компилируется.В этой версии используются скалярные конкретные типы, но такие же ошибки возникают в исходном коде с использованием массивов конкретных типов или массивов производных типов
MODULE Resize_mod
PUBLIC
CONTAINS
SUBROUTINE resize(val)
CLASS(*),INTENT(INOUT) :: val
WRITE(*,*) 'resize'
ENDSUBROUTINE resize
SUBROUTINE resize_alloc(val)
CLASS(*),ALLOCATABLE,INTENT(INOUT) :: val
WRITE(*,*) 'resize_alloc'
ENDSUBROUTINE resize_alloc
SUBROUTINE resize_ptr(val)
CLASS(*),POINTER,INTENT(INOUT) :: val
WRITE(*,*) 'resize_ptr'
ENDSUBROUTINE resize_ptr
ENDMODULE Resize_mod
PROGRAM testResize
USE Resize_mod
INTEGER,TARGET :: array0d
INTEGER,ALLOCATABLE :: alloc0d
INTEGER,POINTER :: ptr0d
array0d=1
CALL resize(array0d)
ALLOCATE(alloc0d)
alloc0d=1
CALL resize(alloc0d)
!Following line gives: "Error: Actual argument to ‘val’ at (1) must be polymorphic"
CALL resize_alloc(alloc0d)
ALLOCATE(ptr0d)
ptr0d=1
CALL resize(ptr0d)
!Following line gives: "Error: Actual argument to ‘val’ at (1) must be polymorphic"
CALL resize_ptr(ptr0d)
ENDPROGRAM testResize
Как показано, код выдает следующие ошибки:
testResize.f90:31:20:
CALL resize_alloc(alloc0d)
1
Error: Actual argument to ‘val’ at (1) must be polymorphic
testResize.f90:37:18:
CALL resize_ptr(ptr0d)
1
Error: Actual argument to ‘val’ at (1) must be polymorphic
Если я закомментирую 2 строки, названные в ошибках, я получу следующий правильный вывод:
resize
resize
resize
Я много писал код на Фортране, но никогда раньше не пытался использовать неограниченный полиморфизм.Пожалуйста, дайте мне знать, возможно ли то, что я пытаюсь сделать, и если да, то, что я делаю неправильно.
Я использую компилятор gfortran 5.4.0, который должен полностью поддерживать неограниченный полиморфизм, насколько это возможно.Я могу сказать.