2013-09-28 19 views
7

Mam typ wyprowadzony (wrapper) zawierający inny typ pochodny (over). W tym ostatnim przypadku operator przypisania został przeciążony. Ponieważ przypisanie typów pochodnych odbywa się zgodnie z domyślnym podziałem na składniki, można oczekiwać, że przypisanie dwóch wystąpień wrapper spowoduje w pewnym momencie wywołanie przeciążonego przypisania dla over. Jednakże, używając poniższego programu, nie wydaje się, aby tak było. Przeciążone zadanie jest wywoływane tylko wtedy, gdy przeciążam zadanie przypisane do wrapper, zawierające wyraźne przypisanie między instancjami over (przez odkomentowanie skomentowanych linii kodu). Czemu? Uważam, że jest to trochę sprzeczne z intuicją. Czy istnieje sposób na uniknięcie przeciążenia w rodzaju owijania?Zagnieżdżony typ pochodny z przeciążonym przypisaniem

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 

Odpowiedz

8

Ta [niefortunna] sytuacja jest konsekwencją reguł języka (F90 +) dla wewnętrznego przypisania typów pochodnych. Szczegóły podano w F2008 7.2.1p13. Jako podsumowanie, wewnętrzne przypisanie typów pochodnych (przypisanie, które ma miejsce z pominiętym specyfikiem wrapper_assign) nie wywołuje zdefiniowanego przypisania związanego z typem niepowiązanym dla każdego komponentu, które są typu pochodnego. W F90/F95, jeśli chcesz zdefiniować przypisanie na niższym poziomie hierarchii komponentów, musisz mieć zdefiniowane przypisanie dla wszystkich komponentów nadrzędnych do obiektu podstawowego.

F2003 Dodany typ przypisany zdefiniowany przypisanie do języka i ten jest wywoływany przez wewnętrzne przypisanie typów pochodnych. Użyj tego zamiast samodzielnej ogólnej formy określania zdefiniowanego przypisania. (Zapobiega to również potencjalnemu problemowi z dostępną nazwą typu, ale zdefiniowana procedura przyporządkowania nie jest dostępna.)

+0

Dziękuję bardzo Ian, nie wiedziałem o tych ograniczeniach dla wewnętrznego przypisania typów pochodnych. Twoja sugestia rzeczywiście działa. Niestety, kompilator, którego używam najbardziej, nie wydaje się poprawnie tego implementować, ponieważ nie wywołuje ono przypisania 'over', nawet jeśli deklaruję je jako procedurę typu type (zagram raport o błędzie). Ale inne kompilatory, które wypróbowałem, rzeczywiście robią to, co opisujesz. –

+0

Czy naprawdę używasz poprawnej składni 'GENERIC :: ASSIGNMENT (=) => wrapper_assign'? –

+0

@VladimirF: Tak, zgaduję, że tak. Zamieściłem swoje rozwiązanie tylko po to, aby uzupełnić wątek. Próbowałem NAG 5.3 i GFortran 4.9.0, oba z oczekiwanymi wynikami. Z kolei procesor Intel 13.1.3 kompiluje kod na podstawie skarg, ale przeciążone zadanie nie jest wywoływane podczas wykonywania programu. –

1

Wystarczy, aby zakończyć wątek: konkretna realizacja IanH's suggestion (proszę posłuchać jego oryginalnej odpowiedzi, a nie tej), która pracował dla mnie był następujący:

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