Fortran 2003,选择Type以区分'真实'和'真实阵列'

时间:2014-03-11 03:01:12

标签: oop polymorphism fortran

我的问题是,“可以使用select type块来区分real :: realInputreal :: realArrayInput(:)吗?”很清楚如何使用select type来区分派生类型,但对于我如何(或是否)可以在内在类型上使用它变得不那么清楚。

在Mad Libs形式中,可以在下面填写空格以区分上述输入:

select type (input)
    type is (real)
        print *, "I caught the realInput"
    type is (___________)
        print *, "I caught the realArrayInput"
end select

我发现一些相关帖子并不完全包含我希望的答案:

Select Type Issues

Determining Variable Type

2 个答案:

答案 0 :(得分:3)

没有。 input被声明为数组或标量,即使它是多态的(即使它是无限多态的)。

最近与C TS的进一步互操作性(可能是F201X的一部分)引入了假设等级和RANK内在的概念,它可以做你想要的。但是对于假定的等级对象可以做什么有许多限制。而且无论SELECT TYPE如何仍然只适用于类型。 select类型构造的语法不允许在类型保护语句中指定rank。

显然取决于你真正想要做什么(?)......以及其他人提到的通用接口,在当前Fortran中有一个可以是数组或标量的对象的方法(还有其他可能性)是使用派生类型包装器,它是常见父类型的扩展。然后使用声明为父类型的多态对象(或者可以使用无限多态对象)来引用相关派生类型的对象。

TYPE :: parent
END TYPE parent

TYPE, EXTENDS(parent) :: scalar_wrapper
  REAL :: scalar_component
END TYPE scalar_wrapper

TYPE, EXTENDS(parent) :: array_wrapper
  REAL :: array_component(10)
END TYPE array_wrapper
...

SUBROUTINE what_am_i(object)
  ! Note that object is scalar, but that doesn't tell us 
  ! the rank of the components of the dynamic type of object.
  CLASS(parent), INTENT(IN) :: object
  !****
  SELECT TYPE (object)
  TYPE IS (scalar_wrapper)
    PRINT "('I am a scalar with value ',G0)",  &
        object%scalar_component
  TYPE IS (array_wrapper)
    PRINT "('I am an array with values ',*(G0,:,','))",  &
        object%array_component
  CLASS DEFAULT
    PRINT "('I am not sure what I am.')"
  END SELECT
END SUBROUTINE what_am_i

答案 1 :(得分:2)

只需结合IanH's anwser和MSB的评论并详细解释:您不能使用select type构造来区分真实的标量和真实的数组,因为它们只在中有所不同维度,但不在类型中。当您声明变量input时,您已经“永远”决定它是否具有dimension属性:

class(*) :: input_scalar
class(*), dimension(10) :: input_array

变量稍后取得的值(或指向它所指向的任何对象,如果它是指针),它不能代表具有与其声明中的维度(等级)不同的维度(等级)的东西。

另一方面,您可以使用interface构造(或类型绑定过程中的generic)来区分相同类型但不同等级的对象。下面的示例演示了标量和秩一个整数和实数。

module testmod
  implicit none
  interface typetest
    module procedure typetest0, typetest1
  end interface typetest
contains
  subroutine typetest0(object)
    class(*), intent(in) :: object
    select type(object)
    type is (real)
      print *, "real scalar"
    type is (integer)
      print *, "integer scalar"
    end select
  end subroutine typetest0

  subroutine typetest1(object)
    class(*), dimension(:), intent(in) :: object
    select type(object)
    type is (real)
      print *, "real array"
    type is (integer)
      print *, "integer array"
    end select
  end subroutine typetest1
end module testmod

program test
  use testmod
  implicit none

  integer :: ii
  integer, dimension(10) :: iarray

  call typetest(ii)      ! invokes typetest0
  call typetest(iarray)  ! invokes typetest1

end program test