【问题标题】:Nested derived type with overloaded assignment具有重载赋值的嵌套派生类型
【发布时间】:2013-09-28 06:38:49
【问题描述】:

我有一个派生类型 (wrapper),其中包含另一个派生类型 (over)。对于后者,赋值运算符已被重载。由于派生类型的分配是按默认组件进行的,我希望分配wrapper 的两个实例会在某些时候调用over 的重载分配。但是,使用下面的程序,似乎并非如此。仅当我还重载了 wrapper 的赋值时才调用重载的赋值,该赋值包含 over 实例之间的 explicit 赋值(通过取消注释代码行)。为什么?我觉得这有点违反直觉。有什么办法可以避免包装类型的重载?

module test_module
  implicit none

  type :: over
    integer :: ii = 0
  end type over

  type :: wrapper
    type(over) :: myover
  end type wrapper

  interface assignment(=)
    module procedure over_assign
    !module procedure wrapper_assign
  end interface assignment(=)

contains

  subroutine over_assign(other, self)
    type(over), intent(out) :: other
    type(over), intent(in) :: self

    print *, "Assignment of over called"
    other%ii = -1

  end subroutine over_assign

  !subroutine wrapper_assign(other, self)
  !  type(wrapper), intent(out) :: other
  !  type(wrapper), intent(in) :: self
  !
  !  other%myover = self%myover
  !
  !end subroutine wrapper_assign

end module test_module

program test
  use test_module
  implicit none

  type(wrapper) :: w1, w2

  print *, "Assigning wrapper instances:"
  w2 = w1

end program test

【问题讨论】:

    标签: fortran fortran95 fortran2003


    【解决方案1】:

    这种 [不幸的] 情况是语言规则 (F90+) 对派生类型进行内在赋值的结果。详细信息在 F2008 7.2.1p13 中有详细说明。总而言之,派生类型的内在赋值(在 wrapper_assign 特定注释掉的情况下发生的赋值)不会为任何派生类型的组件调用非类型绑定定义的赋值。在 F90/F95 中,如果您想在组件层次结构的某个较低级别定义分配,那么您需要为所有父组件定义分配,直到基础对象。

    F2003 为语言添加了类型绑定定义的赋值,并且这个由派生类型的内在赋值调用的。使用它而不是指定定义分配的独立通用形式。 (这也避免了类型名称可访问但定义的分配过程不可访问的潜在问题。)

    【讨论】:

    • 非常感谢 Ian,我不知道派生类型的内在分配的这些限制。你的建议确实有效。不幸的是,我使用最多的编译器似乎没有正确实现它,因为它没有调用over 的赋值,即使我将其声明为类型绑定过程(我将提交错误报告)。但是我现在尝试过的其他编译器确实按照您的描述进行。
    • 你真的使用正确的语法GENERIC :: ASSIGNMENT(=) => wrapper_assign吗?
    • @VladimirF:是的,我想我做到了。我发布我的解决方案只是为了完成线程。我已经尝试过 NAG 5.3 和 GFortran 4.9.0,两者都达到了预期的效果。另一方面,Intel 13.1.3 编译代码时不会报错,但在程序执行期间不会调用重载赋值。
    • 在 Intel 14.0 中为我工作。
    【解决方案2】:

    只是为了完成线程:对我有用的IanH's suggestion 的具体实现(请赞成他的原始答案而不是这个)是以下一个:

    module test_module
      implicit none
    
      type :: over
        integer :: ii = 0
      contains
        procedure :: over_assign
        generic :: assignment(=) => over_assign
      end type over
    
      type :: wrapper
        type(over) :: myover
      end type wrapper
    
    contains
    
      subroutine over_assign(other, self)
        class(over), intent(out) :: other
        class(over), intent(in) :: self
    
        print *, "Assignment of over called"
        other%ii = -1
    
      end subroutine over_assign
    
    end module test_module
    
    
    program test
      use test_module
      implicit none
    
      type(wrapper) :: w1, w2
    
      print *, "Assigning wrapper instances:"
      w2 = w1
    
    end program test
    

    【讨论】:

    • class(over), intent(in) :: self 应该是 TYPE(over), intent(in) :: self 否则派生类型将不允许覆盖此操作。
    猜你喜欢
    • 2013-10-07
    • 2011-11-13
    • 2014-07-25
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    相关资源
    最近更新 更多