0

Mac OS X 10.8.2でPGIFortranコンパイラバージョン12.10-0を使用して、コードを保存するための汎用二重リンクリストをFortranに実装したいと思います。これが私のプロトタイプで、3つのファイルが含まれています。

--->ファイル1:

! ----------------------------------------------------------------------------
! Description: 
! 
!   This module provides several basic data structures, e.g. double linked list. 
! 
! Authors: 
! 
!   Li Dong <dongli@lasg.iap.ac.cn> - 2012-11-11 
! ----------------------------------------------------------------------------

module basic_data_structure 

    implicit none 

    private 

    public list_elem_t, list_t 

    type list_elem_t 
        class(list_elem_t), pointer :: prev, next 
    end type list_elem_t 

    type list_t 
        integer :: num_elem = 0 
        class(list_elem_t), pointer :: head, tail 
    contains 
        procedure :: append => list_append 
        procedure :: insert => list_insert 
        procedure :: final => list_final 
    end type list_t 

contains 

    ! ------------------------------------------------------------------------
    ! Description: 
    ! 
    !   The following list_* are the type-bound procedures of double linked 
    !   list data structure. 
    ! 
    ! Authors: 
    ! 
    !   Li Dong - <dongli@lasg.iap.ac.cn> - 2012-11-11 
    ! ------------------------------------------------------------------------

    subroutine list_append(this, elem) 

        class(list_t), intent(inout) :: this 
        class(list_elem_t), intent(out), pointer :: elem 

        character(50), parameter :: sub_name = "list_append" 

        allocate(elem)
        if (this%num_elem == 0) then
            this%head => elem
            nullify(this%head%prev)
            this%tail => this%head
        else
            this%tail%next => elem
            elem%prev => this%tail
            this%tail => elem
        end if
        nullify(this%tail%next) 
        this%num_elem = this%num_elem+1 

    end subroutine list_append 

    subroutine list_insert(this, existed_elem, elem) 

        class(list_t), intent(inout) :: this 
        class(list_elem_t), intent(inout), pointer :: existed_elem 
        class(list_elem_t), intent(out), pointer :: elem 

        character(50), parameter :: sub_name = "list_insert" 

        ! TODO: Check existed_elem is allocated. 
        ! TODO: Check existed_elem is one element of this. 

        allocate(elem) 
        elem%prev => existed_elem 
        elem%next => existed_elem%next 
        if (associated(existed_elem%next)) then 
            existed_elem%next%prev => elem 
            existed_elem%next => elem 
        end if 
        this%num_elem = this%num_elem+1 

    end subroutine list_insert 

    subroutine list_final(this) 

        class(list_t), intent(inout) :: this 

        class(list_elem_t), pointer :: elem 
        integer i 

        elem => this%head 
        do i = 1, this%num_elem-1 
            elem => elem%next 
            if (associated(elem%prev)) deallocate(elem%prev) 
        end do 
        deallocate(this%tail) 

    end subroutine list_final 

end module basic_data_structure

--->ファイル2

! ----------------------------------------------------------------------------
! Description: 
! 
!   This module manages the model variables. 
! 
! Authors: 
! 
!   Li Dong <dongli@lasg.iap.ac.cn> - 2012-11-11 
! ----------------------------------------------------------------------------

module variable 

    use basic_data_structure 

    implicit none 

    private 

    public variable_register 
    public variable_final 

    public var_t, var_1d_t 

    integer, parameter :: A_GRID = 1 
    integer, parameter :: B_GRID = 2 
    integer, parameter :: C_GRID = 3 

    type, extends(list_elem_t) :: var_t 
        character(10) name 
        character(50) long_name 
        character(20) units 
        integer grid_type 
    end type var_t 

    type, extends(var_t) :: var_1d_t 
        real(8), allocatable :: array(:) 
    end type var_1d_t 

    type, extends(var_t) :: var_2d_t 
        real(8), allocatable :: array(:,:) 
    end type var_2d_t 

    type(list_t) var_list 

contains 

    ! ------------------------------------------------------------------------
    ! Description: 
    ! 
    !   Register a variable. 
    ! 
    ! Authors: 
    ! 
    !   Li Dong <dongli@lasg.iap.ac.cn> - 2012-11-11 
    ! ------------------------------------------------------------------------

    subroutine variable_register(name, var) 

        character(*), intent(in) :: name 
        class(var_t), intent(inout), pointer :: var 

        character(50), parameter :: sub_name = "variable_register" 

        select type (var) 
        type is (var_1d_t) 
            print *, "---> Register a 1D variable """//trim(name)//"""." 
        type is (var_2d_t) 
            print *, "---> Register a 2D variable """//trim(name)//"""." 
        type is (var_t) 
            print *, "---> Oh, no!" 
        class default 
            print *, "---> Unknown variable type """//trim(name)//"""." 
        end select 

        call var_list%append(var) 

        ! -------------------------------> PROBLEM IS HERE 
        select type (var) 
        type is (var_1d_t) 
            print *, "---> Register a 1D variable """//trim(name)//"""." 
        type is (var_2d_t) 
            print *, "---> Register a 2D variable """//trim(name)//"""." 
        type is (var_t) 
            print *, "---> Oh, no!" 
        class default 
            print *, "---> Unknown variable type """//trim(name)//"""." 
        end select 

    end subroutine variable_register 

    ! ------------------------------------------------------------------------
    ! Description: 
    ! 
    !   Clean the registered variables. 
    ! 
    ! Authors: 
    ! 
    !   Li Dong <dongli@lasg.iap.ac.cn> - 2012-11-11 
    ! ------------------------------------------------------------------------

    subroutine variable_final() 

        character(50), parameter :: sub_name = "variable_final" 

        call var_list%final() 

    end subroutine variable_final 

end module variable

--->ファイル3:

program test_variable 

    use variable 

    implicit none 

    type(var_1d_t), pointer :: a 

    call variable_register("a", a) 
    call variable_final() 

end program test_variable

実行結果は次のとおりです。

MacBook-Pro:sandbox dongli$ ./test_variable 
 ---> Register a 1D variable "a". 
 ---> Unknown variable type "a". 

リストを追加した後、varタイプが不明なタイプに変更されるのはなぜですか?期待される機能をどのように実現できますか?

4

1 に答える 1

1

F2008 12.5.2.5 p2は、ポインターと割り当て可能なダミー引数に関して、「関連するダミー引数が多形である場合に限り、実際の引数は多形である必要があります...」と述べています。

variable_registerのダミー引数varは、ポリモーフィックポインターです。aメインプログラムの実際の引数はそうではありません。プログラムにエラーがあり、Fortranプロセッサはこのエラーを診断する必要はありません(ただし、この特定のケースでは、これを検出するのは簡単です)。

F2008 12.5.2.5の同じ段落は、「...実際の引数の宣言されたタイプは、ダミーの引数の宣言されたタイプと同じでなければならない」と続けています。list_appendのダミー引数は、宣言された型のポリモーフィックポインタですlist_elem_t。実際の引数は、宣言された型のポリモーフィックポインタですvar_t。それらは同じではありません-あなたのプログラムはさらにエラーがあります。繰り返しになりますが、Fortranプロセッサはこれを診断する必要はありませんが、この場合は簡単に診断できるはずです。

プログラムにエラーがあるため、何が起こる可能性もありますが、関連する注記では、elemlist_appendへの引数が宣言されていINTENT(OUT)ます。つまり、その手順の開始時に、elemのポインターの関連付けステータスは未定義です。つまり、elemが何を指しているのか(またはその動的タイプ)がわかりません。次に、list_appendのallocateステートメントは、宣言されたタイプのオブジェクトを割り当てますelem。つまり、list_elem_t(最終的な引数であるポインターと「中間」引数であるポインターが、それぞれの宣言されたタイプの親に向けられているという事実)上記の12.5.2.5で引用した制限が存在する理由-F2008の注12.27を参照してください。選択したタイプはそのオプションをチェックしません。

于 2012-11-15T02:10:41.567 に答える