У меня есть два полиморфных массива производного типа (obj1 и obj2) в подпрограмме. Основываясь на использовании подпрограммы, в то время как типы двух массивов могут отличаться, оба массива одного типа; например, оба типа A или оба типа B. В приведенном ниже примере кода я показываю только один подтип абстрактного класса (модели), в то время как на самом деле я хочу, чтобы это работало по нескольким подтипам. Кроме того, в производственном коде элементы модели1 были изменены до этой копии.Копирование подмножеств полиморфных массивов в целевые полиморфные массивы
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 (тип А) (с учетом как 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, указывая на то, что происходит что-то странное.
Чтобы обратиться к жалобам компилятора о внутреннем назначении, я рассмотрел возможность написания подпрограмм; однако это вызывает новый набор забот: родительский тип, который оба эти наследования наследует, является абстрактным, и я не могу указать общий оператор назначения в этом классе, что приводит к сложному родительскому классу, который требует довольно много частные методы для копирования, поскольку он не указывает никаких частных переменных. Кроме того, преобразование между подклассами A и B плохо определено.Это все еще кажется единственным оставшимся выходом, и кажется сложным.
Как я могу эффективно передать указанные полиморфные подмассивы?
Я использую версию gfortran 6.1.1.
Даже если есть способы исправить представленные исходные решения, было бы полезно, если бы некоторые обсуждения о том, как эффективно перегрузить операторы присваивания в этом контексте. – alekepd
В вашей попытке 'select type' жалоба касается' model2 (i) 'нераспределяемой. В самом деле, вы не ссылаетесь на 'POBJECT' в этой конструкции (которая связана с' model1'). Вероятно, вы захотите попробовать еще один 'select type' на (выделенной)' model2' и связанную с ним роль в качестве целевой цели. [Или что-то вроде 'allocate (model2, mold = model1 (индексы)); select type (obj => model2) ... '] – francescalus
Для вашей попытки выделения ресурсов вы можете заметить, что есть [проблемы] (http://stackoverflow.com/q/34384145) с распределением ресурсов gfortran. Хотя результат отличается, может быть, стоит явно указать границы распределения. Что-то вроде 'allocate (model2 (SIZE (индексы)), source = model1 (индексы)). – francescalus