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

时间:2017-07-12 16:36:12

标签: fortran parameter-passing type-bounds

无论这个附加文本的形状如何,我都希望将文本添加到标量对象的组件中。

为了尝试这个,我创建了一个元素过程,它有一个元素输入参数但只有一个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)对于INTENT(INOUT)的实际参数ELEMENTAL子例程'add'的虚拟'objA'是标量,但另一个实际参数是数组`

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

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

是否有正确的方法可以将文字添加到obj_A%Message,无论该文字的形状是什么?

1 个答案:

答案 0 :(得分:3)

使用testA子程序时,可以提供数组输入和数组输出[然后以元素方式进行操作]。但是,您尝试将数组输入分配给标量输出(此处: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 )。

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

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 接口以相同的名称提供它们:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 44.26"  preserveAspectRatio="none" class="courbe-blanche">
  <g data-name="Calque 1">
    <path fill="#fff" d="M612 15.25C570 29.2 504.47 43.5 385.2 41.4 278 39.55 113.1 25 0 3.45v40.82h612z"/>
    <path fill="#d1eaf4" d="M612 15.25C570 29.2 504.47 43.5 385.2 41.4 278 39.55 113.1 25 0 3.45V0s192.74 31.35 394.64 31.35C536.2 31.35 612 1.28 612 1.28z"/>
  </g>
</svg>