拡張構造体を使ったプログラミングにおける問題と解決策
ナビゲーションに移動
検索に移動
Fortran で拡張構造体を利用する場合、言語仕様に伴ういくつかの困難が存在する。 本ページではそれらについて示すとともに、現状での解決策等を提示する。
同クラス内での代入
問題点:拡張後の構造体に拡張前の構造体を代入することができない。
例:
type aaa integer :: bbb endtype type,extends(aaa) :: aaa_ex integer :: ccc endtype
とした場合に aaa_ex = aaa がエラーとなる。
解決策:ユーザー定義代入を定義する。
例:
type aaa integer :: bbb endtype type,extends(aaa) :: aaa_ex integer :: ccc contains generic :: assignment(=) => equal procedure :: equal endtype
subroutine equal(out,in) implicit none class(aaa),intent(inout) :: out !!! intent(inout) 指定は必須。 !!! そうしないと代入時に ccc が未定義となる。 type(aaa),intent(in) :: in out%aaa = in%aaa !!! 各成分ごとの代入が必要。 !!! out = in では subroutine equal の再起呼び出しとなってしまう。 !!! この解決策はメンバ変数が多い場合に問題となる。 endsubroutine
オーバーロード時の元関数呼び出し
問題点:プロシージャのオーバーロード時に元のプロシージャが呼び出せなくなる。
例:
module aaa_module
implicit none
type aaa
contains
procedure :: sub
endtype
...
endmodule
module aaa_ex_module
use aaa_module,only: aaa
implicit none
type,extends(aaa) :: aaa_ex
contains
procedure :: sub !!! オーバーロード
endtype
contains
subroutine sub(self)
implicit none
class(aaa_ex) :: self
元の sub を呼べない。
endsubroutine
endsubroutine
解決策:オーバーロードする関数を generic とし、元の sub を呼び出す場合は詳細なプロシージャ名を指定する。
例:
module aaa_module
implicit none
type aaa
contains
generic :: sub => sub_original
procedure :: sub_original
endtype
...
endmodule
module aaa_ex_module
implicit none
type,extends(aaa) :: aaa_ex
contains
generic :: sub => sub_ex !!! オーバーロード
procedure :: sub_ex
endtype
contains
subroutine sub_ex(self)
implicit none
class(aaa_ex) :: self
call self%sub_original()
...
endsubroutine
endsubroutine