2016-05-09 47 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语句,也可以分配可分配的东西 - 对可分配变量的简单分配可能会导致它被分配。您无法处理这些情况下的错误消息。还有大量的编码结构会导致编译器为其自身的内部需求“分配”内存,同样,你也无法处理错误。在较低的级别上,操作系统实际满足内存程序请求的方式也对您有所帮助 - 系统可能会被过度使用,操作系统不会向进程报告内存不足错误,直到分配完成后声明已经完成。结合起来,在可用内存非常低且尝试分配小对象失败的情况下,编译器可能没有足够的内存来执行错误报告代码。还有一个问题是,编译器的运行时可以更好地了解失败的原因以及程序的状态,它可以通过简单的整数代码和字符消息进行通信 - 例如,编译器的运行时可以为用户提供堆栈跟踪或者类似的,除了它可以传递回该程序的任何消息之外。

所有的,对于小的分配,程序员提供的错误报告可能不是很有成效。

对于较大的分配可能是非常值得的,特定故障的概率较高,并且原因很可能可以成功传达并采取行动(“您的问题维度太大了!请将其缩小并且再试一次......“)。