Reputation: 855
I want to call a subroutine depending on the kind value of the argument. I tried the following, but I get an error.
parameter, integer:: kind=4
integer(kind):: variable
if (kind==8) then
call routine_kind8(variable)
elseif(kind==4) then
call routine_kind4(variable)
endif
I get the following error:
call routine_kind8(variable)
1
Error: Type mismatch in argument 'variable' at (1); passed INTEGER(4) to INTEGER(8)
How can I prevent this from happening?
The subroutine routine_kind8
could be defined is defined as follows:
subroutine routine_kind8(variable)
implicit none
integer(8), intent(in):: variable
call api_write_data_to_file(variable)
end subroutine routine
where api_write_data_to_file
is a function from an api which can accept any kind type. However, I can not dynamically define kind types in the argument list. Therefore it is necessary for me to call different versions of this routine, based on the kind type of the variable.
I can or more precisely don't want to call api_write_data_to_file
directly. Instead I want to call it inside routine_kind8
Upvotes: 1
Views: 619
Reputation: 18098
If you are using a fairly recent compiler, you might look into unlimited polymorphism to achieve your goal. Then, you can even pass different types to the same subroutine:
module test_mod
contains
subroutine print_type( input )
class(*),intent(in) :: input
select type(input)
type is (integer(kind=4))
print *, "Got an integer of kind 4"
type is (integer(kind=8))
print *, "Got an integer of kind 8"
type is (real)
print *, "Got a real number"
type is (complex)
print *, "Got a complex number"
end select
end subroutine
end module
program test
use test_mod
call print_type( 1_4 )
call print_type( 1_8 )
call print_type( 1. )
call print_type( (1.,1.) )
end program
You can use the select case
statement to further decide how to proceed and which further subroutines to call. Or, skip the select case
statement alltogether and pass everything to api_write_data_to_file
directly.
Alternatively you could create an interface
block for api_write_data_to_file()
in the same manner:
interface api_write_data_to_file
subroutine api_write_data_to_file(variable)
class(*),intent(in) :: variable
end subroutine
end interface
Then, you do not need a wrapper to call api_write_data_to_file()
.
Upvotes: 6
Reputation: 32366
An if
construct with constant expression conditions is not the same thing as conditional compilation. Dead code elimination also doesn't apply to ensure that only one of the blocks is processed.
What that means is that, when you have the declaration integer(kind=4) variable
you do still have a line saying
call routine_kind8(variable)
which is expecting an integer(kind=8)
argument.
You could use conditional compilation with a pre-processor, for example, but a far better approach could be to use generic resolution:
parameter, integer:: kind=4
integer(kind):: variable
call routine(variable)
where around the creation of routine_kind4
and routine_kind8
there has been something like
interface routine
procedure routine_kind4 ! Defined at some point
procedure routine_kind8
end interface
Upvotes: 0