Ambiguous c_float and real

I’m creating generic procedure for two subs with c_float and real dummy argument.


program main

    use iso_c_binding
    implicit none
    
    interface print_number
        procedure:: print_number_real, print_number_c_float
    end interface
  
    
    call print_number(1.0)
    
    
    contains
    
        subroutine print_number_real(a)
            real:: a
            print*, a
        
        end subroutine
        
        subroutine print_number_c_float(a)
            real(c_float):: a
            print*, a
        
        end subroutine

end program

– GCC version 14.1.0

The compiler complains that “Error: Ambiguous interfaces in generic interface ‘print_number’ for ‘print_number_real’ at (1) and ‘print_number_c_float’ at (2)”.

Is the fortran compiler not able to tell the difference between type “c_float” and intrinsic “real”?

1 Like

Usually not, if they have the same kind integer number, as they do in your case.

1 Like

Welcome to the forum :slight_smile:

No, the compiler interprets “real” as “real(kind=kind(1.0))” and it is highly probable that this kind is the same as c_float - kinds are simply integer numbers, nothing magic about them. Both are single precision (unless you happen to use a compile option to change the default kind).

2 Likes

Thanks @certik and @Arjen. You are right.

I checked the iso_c_binding.f90 in the installation directory, and it says:“INTEGER (KIND=4), PARAMETER :: C_FLOAT = 4”.

Thank you for your help.

1 Like

In the general case there’s no guarantee they would be equal, so there would be some value in a generic interface that could handle the different cases. Is there a way to code it so it would work both in an environment where c_float is the same as the default kind, and where it’s different, without changing the code?

I can think of a preprocessing solution, but otherwise I do not think there is one. Although, you could do something along these lines, if you can spare one precision:

        subroutine print_number_real(a)
            real:: a
            print*, a
        
        end subroutine
        
        ! Sacrifice double precision in case default real and c_float are the same
        subroutine print_number_c_float(a)
            integer, parameter :: cf = merge( kind(1.0d0), c_float, kind(1.0) == c_float ) 
            real(cf):: a
            print*, a
        
        end subroutine

There is work underway for the next revision of the standard that would probably offer a solution for you, but this is still a few years away.