Is it safe to do the other-way around? For example declaring a variable a real*4 and initialize it as x = 0.d0? There will be a type conversion or, perhaps, the compiler just fixes that?
(not that I want to do that for any reason, just trying to understand the consequences).
With Fortran, you are more likely (even if not all that prevalent) to come across codes with the following than functions such as zero/zeros and one/ones that are more common with other languages such as Julia:
real(dp), parameter :: ZERO = 0.0_dp
real(dp), parameter :: ONE = 1.0_dp
..
x = ZERO ! here x can be of any rank
x = ONE ! -ditto-
sqrt is a generic intrinsic such that the kind of the result is the same as that of the actual argument. The standard “way” will be to use it instead of dsqrt.
Note in Fortran, the kind is separate from type per se e.g., objects that represent floating-point quantities are of real intrinsic type, as you know. But they can be of different kinds.
Quite a few of the generic intrinsics usually tend to have an optional parameter (dummy argument in Fortran parlance) to indicate the kind of the result. Though not SQRT, LOG, etc. where it’s better left to the programmer to do so using conversion intrinsics such as REAL. See a related discussion at Intel Fortran forum.
Maybe the responses so far have given you what you need, but to answer the original question posed, it is not possible to write a function that behaves like
integer, parameter :: dp = kind(0d0)
real(dp) :: x
x = zero(dp)
The reason is that a dummy argument cannot the kind parameter of a function result or other dummy argument. That is, the following is not valid Fortran:
function zero(k)
integer, intent(in) :: k
real(kind=k) :: zero
zero = real(0, kind=k)
end function
However, one can come close with the alternative
integer, parameter :: dp = kind(0d0)
real(dp) :: x
x = zero(x)
where zero would be a generic name for several functions, e.g.,
real(dp) function zero_dp(x) result(z)
real(dp), intent(in) :: x
z = 0._dp
end function
The strategy here is to resolve the desired return type using an argument with the desired kind, rather than passing the kind parameter itself.