2

私が取り組んでいるプロジェクトでは、新しいオブジェクトが作成され、古いオブジェクトが破棄されるときに、オブジェクトの配列のサイズを頻繁に変更する必要があることに気付きました。これは、コード全体で多数の異なる派生型で発生し、そのほとんどは相互に関係がありません。これらの配列のサイズを固有の派生型に合わせて変更するコードを書くのは面倒なので、派生型配列がそれらのサブルーチンを使用できるように、無制限のポリモーフィック仮引数を使用していくつかのヘルパー サブルーチンを作成してみようと考えました。

私が見つけたのは、私の無制限のポリモーフィック ルーチンをコンパイルして で呼び出すことができるということ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

私は Fortran コードを広範囲に記述してきましたが、これまで無制限のポリモーフィズムを使用しようとしたことはありません。私がやろうとしていることが可能かどうか、もしそうなら、私が間違っていることを教えてください。

私は gfortran コンパイラ 5.4.0 を使用しています。これは、私が知る限り、無制限のポリモーフィズムを完全にサポートする必要があります。

4

2 に答える 2

1

次のように宣言された割り当て可能なオブジェクトがある場合

class(*), allocatable :: obj(:)

「割り当て可能」な性質が配列の形状または型の側面に個別に適用されることを仮引数に指定することはできません。

仮引数に属性があると言うとすぐallocatableに、完全な制限が仮引数と関連する実引数に適用されます。この場合、割り当て可能な無制限の多態性の仮引数は、割り当て可能な無制限の多態性の実引数にのみ関連付けることができます。1

実引数alloc0dは宣言された型integerであり、無制限のポリモーフィックではありません。したがって、このような手続き参照は許可されません。

同じ論理が、ポインターの仮/実引数に対して明示的に保持されます。完全を期すために、ダミーが無制限のポリモーフィックでない場合、実引数の要件は、宣言された同じ型でなければならないということです。

allocatable仮引数にor属性がなければ、pointer引数の関連付けは有効です。

割り付け可能/ポインター仮配列引数を再形成できるようにするには、仮引数が多態的でないことが必要です。そのような場合を処理する別の方法を見つける必要があります (おそらくジェネリックを使用)。


1これの動機は、割り当て可能なポリモーフィック仮引数の動的な型と、その形状 (配列の場合) がallocateステートメントで変更される可能性があるためです。そのステートメントは、互換的に定義されていない場合、関連する実引数に明らかに影響を与えません。これも Fortran の規則に当てはまります。「このオブジェクトは多態的ですが、型を変更しないことを約束します」とは言えません。

于 2019-06-05T20:55:33.470 に答える