Вложенный производный тип с перегруженным назначением
У меня есть производный тип (wrapper
) содержащий другой производный тип (over
). Для последнего оператор присваивания был перегружен. Поскольку присвоение производных типов происходит по умолчанию по компонентам, я ожидаю, что назначение двух экземпляров wrapper
будет вызывать перегруженное назначение для over
в какой-то момент. Однако, используя программу ниже, это не похоже на случай. Перегруженное назначение вызывается только в том случае, если я также перегружаю назначение для wrapper
содержащий явное присваивание между экземплярами over
(раскомментируя закомментированные строки кода). Зачем? Я нахожу это несколько противоречивым. Есть ли способ избежать перегрузки в типе упаковки?
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
2 ответа
Эта [неудачная] ситуация является следствием правил языка (F90+) для внутреннего присваивания производных типов. Детали изложены в F2008 7.2.1p13. Таким образом, внутреннее присваивание производных типов (присваивание, которое происходит с закомментированным конкретным атрибутом wrapper_assign) не вызывает присвоения, не связанного с типом, для любых компонентов производного типа. В F90/F95, если вы хотите определить назначение на каком-то более низком уровне иерархии компонентов, вам необходимо определить назначение для всех родительских компонентов вплоть до базового объекта.
F2003 добавило определенное присвоение языку с привязкой к типу, и это вызывается внутренним присваиванием производных типов. Используйте это вместо автономной универсальной формы указания определенного назначения. (Это также позволяет избежать потенциальной проблемы с доступностью имени типа, но недоступна определенная процедура присваивания.)
Просто чтобы завершить тему: конкретная реализация предложения IanH (пожалуйста, опишите его первоначальный ответ, а не этот), который работал для меня, была следующей:
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