2016-05-09 43 views
1

目標是創建一個可以處理任何類型的一級分配的分配例程。我們的代碼庫可以通過標準化錯誤捕獲進行單一調用。Fortran中的多態陣列分配例程

編譯器錯誤如下:

generic_allocation.f08:32:27: 

     call myAllocator (array_int, source_int, lambda) 
          1 
Error: Actual argument to ‘myarray’ at (1) must be polymorphic 
generic_allocation.f08:33:27: 

     call myAllocator (array_real, source_real, lambda) 
          1 
Error: Actual argument to ‘myarray’ at (1) must be polymorphic 

可以將此代碼來解決?

測試代碼試圖分配一個整數數組,然後一個真正的數組:

module mAllocator 
    implicit none 
contains 
    subroutine myAllocator (myArray, source_type, lambda) 
     class (*), allocatable, intent (inout) :: myArray (:) 
     class (*),    intent (in) :: source_type 
     integer,     intent (in) :: lambda 

     integer     :: alloc_status = 0 
     character (len = 512) :: alloc_message = '' 
      allocate (myArray (1 : lambda), source = source_type, stat = alloc_status, errmsg = alloc_message) 
      if (alloc_status /= 0) then 
       write (*, "(' allocation errmsg = ', g0, '.')") trim (alloc_message) 
       stop 'Fatal error in subroutine myAllocator' 
      end if 
    end subroutine myAllocator 
end module mAllocator 

program generic_allocation 

    use mAllocator, only : myAllocator 

    implicit none 

    integer, parameter :: lambda = 10 
    integer, parameter :: source_int = 1 
    real, parameter :: source_real = 1.0 

    integer, allocatable :: array_int (:) 
    real, allocatable :: array_real (:) 
     call myAllocator (array_int, source_int, lambda) 
     call myAllocator (array_real, source_real, lambda) 
end program generic_allocation 

代碼的第一個版本,如圖FORTRAN: polymorphism allocation在一個select type構建依賴。使用的另一個參考是Fortran polymorphism, functions and allocation

的gfortran版本是6.0

$ gfortran -v 
Using built-in specs. 
COLLECT_GCC=gfortran 
COLLECT_LTO_WRAPPER=/opt/gnu/6.0/libexec/gcc/x86_64-pc-linux-gnu/6.0.0/lto-wrapper 
Target: x86_64-pc-linux-gnu 
Configured with: ./configure --prefix=/opt/gnu/6.0 --enable-languages=c,c++,fortran,lto --disable-multilib --disable-werror 
Thread model: posix 
gcc version 6.0.0 20160227 (experimental) (GCC) 
+2

*目標是創建一個可以處理任何類型的一級分配的分配例程。*這不是「allocate」提供的嗎? –

回答

4

你所遇到的語言刻意限制,落實到位,以防止分配一個對象以某種類型不匹配聲明的類型實際的程序論據。考慮如果分配器將與array_int相對應的僞參數分配爲REAL類型,會發生什麼情況。

你不能用一個單獨的程序來實現你的目標,然而你可能能夠避免編寫一段源代碼,然後你將INCLUDE包含到多個過程的主體中,每個聲明的類型都有一個),你想處理。

! In AllocateBody.i90 
integer, intent(in) :: lambda 
integer     :: alloc_status 
character (len = 512) :: alloc_message 
allocate (myArray (1 : lambda), & 
    source = source_type, & 
    stat = alloc_status, & 
    errmsg = alloc_message) 
if (alloc_status /= 0) then 
    write (*, "(' allocation errmsg = ', g0, '.')") & 
     trim (alloc_message) 
    stop 'Fatal error in subroutine myAllocator' 
end if  


! Elsewhere. 
subroutine my_allocator_integer(myArray, source_type, lambda) 
    integer, intent(out), allocatable :: myArray(:) 
    integer, intent(in) :: source_type 
    include 'AllocateBody.i90' 
end subroutine my_allocator_integer 

subroutine my_allocator_real(myArray, source_type, lambda) 
    real, intent(out), allocatable :: myArray(:) 
    real, intent(in) :: source_type 
    include 'AllocateBody.i90' 
end subroutine my_allocator_real 

subroutine my_allocator_foo(myArray, source_type, lambda) 
    type(foo), intent(out), allocatable :: myArray(:) 
    type(foo), intent(in) :: source_type 
    include 'AllocateBody.i90' 
end subroutine my_allocator_foo 

您可以將所有這些特定的過程放在一個通用名稱的後面。但是,在着手這個之前,請注意,在現代Fortran中,即使沒有ALLOCATE語句,也可以分配可分配的東西 - 對可分配變量的簡單分配可能會導致它被分配。您無法處理這些情況下的錯誤消息。還有大量的編碼結構會導致編譯器爲其自身的內部需求「分配」內存,同樣,你也無法處理錯誤。在較低的級別上,操作系統實際滿足內存程序請求的方式也對您有所幫助 - 系統可能會被過度使用,操作系統不會向進程報告內存不足錯誤,直到分配完成後聲明已經完成。結合起來,在可用內存非常低且嘗試分配小對象失敗的情況下,編譯器可能沒有足夠的內存來執行錯誤報告代碼。還有一個問題是,編譯器的運行時可以更好地瞭解失敗的原因以及程序的狀態,它可以通過簡單的整數代碼和字符消息進行通信 - 例如,編譯器的運行時可以爲用戶提供堆棧跟蹤或者類似的,除了它可以傳遞迴該程序的任何消息之外。

所有的,對於小的分配,程序員提供的錯誤報告可能不是很有成效。

對於較大的分配可能是非常值得的,特定故障的概率較高,並且原因很可能可以成功傳達並採取行動(「您的問題維度太大了!請將其縮小並且再試一次......「)。