nAG Fortran コンパイラ 7.2 マニュアル

 
ナビゲーション:前へ   上へ   次へ

9.4 他のデータ指向に関する機能強化

9.4.1 パラメタ化構造型 [6.0, LENGTHは6.1]

構造型は新たに型パラメタを持つことができるようになりました。 組込み型に対するものと同様、それらは2種類の形で提供されます: "kind"と類似のもの (コンパイル時に既知でなくてはなりません(“kind”型パラメタと呼ばれる)) と、文字長と類似のもの(実行時に変更可能です(“length”型パラメタと呼ばれ る))の2種類です。

9.4.1.1 基本構文とセマンティクス

型パラメタを持つ構造型はそれらを型定義で列記しなければなりません。型を与えて “kind”パラメタもしくは“length”パラメタの指定を行います。
例:
  TYPE real_matrix(kind,n,m)
    INTEGER,KIND :: kind
    INTEGER(int64),LEN :: n,m

すべての型パラメタはINTEGER型として明示的に指定される必要がありますが、 整数の種別は変わってっも構いません。 型パラメタは常にスカラであり、配列は許されません。 型定義において“kind”型パラメタは定数式中で利用でき、任意の型パラメタを 宣言式(配列境界、文字長、もしくは“length”型パラメタ値)中で使用できま す。 例えば上記の型定義の残りは次のようになります:

    REAL(kind) value(n,m)
  END TYPE real_matrix

このような構造型の要素を宣言する場合、型パラメタは名前の後に指定しなければ なりません。
例:

  TYPE(real_matrix(KIND(0d0),100,200)) :: my_real_matrix_variable
同様に、型パラメタはこのような型の値を構成する際に指定されなくてはなりません。
例:
  my_real_matrix_variable = &
    real_matrix(kind(0d0),100,200)((/ (i*1.0d0,i=1,20000) /))

型定義の外で構造型パラメタの値を調べる場合には成分を参照する場合と同様 の記法が用いられます。
例:

  print *,'Columns =',my_real_matrix_variable%m
つまり型パラメタ名は成分名や型結合手続き名と同じクラスに属しています。 しかしながら型パラメタは代入の左辺上でその指定子を使って変更することは できません。 さらに組込み型パラメタもこの方法により調べることが可能です。例えば
  REAL :: array(:,:)
  CHARACTER(*),INTENT(IN) :: ch
  PRINT *,array%kind,ch%len
KIND(array)LEN(ch) で同じ値を出力します。 種別パラメタの調査はオブジェクトが配列であっても常にスカラである点に注意して 下さい。

構造型パラメタは型定義中で必ずしも実際に使われる必要はなく、種別型パラメタを 宣言式内でのみ使用することもあり得ます。
例:

  TYPE fixed_byte(n)
    INTEGER,KIND :: n
    INTEGER(1) :: value(n)
  END TYPE
  TYPE numbered_object(object_number)
    INTEGER,LENGTH :: object_number
  END TYPE
fixed_byte パラメタ n は定数式中で使われてはいませんが、それに 対しては常に定数値を指定する必要があります。これは “kind” 型パラメタと して宣言されているからです。 同様に object_number は使われていませんが、それに対しては常に値を指定 する必要があります。 これは見かけほど意味のないことではありません。 それぞれの numbered_object はたとえそれが配列であっても object_number に対する一つの値を持ちます。

9.4.1.2 セマンティクスの追加説明

型パラメタを持つ構造型は1つまたは複数の型パラメタに対してデフォルト値を持つ ことが可能です。この場合、デフォルト値を持つパラメタは型指定子で省略が可能で す。
例:
  TYPE char_with_maxlen(maxlen,kind)
    INTEGER,LENGTH :: maxlen = 254
    INTEGER,KIND   :: kind = SELECTED_CHAR_KIND('ascii')
    INTEGER        :: len = 0
    CHARACTER(len=maxlen,kind=kind) :: value
  END TYPE
  ...
  TYPE(char_with_maxlen) temp
  TYPE(char_with_maxlen(80)) card(1000)
  TYPE(char_with_maxlen(kind=SELECTED_CHAR_KIND('iso 10646'))) ucs4_temp

種別型パラメタは定数式中で使えます(従ってデフォルトの初期化で使えます)が、 大きさが可変である成分は長さの型パラメタに依存するためデフォルトによる初期化 はできません。 従って上記例の value はデフォルト初期化できません。

組込み型とは異なり、構造型代入においては異なる型パラメタ値間での自動的な変換 はありません。そのため上記の宣言が行われています。

  card(1) = card(2) ! This is ok, maxlen==80 for both sides.
  temp = card       ! This is not allowed - maxlen 254 vs. maxlen 80.

9.4.1.3 引継ぎ型パラメタ

構造型の引継ぎ型パラメタは文字長と同じように動作しますが、仮引数でのみ認めら れていて名前付き定数では認められていません。 例えば次のサブルーチンは任意の char_with_maxlen 変数に対して機能しま す。
  SUBROUTINE stars(x)
    TYPE(char_with_maxlen(*)) x
    x%value = REPEAT('*',x%maxlen)
  END SUBROUTINE

9.4.1.4 無指定型パラメタ

無指定型パラメタはFortran 2003での新機能です。これらは CHARACTER と パラメタ化構造型の両方で利用可能で、無指定配列境界と同じような動作をします。 無指定型パラメタを持つ変数は ALLOCATABLE もしくは POINTER 属 性を持つ必要があります。 割付け変数の無指定型パラメタの値は割付け(型付き割付けもしくは組込み代入の 自動再割付け)により決定されます。 ポインタにおいては、無指定型パラメタの値は指示先の型パラメタの値です。 次は上記で定義されている型 real_matrix を使った例です。
  TYPE(real_matrix(KIND(0.0),100,200)),TARGET :: x
  TYPE(real_matrix(KIND(0.0),:,:)),POINTER :: y, z
  ALLOCATE(real_matrix(KIND(0.0),33,44) :: y)  ! Typed allocation.
  z => x                                       ! Assumes from the target.
  PRINT *,y%n,z%n                              ! Prints 33 and 100.
割付けされていない割付け、もしくは指示先と結合されていないポインタの無指定型 パラメタ値を参照することは許されていない点に注意して下さい。

仮引数が割付けもしくはポインタの場合、実引数は仮引数と完全に同じ無指定型パラ メタでなくてはなりません。
例:

  SUBROUTINE sub(rm_dble_ptr)
    TYPE(real_matrix(KIND(0d0),*,:)),POINTER :: rm_dble_ptr
  ...
  TYPE(real_matrix(KIND(0d0),100,200)),POINTER :: x
  TYPE(real_matrix(KIND(0d0),100,:)),POINTER :: y
  TYPE(real_matrix(KIND(0d0),:,:)),POINTER :: z
  CALL sub(x)  ! Invalid - X%M is not deferred (but must be).
  CALL sub(y)  ! This is ok.
  CALL sub(z)  ! Invalid - X%N is deferred (but must not be).

9.4.2 最終化 [5.3]

拡張可能構造型はそれに結合された“最終サブルーチン”を持つことができます。 これらのサブルーチンはその型のオブジェクトが破棄される直前に自動的に呼び出され ます。ここで言う破棄には解放によるもの、手続きからの復帰によるもの、組込み代入 の左辺である場合のもの、そして INTENT(OUT) 仮引数として渡された場合によ るものがあります。

ある型の最終サブルーチンは一つの引数のみを持つサブルーチンでなくてはなりません。 この引数はその型の通常の仮引数でなくてはなりません(INTENT(OUT) であっ てはなりません)。 それはスカラでも配列でも良く、その型のオブジェクトが破棄される時に最終サブルー チンがコールされます(引数は該当オブジェクトと同じ次元数を持ちます)。 最終サブルーチンは要素別であっても構いません。その場合、他にそのためのサブルー チンを持たないものであれば、任意の次元数のオブジェクトも扱えます。 オブジェクトの次元数に対して最終サブルーチンが存在しない場合には、サブルーチン はコールされない点に注意してください。

最終サブルーチンは型結合手続きと同様に、CONTAINS文に続く型定義中で宣言 されます。 それらは FINAL 文により宣言されますが、その構文は次の通りです。

FINAL [ :: ] name [ , name ]...

ここにそれぞれのname は上記ルールを満たすサブルーチンを表します。

最終サブルーチンを持つ簡単な型を以下に示します。

  TYPE flexible_real_vector
    LOGICAL :: value_was_allocated = .FALSE.
    REAL,POINTER :: value(:) => NULL()
  CONTAINS
    FINAL destroy_frv
  END TYPE
  ...
  ELEMENTAL SUBROUTINE destroy_frv(x)
    TYPE(flexible_real_vector),INTENT(INOUT) :: x
    IF (x%value_was_allocated) DEALLOCATE(x%value)
  END SUBROUTINE

破棄されるオブジェクトが最終化可能な成分を持つ場合、成分を最終化する前に オブジェクト全体に対する最終サブルーチンが呼び出されます。 オブジェクトが配列の場合には個々の成分は別個に最終化されます(その際に 呼び出される最終サブルーチンは成分の次元数に対応するものであって、オブ ジェクトの次元数に対応するものではありません)。

例:

  TYPE many_vectors
    TYPE(flexible_real_vector) scalar
    TYPE(flexible_real_vector) array(2,3)
  CONTAINS
    FINAL :: destroy_many_vectors_1
  END TYPE
  ...
  SUBROUTINE destroy_many_vectors_1(array1)
    TYPE(many_vectors) array1(:)
    PRINT *,'Destroying a',SIZE(array1),'element array of many vectors'
  END SUBROUTINE
  ...
  TYPE(many_vector) mv_object(3)
mv_object が破棄される際にはまず‘destroy_many_vectors_1’ が mv_object を引数として呼び出され、以下が出力されます。
 Destroying a 3 element array of many vectors
次に配列のそれぞれの要素について、scalararray 成分双方が destroy_frvをコールすることによって最終化されます。 これらは任意の順番で行われる可能性があります(要素別処理であるので並列に 行われることもあり得ます)。

最終サブルーチンは型拡張を通じて継承されないことに注意して下さい。その代りに、 拡張型のオブジェクトが破棄される場合には最初にそのオブジェクトが持つ最終サブ ルーチンが呼び出され、その後で親成分について親型の最終サブルーチンが呼び出さ れます。

9.4.3 PROTECTED属性 [5.0]

PROTECTED 属性は PROTECTED 文もしくは型宣言文内の PROTECTED キーワードにより指定可能です。 これはモジュール変数がモジュール外から変更されることのないように保護します。

9.4.3.1 構文

PROTECTED文の構文は以下の通りです:

PROTECTED [ :: ] name [ , name ] ...

PROTECTED属性はモジュール内の変数についてのみ指定可能です。

9.4.3.2 セマンティクス

PROTECTED属性を持った変数はその変数が定義されるモジュール内でのみ変更 可能です。 該当モジュール外においては、INTENT(IN) 仮引数の場合と同様、それらは 変数定義の文脈中(例えば代入文の左辺など)では使用することができません。

これによりモジュール作成者は一部の変数を外部に公開しながらも、その値の変更を 許さないといった運用が可能になります。

9.4.3.3 用例

MODULE temperature_module
  REAL,PROTECTED :: temperature_c = 0, temperature_f = 32
CONTAINS
  SUBROUTINE set_temperature_c(new_value_c)
    REAL,INTENT(IN) :: new_value_c
    temperature_c = new_value_c
    temperature_f = temperature_c*(9.0/5.0) + 32
  END SUBROUTINE
  SUBROUTINE set_temperature_f(new_value_f)
    REAL,INTENT(IN) :: new_value_f
    temperature_f = new_value_f
    temperature_c = (temperature_f - 32)*(5.0/9.0)
  END SUBROUTINE
END
PROTECTED属性はtemperature_moduleの利用者にtemperature(温度)を 摂氏もしくは華氏で読みだすことを許しますが、変数の変更は提供されているサブルー チンを介してのみ可能です。これによって摂氏と華氏の値の整合性が保証されています。

9.4.4 ポインタの機能強化

9.4.4.1 ポインタのINTENT [5.1]

POINTER仮引数はINTENT属性を持つことができるようになりました。 この属性はポインタ結合状態に対してのものでポインタの指示先のものではありません。

INTENT(IN)ポインタには代入はできますが、ポインタ代入、ヌル化、割付け、 解放は行えません。 INTENT(OUT)ポインタは手続きの入口において未定義結合状態を受けとります。 INTENT(INOUT)ポインタは使用に関しての制限はありませんが、実引数はポイン タ関数の参照ではなくポインタ変数である必要があります。

9.4.4.2 ポインタ上下限指定 [5.2]

ポインタの上下限はポインタ代入において左辺に指定することで、デフォルト値からの 変更が可能です。
例:
  REAL,TARGET :: x(-100:100,-10:10)
  REAL,POINTER :: p(:,:)
  p(1:,1:) => x
上限値は下限値に寸法から1を引いた数を足すことによって得ることができます。 従って上の例ではPの上下限は1:201,1:21となります。 ポインタ代入において任意の次元数の下限値を設定する場合、値は明示的に指定 されなくてはならず(配列の宣言のときとは異なり1というデフォルト値がある わけではありません)、またこれをポインタのすべての次元に対して指定する必 要がある点に注意してください。

9.4.4.3 次元再割当ポインタ代入 [5.0]

この機能は多次元ポインタが1次元オブジェクトを指し示すことを可能にします。
例:
  REAL,POINTER :: diagonal(:),matrix(:,:),base(:)
  ...
  ALLOCATE(base(n*n))
  matrix(1:n,1:n) => base
  diagonal => base(::n+1)
  !
  ! DIAGONAL now points to the diagonal elements of MATRIX.
  !

次元再割当に際して、下限値と上限値双方の値は全ての次元に対して明示的に指定され なくてはならない点に注意してください。デフォルト値はありません。

9.4.5 個別成分アクセシビリティ [5.1]

構造型内の個々の成分に対してアクセシビリティを設定できるようになりました。
例:
  TYPE t
    LOGICAL, PUBLIC :: flag
    INTEGER, PRIVATE :: state
  END TYPE
継承されない、もしくは割付可能である、もしくは暗黙的初期値指定されるプライベートな要素が含まれる場合、 すべての成分が公開である構造体構成子はそれを定義するモジュール外では利用できません。 (構造体書式の拡張を参照)

9.4.6 非公開型の公開要素 [5.1]

あるモジュールからの言語要素(名前付き定数、変数、手続き)のエクスポートが、 たとえその中に非公開な型や非公開型の引数(手続きの場合)が含まれている場合 であっても可能になりました。
例:
  MODULE m
    TYPE, PRIVATE :: hidden_type
      CHARACTER(6) :: code
    END TYPE
    TYPE(hidden_type), PUBLIC, PARAMETER :: code_green = hidden_type('green')
    TYPE(hidden_type), PUBLIC, PARAMETER :: code_yellow = hidden_type('yellow')
    TYPE(hidden_type), PUBLIC, PARAMETER :: code_red = hidden_type('red')
  END
© 日本ニューメリカルアルゴリズムズグループ株式会社 2025
Privacy Policy  /  Trademarks