Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

overriding intrinsic operation

Blane_J_
New Contributor I
367 Views

My problem comes in this way:

module proto
    implicit none
    
    public
        
    type, abstract :: tp1
    contains
        private
        generic, public                 :: ge           => sub
        procedure(Isub), pass, deferred :: sub
            
        generic, public                 :: operator(==) => sub
    end type tp1
    
    abstract interface
        function Isub(this, a)
            import tp1

            logical                :: Isub
            class(tp1), intent(in) :: this
            class(*),   intent(in) :: a

        end function Isub
    end interface
    
end module proto
    
module inst
    use proto
    implicit none
    
    private
    public :: tp2
    
    type, extends(tp1) :: tp2
        integer :: s
    contains
        private
        procedure, pass :: sub
    end type tp2
        
contains
    
    function sub(this, a)
        implicit none
            
        logical                :: sub
        class(tp2), intent(in) :: this
        class(*),   intent(in) :: a
        integer                :: tmp
    
        select type(a)
        type is(integer)
            tmp = a
        class default
            tmp = 0
        end select

        if(this % s == tmp)then
            sub = .true.
        else
            sub = .false.
        end if

        return
    end function sub
    
end module inst

program main
    use inst
    
    type(tp2) :: t
    
    if(t ==       12) write(*,*) "yes"    ! FirstLine:  This is bad.
    if(t %    ge(12)) write(*,*) "yes"    ! SecondLine: This is good.
    
end

When comments out the FirstLine in main, compiler says nothing, but When comments out the SecondLine, the FirstLine generates a link error says unresoved external symbol _PROTO_mp_SUB.

And in addtion, if I do not use operator == but another self-defined operator(anyone, here assume .op.), both FirstLine and SecondLine work normally. Did I misused it? Thanks in advance for any suggestion.

0 Kudos
1 Solution
IanH
Honored Contributor II
367 Views

The code is non-conforming, as clarified by interpretation F08/0052.  Different versions of the compiler deal (or fail to deal) with the non-conformance in different ways, and it is plausible that there are still issues - there have been threads about this here in the last few months.

The type tp1 has a private deferred binding `sub`.  Because it is private, outside the module `proto` that binding is inaccessible - it cannot be referenced by name or overridden.  The type tp2 also has a binding called sub, but because the binding of the same name in the parent type is inaccessible, this is a different binding.  The deferred binding in the parent type is not overridden but it is inherited, this inheritance of a deferred binding means that the type tp2 should be abstract.  The compiler should diagnose this with a relevant message - it doesn't, which is a compiler bug, but the link errors that you do see are somewhat of a consequence of the error in the program.

A private deferred binding in a type always means that non-abstract extensions of that type cannot be defined outside of the module (or its descendants) that has the type with a private deferred binding.

If you make the sub binding public in type tp1, then things perhaps work as you expect.

(The code is also non-conforming, in that function sub ends up referencing the undefined variable `this%s`.)

View solution in original post

0 Kudos
2 Replies
IanH
Honored Contributor II
368 Views

The code is non-conforming, as clarified by interpretation F08/0052.  Different versions of the compiler deal (or fail to deal) with the non-conformance in different ways, and it is plausible that there are still issues - there have been threads about this here in the last few months.

The type tp1 has a private deferred binding `sub`.  Because it is private, outside the module `proto` that binding is inaccessible - it cannot be referenced by name or overridden.  The type tp2 also has a binding called sub, but because the binding of the same name in the parent type is inaccessible, this is a different binding.  The deferred binding in the parent type is not overridden but it is inherited, this inheritance of a deferred binding means that the type tp2 should be abstract.  The compiler should diagnose this with a relevant message - it doesn't, which is a compiler bug, but the link errors that you do see are somewhat of a consequence of the error in the program.

A private deferred binding in a type always means that non-abstract extensions of that type cannot be defined outside of the module (or its descendants) that has the type with a private deferred binding.

If you make the sub binding public in type tp1, then things perhaps work as you expect.

(The code is also non-conforming, in that function sub ends up referencing the undefined variable `this%s`.)

0 Kudos
Blane_J_
New Contributor I
367 Views

Thanks lanH, your explanation is clear enough and I think as it is called an abstract type, all entities within it should always be public to descendants. so only make overridens that override the deferred bindings private should always be a good solution.

0 Kudos
Reply