2012-04-05 10 views
2

私自身のコードは同じことを目指しているので、Metcalfらが「Fortran 95/2003の説明」の例を取ります。抽象型を拡張する派生型の演算子をどのようにオーバーロードしますか?

type, abstract :: my_numeric_type 
contains 
    private 
    procedure(op2), deferred :: add 
    generic, public :: operator(+) => add 
end type 

abstract interface 
    function op2(a,b) result (r) 
     import :: my_numeric_type 
     class(my_numeric type), intent(in) :: a,b 
     class(my_numeric type), allocatable :: r 
    end function op2 
end interface 

type, extends(my_numeric_type) :: my_integer 
    integer, private :: value 
contains 
    procedure :: add => add_my_integer 
end type 

ここで私の質問は、add_my_integer機能を正しく実装する方法です。タイプバインドされたプロシージャであるため、最初の引数をmy_integerとしてキャストするように強制されているようですが、2番目のメソッドは抽象インターフェイスに準拠するためにmy_numeric_typeでなければなりません。その結果、rmy_integerに割り当てる必要がありますか?ここで私がこれまでに思いついたのはコンパイルされますが、常に型をチェックするのは奇妙に思えますし、(おそらく私のコードでは別の問題が原因で)セグメンテーションフォルトが発生します。

function add_my_integer(a,b) result(r) 
    class(my_integer), intent(in) :: a 
    class(my_numeric_type), intent(in) :: b 
    class(my_numeric_type), allocatable :: r 

    allocate(my_integer :: r) 
    select type (b) 
     type is (my_integer) 
      r = a+b 
    end select 
end function 
+0

どのコンパイラを試しましたか? –

+0

最新のifort。 – tiam

答えて

3

これは私にとっては効果がありますが、かなり複雑です(select typeが多すぎます)。私は出力を簡単にするために値を公開しました。それ以外の場合は、カスタムゲッターとセッターが必要です。

module num 

    type, abstract :: my_numeric_type 
    contains 
     private 
     procedure(op2), deferred :: add 
     generic, public :: operator(+) => add 
     procedure(op), deferred :: ass 
     generic, public :: assignment(=) => ass 
    end type 

    abstract interface 
     subroutine op(a,b) 
      import :: my_numeric_type 
      class(my_numeric_type), intent(out) :: a 
      class(my_numeric_type), intent(in) :: b 
     end subroutine op 
     function op2(a,b) result (r) 
      import :: my_numeric_type 
      class(my_numeric_type), intent(in) :: a,b 
      class(my_numeric_type), allocatable :: r 
     end function op2 

    end interface 

    type, extends(my_numeric_type) :: my_integer 
     integer, public :: value 
    contains 
     procedure :: add => add_my_integer 
     procedure :: ass => ass_my_integer 
    end type 

    contains 

    function add_my_integer(a,b) result(r) 
     class(my_integer), intent(in) :: a 
     class(my_numeric_type), intent(in) :: b 
     class(my_numeric_type), allocatable :: r 

     select type (b) 
      type is (my_integer) 
       allocate(my_integer :: r) 
       select type (r) 
        type is (my_integer) 
        r%value = a%value+b%value 
       end select 
     end select 
    end function 


    subroutine ass_my_integer(a,b) 
     class(my_integer), intent(out) :: a 
     class(my_numeric_type), intent(in) :: b 

     select type (b) 
      type is (my_integer) 
        a%value = b%value 
     end select 
    end subroutine 

end module 

program main 
    use num 

    class(my_integer), allocatable :: a, b, c 
    allocate(my_integer :: a) 
    allocate(my_integer :: b) 
    allocate(my_integer :: c) 
    a=my_integer(1) 
    b=my_integer(2) 
    c = a+b 
    write (*,*) c%value 
end program 
+0

すべての操作にif文を付けるのは非常に効率が悪いようです。 – tiam

+0

整数に追加したい、または整数に代入したい他の拡張型があるかもしれないので、少なくとも外部のものは非常に必要です。外側の方が良い解決法を思いついてみてください。 多型性は、効率の点でコストがかかります。 –

+0

@tiam:あなたのコードが大規模な配列操作を行うのにほとんどの時間を費やしているのであれば、おそらくあまりにも非効率的ではありません。 – bdforbes

関連する問題