【问题标题】:Fortran 2003, Select Type to Differentiate 'real' from 'real array'Fortran 2003,选择类型以区分“真实”和“真实数组”
【发布时间】:2014-04-14 11:13:18
【问题描述】:

我的问题是,“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

【问题讨论】:

  • 也许您可以通过将变量传递给elemental 过程,或者为两个过程编写通用接口来实现您的目标。
  • 你能用rank内在函数检查排名吗?

标签: oop polymorphism fortran


【解决方案1】:

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

最近与 C TS(可能是 F201X 的一部分)的进一步互操作性引入了假定等级的概念和 RANK 内在,这可能会做你想要的。但是对于假设的等级对象可以做什么有很多限制。不管那个 SELECT TYPE 仍然只适用于类型。选择类型构造的语法根本不允许在类型保护语句中指定等级。

显然取决于您实际想要做什么(?)......除了其他人提到的通用接口之外,一种在当前 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

【讨论】:

  • 谢谢伊恩。你能确认我理解你的意思吗?听起来 type is (real) 是有效的 Fortran,但 both real :: realInput real :: realArrayInput(:) 将被 select type 块视为 real,即两者会导致上面的程序(我刚刚编辑它以使这个评论清楚)打印“我抓住了 realInput”。如果这不是你的意思,你能澄清一下吗?
  • 你的理解是正确的。 SELECT TYPE 仅适用于类型。
【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多