问题
Suppose I have a subroutine:
subroutine foo(x, Nx)
implicit none
integer, intent(IN) :: x
integer, intent(IN) :: Nx
select case(x)
case (1)
write(*,*) "Minimum value"
case (Nx)
write(*,*) "Maximum value"
case default
write(*,*) "Somewhere in-between"
end select
end subroutine foo
Suppose my driver looks like this:
program main
implicit none
interface
subroutine foo(x,Nx)
integer, intent(IN) :: x
integer, intent(IN) :: Nx
end subroutine foo
end interface
integer, parameter :: Nx = 100
integer :: x
call foo(20, Nx)
end program main
The above program will not compile because in the subroutine, case (Nx)
is invalid. Specifically, ifort 16 gives the following error:
error #6601: In a CASE statement, the case-value must be a constant expression.
In other words, even though Nx is effectively declared as a subroutine constant via intent(IN)
, it needs to be either a literal constant or parameter
of type integer
.
Are there any ways to make the case statement accept Nx
as the constant parameter we know it to be? Is there some way to declare Nx
to be a passed-in parameter
?
I realize that in this simple, short example, an if-then-elseif-else-end block would suffice, but then I wouldn't know the answer to this question. :-)
回答1:
Just use an if statement. A subroutine argument (which you call parameter) is certainly not a parameter (named constant). The intent(in)
doesn't make it effectively a parameter, it is just a promise you will not change it, but there are ways to circumvent that. The case statement needs a compile-time constant.
回答2:
You ask whether there is a way to "accept Nx as the constant parameter we know it to be?". We don't know that Nx forms a constant expression, and we indeed know that it doesn't.
The only way for Nx
to be a constant expression is for Nx
to be a named constant. Being a named constant is incompatible with being a dummy argument, even one which is argument associated, with intent(in)
or no intent
attribute, with a named constant.
Conceptually, the subroutine foo
is an external procedure as far as the main program is concerned (there's an interface block). This means that one would expect it to be compiled as a stand-alone thing, being linked in at that later stage. It should be valid regardless of its ultimate use. [That said, even when it isn't an external procedure the first part still holds as far as the language specification goes.]
Naturally, there are other ways to have Nx
a named constant in the subroutine if you don't want to rewrite this using an if
construct.
来源:https://stackoverflow.com/questions/32553490/passing-parameter-as-parameter-in-fortran-90