在类型绑定元素过程中作为意图(inout)传递的对象



我想向标量对象的组件添加文本,无论此附加文本的形状如何。

为了尝试这个,我创建了一个元素过程,它有一个元素输入参数,但只有一个intent(inout)参数,即传递的对象。

这是MWE:

module add_mod
implicit none
type obj_A
character(len=:), allocatable    :: Message
contains
procedure, pass(objA) :: add
procedure, pass(objA) :: write
end type
contains
elemental subroutine add( objA, text )
implicit none
class(obj_A), intent(inout)                   :: objA
character(len=*), intent(in)                 :: text
objA%Message=objA%Message//text
end subroutine add
impure elemental subroutine write( objA, text )
implicit none
class(obj_A), intent(in)                   :: objA
character(len=*), intent(in)                 :: text
print*,'write ', text
end subroutine write
end module

program test
use add_mod
implicit none
type(obj_A) :: testA

call testA%add('toto')
print *, testA%Message
! call testA%add( ['toto','abcc','d,ef'] )
print *, testA%Message
call testA%write( ['toto','abcc','d,ef'] )
end program

如果我call testA%add( ['toto','abcc','d,ef'] )评论该行,它工作正常。但是如果我取消评论,我在编译过程中会出现错误

错误:(1( 处的实际参数用于 ELEMENTAL 子例程"add"的 INTENT(INOUT( 虚拟"objA"是一个标量,但另一个实际参数是一个数组

我理解为什么testA%write调用是正确的,这是由于传递对象的intent(in);在这种情况下,编译器理解一个参数是标量形状,另一个参数是数组形状。

对于testA%add( ['toto','abcc','d,ef'] ),我也明白它需要一个intent(inout)obj_A形状的数组,因为输入的文本是一个标量。因此,这不是正确的方法。

有没有一种正确的方法可以在obj_A%Message中添加文本,无论这个文本的形状是什么?

使用elemental子例程时,可以提供数组输入和数组输出 [然后操作以逐元素的方式发生]。但是,您正在尝试将数组输入分配给标量输出(此处:testA(。

如果使用大小为 3 的数组输出,则例程将按预期工作:

module add_mod
implicit none
type obj_A
character(len=:), allocatable    :: Message
contains
procedure, pass(objA) :: add
end type
contains
elemental subroutine add( objA, text )
implicit none
class(obj_A), intent(inout)                   :: objA
character(len=*),intent(in)                   :: text
objA%Message=objA%Message//text
end subroutine add
end module
program test
use add_mod
implicit none
type(obj_A) :: testA
type(obj_A) :: testB(3)
call testA%add('toto')
print *, testA%Message
call testB%add( ['toto','abcc','d,ef'] )
print *, testA%Message
print *, testB(1)%Message, testB(2)%Message, testB(3)%Message
end program

下面是将字符串数组添加到标量输出的版本。请注意,由于这个星座,子程序不能elemental。但是,可以pure

module add_mod
implicit none
type obj_A
character(len=:), allocatable    :: Message
contains
procedure, pass(objA) :: add
end type
contains
pure subroutine add( objA, text )
implicit none
class(obj_A), intent(inout)                   :: objA
character(len=*), dimension(:), intent(in)    :: text
integer :: i
do i=1,size(text)
objA%Message=objA%Message//text(i)
enddo !i
end subroutine add
end module
program test
use add_mod
implicit none
type(obj_A) :: testA
call testA%add(['toto'])
print *, testA%Message
call testA%add( ['toto','abcc','d,ef'] )
print *, testA%Message
end program

最后,要同时支持标量参数和数组参数,您需要提供并绑定多个实现,然后使用generic接口以相同的名称提供它们:

module add_mod
implicit none
type obj_A
character(len=:), allocatable    :: Message
contains
generic :: add => add1, add2
procedure, pass(objA) :: add1
procedure, pass(objA) :: add2
end type
contains
pure subroutine add1( objA, text )
implicit none
class(obj_A), intent(inout)                   :: objA
character(len=*), dimension(:), intent(in)    :: text
integer :: i
do i=1,size(text)
objA%Message=objA%Message//text(i)
enddo 
end subroutine add1
pure subroutine add2( objA, text )
implicit none
class(obj_A), intent(inout)                   :: objA
character(len=*), intent(in)                  :: text
objA%Message=objA%Message//text
end subroutine add2
end module
program test
use add_mod
implicit none
type(obj_A) :: testA
call testA%add('toto')
print *, testA%Message
call testA%add( ['toto','abcc','d,ef'] )
print *, testA%Message
end program

最新更新