У меня есть два полиморфных массива производных типов (obj1 и obj2) в подпрограмме. Основываясь на использовании подпрограммы, хотя типы двух массивов могут различаться, оба массива имеют одинаковый тип; например, оба типа A или оба типа B. В приведенном ниже примере кода я показываю только один подтип абстрактного класса (модели), хотя на самом деле я хочу, чтобы это работало с несколькими подтипами. Кроме того, в производственном коде элементы model1 были изменены до этой копии.
program test
use env_kindtypes, only: si, dp
use abs_obj_model, only: model
use obj_linearDivisionModel, only: linearDivisionModel
implicit none
class(model),allocatable :: model1(:), model2(:)
allocate(linearDivisionModel::model1(10))
!want e.g. model2 = model1([1,4,6,2])
![...]
Учитывая obj1, obj2 (тип A) (заданные как model1, model2 типа linearDivisionMode в примере кода) и набор индексов, я хочу передать указанные элементы из obj1 в obj2, выделяя obj2 в процессе.
Я пробовал довольно много подходов для этого, но ни один из них не работает.
Во-первых, я попробовал прямое присваивание с использованием индекса вектора; это терпит неудачу, жалуясь, что прямое назначение размещаемого полиморфного массива еще не поддерживается.
indices = [ 1 , 2 ]
model2 = model1(indices)
результат:
model2 = model1(indices)
1
Error: Assignment to an allocatable polymorphic variable at (1) is not yet supported
Во-вторых, я попытался использовать выделение из источника. Если я попробую это с нотацией среза массива, это сработает (но моя проблема не может быть выражена только с такими диапазонами). Если я попытаюсь векторно индексировать исходный массив, он скомпилируется, но во время выполнения я получаю ошибки из-за нехватки памяти (это нереально, учитывая систему).
allocate(model2,source=model1(indices))
результат выполнения:
Operating system error: Cannot allocate memory
Memory allocation failed
Error termination. Backtrace:
#0 0x434471 in __obj_lineardivisionmodel_MOD___copy_obj_lineardivisionmodel_Lineardivisionmode
at build/processed_src/obj_linear_model.f90:462
#1 0x436c75 in cg_charge_fit
at build/processed_src/test.f90:37
#2 0x403019 in main
at build/processed_src/test.f90:22
Работает, но недостаточно для моих целей.
allocate(model2,source=model1(1:2))
В-третьих, я смог выделить полиморфный массив в надежде на ручную передачу подэлементов: однако, когда я пытаюсь это сделать, я получаю жалобы на полиморфные объекты и внутреннее присваивание, к которым я вернусь позже в этом посте.
indices = [ 1 , 2 ]
allocate(model2(size(indices)),source=model1(1))
do i=1,size(indices)
model2(i) = model1(indices(i))
enddo
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator.
Я пытался использовать операторы выбора типа для удаления полиморфного контекста, но ошибки остаются.
select type (POBJECT => model1)
TYPE IS (linearDivisionModel)
allocate(linearDivisionModel::model2(size(indices)))
do i=1,size(indices)
model2(i) = POBJECT(indices(i))
enddo
end select
полученные результаты:
model2(i) = model1(indices(i))
1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator
В качестве обходного пути я надеялся использовать промежуточный объект-указатель и выделить из него источник. Из-за стандарта f2008 (который применяется здесь) я не могу назначить указатель на векторный индексированный массив. Интересно, что если я создаю указатель, векторный индекс этого указателя, компилятор segfaults указывает на то, что происходит что-то странное.
Чтобы ответить на жалобы компилятора на внутреннее присваивание, я подумал о написании подпрограмм присваивания; однако это вызывает новые опасения: родительский тип, от которого наследуют обе эти подпрограммы, является абстрактным, и я не могу указать общий оператор присваивания deferred в этом классе, что приводит к сложному родительскому классу. который требует довольно много закрытых методов для копирования, поскольку он не указывает закрытых переменных. Кроме того, преобразование между подклассами A и B плохо определено. Это по-прежнему кажется единственным оставшимся выходом и кажется сложным.
Как я могу эффективно передать указанные полиморфные подмассивы?
Я использую gfortran версии 6.1.1.
select type
попытке жалоба связана с тем, чтоmodel2(i)
невозможно выделить. Действительно, вы не ссылаетесь наPOBJECT
в этой конструкции (которая связана сmodel1
). Вы, вероятно, захотите попробовать ещеselect type
на (распределенном)model2
и связанную с ним вещь в качестве цели назначения. [Или что-то вродеallocate(model2, mold=model1(indices)); select type (obj=>model2)...
] - person francescalus   schedule 23.06.2016allocate(model2(SIZE(indices)),source=model1(indices))
. - person francescalus   schedule 23.06.2016