Fortranでは、いくつかのサブルーチンの1つを指すことができる派生型内にプロシージャポインタが必要です。少数を示すためにFortranプロシージャの派生型のサブルーチンへのポインタ
Fortran save procedure as property in derived type
Type bound procedure overloading in Fortran 2003
There is no matching specific subroutine for this type bound generic subroutine call
Generic type-bound procedures with procedure arguments
Type bound procedure as arguments
:この問題は、SOに共通のようです。 関数のこの質問に対する回答は、最初の参照で非常にうまく提供されています。
しかし、タイプバインドされたプロシージャーポインターがサブルーチンを指している場合には、このようなコードをうまく開発する方法論についてはまだ分かりません。難しいのは、返されるものに関連付けられた型がないということです(実際には何も返されないため)。
また、Fortran(2003,2008)の最近の標準では単純な解決策が存在する可能性がありますが、この解決策はすべてのコンパイラでは機能しない可能性がありますが、将来問題が生じる可能性があるというニュアンスを指摘したいと思います。コンパイラに優しいソリューションに興味があります。
私は大きなコードで、派生型のプロシージャポインタを使用するファイルに内部コンパイラエラー(以下も示す)が表示されています。私の質問は:私は厳密にコンパイラ
3)コードはできるだけ多くのコンパイラ間の移植性があることを確認しに渡された情報を最大化)明示的なインターフェイス
2を使用)
1に以下のコードに何ができます(つまり、Fortran 90/95標準を使用する)。
上記をどれだけ満たすことができますか(1が最も重要です)?上記のすべての基準を満たすことは可能ですか?私はそれが「すべてのこれらの基準を満たす」ことが主観的であることは理解していますが、サブルーチンの代わりに機能に関する同じ質問に対して答えが「はい」と主張します。
gcc version 5.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project)
小さなコード:
module subs_mod
implicit none
public :: add,mult
contains
subroutine add(x,y,z)
implicit none
integer,intent(inout) :: x
integer,intent(in) :: y,z
x = y+z
end subroutine
subroutine mult(x,y,z)
implicit none
integer,intent(inout) :: x
integer,intent(in) :: y,z
x = y*z
end subroutine
end module
module type_A_mod
use subs_mod
implicit none
public :: type_A,init,operate
type type_A
procedure(),pointer,nopass :: op
end type
contains
subroutine init(A,op)
implicit none
external :: op
type(type_A),intent(inout) :: A
A%op => op
end subroutine
subroutine operate(A,x,y,z)
implicit none
type(type_A),intent(in) :: A
integer,intent(inout) :: x
integer,intent(in) :: y,z
call A%op(x,y,z)
end subroutine
end module
program test
use type_A_mod
use subs_mod
implicit none
type(type_A) :: A
integer :: x
call init(A,mult)
call operate(A,x,3,5)
write(*,*) 'x = ',x
end program
大きなコードで
コンパイラエラー:
f951.exe: internal compiler error: Segmentation fault
libbacktrace could not find executable to open
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://sourceforge.net/projects/mingw-w64> for instructions.
UPDATE
ここでは、コンパイラより多くの情報を与える小さな変更は、だけど私は大きなコードでこれを試していない。しかし、それは恣意的と思われ、助けになるかどうかは分かりません。、一つの追加のシワがあった、それは私はいくつかの派生型がThe New Features of Fortran 2003に応じて抽象インタフェースを、入っていたということでした。
...
function add(x,y,z) result(TF)
...
logical :: TF
x = y+z
TF = .true.
end function
function mult(x,y,z) result(TF)
...
logical :: TF
x = y*z
TF = .true.
end function
end module
module type_A_mod
...
type type_A
procedure(logical),pointer,nopass :: op
end type
...
subroutine init(A,op)
implicit none
logical,external :: op
...
end subroutine
subroutine operate(A,x,y,z)
...
logical :: TF
TF = A%op(x,y,z)
end subroutine
end module
program test
...
end program
SOLUTIONは ちょうど(@IanH提供)ソリューションにコメントするコメント抽象的なインターフェイスに入力派生型が認識されるようにするには、Import
ステートメントを含める必要があります。ここでは、大きなコードに適用され、小型の実施例である内部コンパイラエラーを軽減し、私は:)
module DT_mod
implicit none
private
public :: DT
type DT
integer :: i
end type
contains
end module
module subs_mod
use DT_mod
implicit none
private
public :: add,mult,op_int
abstract interface
subroutine op_int(d,x,y,z)
import :: DT
implicit none
type(DT),intent(inout) :: d
integer,intent(inout) :: x
integer,intent(in) :: y,z
end subroutine
end interface
contains
subroutine add(d,x,y,z)
implicit none
type(DT),intent(inout) :: d
integer,intent(inout) :: x
integer,intent(in) :: y,z
x = y+z
d%i = 1
end subroutine
subroutine mult(d,x,y,z)
implicit none
type(DT),intent(inout) :: d
integer,intent(inout) :: x
integer,intent(in) :: y,z
x = y*z
d%i = 2
end subroutine
end module
module type_A_mod
use DT_mod
use subs_mod
implicit none
private
public :: type_A,init,operate
type type_A
procedure(op_int),pointer,nopass :: op
end type
contains
subroutine init(A,op)
implicit none
procedure(op_int) :: op
type(type_A),intent(inout) :: A
A%op => op
end subroutine
subroutine operate(A,d,x,y,z)
implicit none
type(DT),intent(inout) :: d
type(type_A),intent(in) :: A
integer,intent(inout) :: x
integer,intent(in) :: y,z
call A%op(d,x,y,z)
end subroutine
end module
program test
use type_A_mod
use subs_mod
use DT_mod
implicit none
type(type_A) :: A
type(DT) :: d
integer :: x,y,z
y = 3; z = 5
call init(A,mult)
call operate(A,d,x,y,z)
write(*,*) 'x,y,x = ',y,z,x
write(*,*) 'd%i = ',d%i
end program
を持っていたすべてのヘルプは大歓迎です。
違いを表示するだけで、更新2で変更された内容を確認するのは難しいです。特に、コード内に空白行を使用しない(読みにくい)ことを考慮すると、 –
ところで、gfortranで '-std = f95'を実行すると、実際にFortran 2003以降のものがいくつあるのかがわかります。 –
ありがとう@VladimirF、私は最近これを試しました、それは有用でした。 – Charlie