2014-09-23 4 views
2

실제 데이터 유형과 복잡한 데이터 유형의 차이점을 숨기려고합니다. FORTRAN 2003에서는 그렇게 할 수있는 방법이있을 것이라고 생각합니다.FORTRAN : data polymorphic

목표는 런타임에 유형을 결정할 수있는 다형성 할당 가능 배열을 정의하는 것입니다. 게다가 다형성 배열을 사용하여 대수를 수행하는 서브 루틴이 있습니다 (실제 및 복합 데이터에 대해 동일한 방정식이 작동합니다). 그럼 난 데 문제

module poly 
    implicit none 
    private 
    type, public :: MyType 
     class(*), allocatable :: AllData(:) 
    contains 
     procedure, public :: Constructor 
    endtype MyType 

    contains 

    subroutine Constructor(this, Nsize, IfComplex) 
     class(MyType), intent(inout) :: this 
     integer, intent(in) :: Nsize 
     logical, intent(in) :: IfComplex 
     if(IfComplex) then 
      allocate(complex(8)::this%AllData(Nsize))   
     else 
      allocate(real(8)::this%AllData(Nsize)) 
     endif 
    endsubroutine 
endmodule poly 

! Same algebra subroutine 
! Main 
program test 
    use poly 
    use Operation 
    type(MyType) :: t1, t2 
    integer :: i 
    call t1%Constructor(4, .true.) 
    call Square(t1%AllData) 
endprogram test 

:

접근 A : :

module poly 
    implicit none 
    private 
    type, abstract, public :: MyType 
    contains 
     procedure, public :: Constructor 
    endtype MyType 

    type, extends(MyType), public :: MyTypeR 
     real(8), allocatable :: AllData(:) 
    endtype MyTypeR 

    type, extends(MyType), public :: MyTypeI 
     complex(8), allocatable :: AllData(:) 
    endtype MyTypeI 

    contains 

    subroutine Constructor(this, Nsize) 
     class(MyType), intent(inout) :: this 
     integer, intent(in) :: Nsize 
     select type(this) 
     type is(MyTypeR) 
      allocate(this%AllData(Nsize))   
     type is(MyTypeI) 
      allocate(this%AllData(Nsize)) 
     endselect 
    endsubroutine 
endmodule poly 

! Algebra subroutine 
module Operation 
    contains 
    subroutine Square(Array) 
     class(*), intent(inout) :: Array(:) 
     select type(Array) 
     class is(real(8)) 
      Array = Array**2 
     class is(complex(8)) 
      Array = Array**2 
     endselect 
    endsubroutine Square 
endmodule Operation 

! Main 
program test 
    use poly 
    use Operation 
    class(MyType), allocatable :: t1, t2 
    integer :: i 
    logical :: IfComplex = .true. 

    if(IfComplex) then 
     allocate(MyTypeI::t1) 
    else 
     allocate(MyTypeR::t1) 
    endif 
    call t1%Constructor(4) 
    call Square(t1%AllData) 
endprogram test 

접근 B (무제한 다형성 할당 가능한 변수)

은 그것을하기 위해서, 나는 두 가지 시도를 대수학 서브 루틴을 두 접근법과 함께 사용합니다. 본질적인 대입 문에서 변수는 다형성이 아니어야합니다. 모든 제안을 주시면 감사하겠습니다.

답변

4

몇 가지 문제가 있습니다.

현재 Fortran에서는 내장 유형을 확장 할 수 없습니다. 내장 유형은 파생 유형 정의의 EXTENDS 지정자에 나타날 수 없습니다.

결과적으로 Fortran 2008에서 언어는 내장 유형이 선택 유형 구문에서 조상 유형이 될 수있는 것으로 가장하지 않습니다. 이 금지는 유형 가드 문의 구문 규칙 (TYPE IS ... CLASS IS 등)에서 암시 적으로 사용됩니다. type-guard-stmt의 CLASS IS 형식은 명시 적으로 derived-type-spec으로 제한됩니다. 내장 유형 이름 사용 제외). 이는 준수하는 Fortran 2008 컴파일러가 구문에 대한 오류 메시지를 발행해야 함을 의미합니다.

(출판으로 그 제한은 포트란 2003 년에 존재하지 않았다,하지만 나중에 포트란 2003 정오표에 추가되었습니다 -. 아마 당신 포트란 2003 컴파일러 공급 업체는 아직 구현에 주변에 도착하지 않은)

에서 Fortran 2003에서는 할당 할 변수 (equals의 왼쪽에있는 것)가 다형성 일 때 본질적인 할당이 허용되지 않았습니다. 다형성 변수에 할당 할 수있는 기능은 Fortran 2008 언어에 추가 된 기능입니다.

위의 두 가지 문제를 해결하려면 Square 서브 루틴의 유형 가드 문을 CLASS IS가 아닌 TYPE IS로 만드십시오. 그 즉시 문제를 넘어

(다음은 주관적이며 궁극적 할 계획에 따라 달라집니다) :

  • 을 더 전형적인 배치가에 대한 것이다 첫 번째 예에서는 두 개의 비 수 타입 바인딩 된 생성자 프로 시저, 하나는 MyTypeR, 다른 하나는 MyTypeI. 대수 연산은 확장이 적절하게 구현되는 MyType 상위의 지연 바인딩입니다.

  • 두 번째 예제의 MyType은 실제로 유용한 역할을 수행하지 않습니다. 할당 가능한 무제한의 다형성 객체를 직접 사용할 수도 있습니다.

+0

위대한 답변. Intrinsic 함수 지원 (할당 포함)이 허용되면 큰 기능입니다. – FortCpp

+0

두 가지 접근 방식에 대한 제안에 감사드립니다. 컴파일 문제가 해결되었습니다. 제가 잠시 동안 실제 (8)과 복잡한 (8)만을 다루고 있다고 가정합시다 (두 번째 접근법에서 몇 가지 세부 사항을 생략했습니다). 어떤 접근 방식이 자신의 의견에 더 낫습니까? – FortCpp

관련 문제