2012-04-05 4 views
2

나는 자신의 코드가 같은 것을 목표로하기 때문에 Metcalf 외의 "Fortran 95/2003 explain"의 예제를 사용한다.추상 형식을 확장하는 파생 형식의 연산자를 어떻게 오버로드합니까?

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

어떤 컴파일러를 사용해 보셨습니까? –

+0

최신 버전. – tiam

답변

3

이 방법은 저에게는 효과적이지만 매우 복잡합니다 (너무 많음 select type). 출력을 쉽게하기 위해 값을 public으로 만들었습니다. 그렇지 않으면 커스텀 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

+0

정수에 추가하거나 정수에 할당하려는 다른 확장 유형이있을 수 있기 때문에 최소한 외곽은 필요합니다. 바깥쪽에 더 좋은 해결책을 찾아보십시오. 다형성에는 효율성에 대한 비용이 있습니다. –

+0

@tiam : 여러분의 코드가 대용량 배열 작업을하는 데 대부분의 시간을 소비하는 경우에는 너무 비효율적이지는 않을 것입니다. 이는 모든 Fortran 코드가 확실히 수행합니다. – bdforbes

관련 문제