2012-04-05 25 views
2

我以Metcalf等人的「Fortran 95/2003解釋」爲例,因爲m自己的代碼旨在實現相同的目的。如何爲擴展抽象類型的派生類型重載一個運算符?

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,因爲它是一個類型綁定過程,但第二個參數必須是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

你試過了哪個編譯器? – 2012-04-05 20:43:28

+0

最新的ifort。 – tiam 2012-04-05 22:20:01

回答

3

這適用於我,但它看起來相當複雜(太多select type)。我公開的價值只是簡單的輸出,否則你需要一個自定義的getter和setter。

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 2012-04-05 22:20:44

+0

看來,但至少外層是非常必要的,因爲可以有其他擴展類型,你想添加到整數或分配給整數。試着想出一個更好的解決方案到外面的一個。 多態性有其成本效率。 – 2012-04-06 06:47:04

+0

@tiam:如果你的代碼大部分時間用於大型數組操作,那麼這可能不會太低效,這是我所有Fortran代碼當然要做的。 – bdforbes 2012-04-08 23:35:29