Reputation: 8140
If you look at the definition of the intrinsic function CEILING
it has an optional parameter KIND
which can be used to force the return value's integer kind.
Would there be any way to implement my own function in Fortran in such a way as to have the kind, or even better the type of the returned value of a function depend on a parameter? I've tried something like this:
program test_kind
use iso_fortran_env
implicit none
integer(kind=int32) :: a
print*, kind(a)
print*, kind(kt(int16))
print*, kind(kt(int32))
contains
function kt(kind)
implicit none
integer, intent(in) :: kind
integer(kind=kind) :: kt
kt = 100
end function kt
end program test_kind
But it fails with the error:
test_kind.f90:12:21:
integer(kind=kind) :: kt
1
Error: Parameter ‘kind’ at (1) has not been declared or is a variable,
which does not reduce to a constant expression
Now I know I can use procedure overloading to have the same name associated with different procedures depending on the types of arguments. But I'm asking whether the type of the return value can depend on the value of an argument.
Upvotes: 3
Views: 1691
Reputation: 724
Or... Pack your functions into a module and have all the flavours of KT.
MODULE KTM
use iso_fortran_env
implicit none
PRIVATE
INTERFACE Kinder
MODULE PROCEDURE kt_byte, kt_int !kt_long, kt_long_long
END INTERFACE Kinder
PUBLIC Kinder
contains
function kt_byte(kind_In)
implicit none
integer(KIND=int8_t), intent(in) :: kind_In
integer(kind=int8_t) :: kt_byte
kt_byte = 100
end function kt_byte
function kt_Int(kind_In)
implicit none
integer(KIND=int16_t), intent(in) :: kind_In
integer(kind=int16_t) :: kt_Int
kt_Int = 200
end function kt_Int
function kt_long(kind_In)
implicit none
integer(KIND=int32_t), intent(in) :: kind_In
integer(kind=int32_t) :: kt_long
kt_long = 400
end function kt_long
function kt_8B(kind_In)
implicit none
integer(KIND=c_long), intent(in) :: kind_In
integer(kind=c_long) :: kt_8B
kt_8B = 800
end function kt_8B
end MODULE KTM
Then use the module where you need the various flavours of the KT function...
program test_kind
use iso_fortran_env
USE KTM !make sure it is in the -I<path> and/or some -L<path> -l<lib>
implicit none
integer(kind=int32) :: a
integer(kind=int16_t) :: b
integer(kind=int8_t) :: c
integer(kind=int64) :: d
integer(kind=c_long) :: e
REAL :: f
print*, kinder(a)
print*, kinder(b)
print*, kinder(c)
print*, kinder(d)
print*, kinder(e)
!The following line will give a compile error
!print*, Kinder(f)
end program test_kind
Or if it is not used in a commonly used library, then put the module ahead of the program and follow it with the program... In a single file.
Upvotes: 1
Reputation: 21451
No. It is not possible in the standard language, as of F2015 draft. The intrinsic procedures are special in this regard.
Dummy arguments that are data objects are always variables in non-intrinsic procedures.
Kind parameters must be given by constant expressions, and variables are not constants. The rules for nominating the type of an object in a scope are practically more restrictive.
Upvotes: 3