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 ]...
最終サブルーチンを持つ簡単な型を以下に示します。
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次に配列のそれぞれの要素について、
scalar
と array
成分双方が
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