サブルーチンに 2 つの派生型ポリモーフィック配列 (obj1 と obj2) があります。サブルーチンの使用に基づいて、2 つの配列の型は異なる場合がありますが、両方の配列は同じ型です。以下のサンプル コードでは、抽象クラス (モデル) の 1 つのサブタイプのみを示していますが、実際には、これを複数のサブタイプで機能させたいと考えています。さらに、製品コードでは、このコピーの前に 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) (サンプル コードではタイプ linearDivisionMode の model1、model2 として指定) および一連のインデックスを指定して、指定された要素を 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))
第 3 に、部分要素を手動で転送することを期待して、多態的な配列を割り当てることができました。ただし、そうしようとすると、多態的なオブジェクトと組み込みの代入について苦情が寄せられます。これについては、この投稿の後半で説明します。
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.
type select ステートメントを使用してポリモーフィック コンテキストを削除しようとしましたが、エラーが残ります。
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 標準 (ここで適用) により、ベクトル インデックス付き配列にポインターを割り当てることができません。興味深いことに、ポインタを作成すると、そのポインタのベクトル インデックスが生成され、コンパイラはセグメンテーション違反を起こし、何か奇妙なことが起こっていることを示します。
組み込み代入に関するコンパイラの不満に対処するために、私は代入ルーチンを作成することを検討しました。ただし、これには新たな懸念事項があります。これらのルーチンの両方が継承する親の型は抽象型であり、そのクラスで一般的な遅延代入演算子を指定できないようであり、かなりの数のプライベート メソッドを必要とする複雑な親クラスにつながります。プライベート変数を指定していないため、コピーします。さらに、サブクラス A と B の間の変換は十分に定義されていません。これはまだ残っている唯一の方法のようであり、複雑に思えます。
指定されたポリモーフィック サブアレイを効果的に転送するにはどうすればよいですか?
gfortran バージョン 6.1.1 を使用しています。