我的问题是,“可以使用select type
块来区分real :: realInput
和real :: 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
我发现一些相关帖子并不完全包含我希望的答案:
答案 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