Tagging in Fortran (like enum)

Tagging in Fortran (like enum)

Hi,

I would like to tag some pointers to some values, such a definition reminds me the enumeration type of C, such as:

 

 enum ctype { out, cut, in, sp}; 

and we have a pointer (named as type_) that will be allocated for the values above:

 

 ctype *type_;  

in a subroutine I try to tag a pointer such as:

 

if(*nnn->type_==out)
{
}

if(*nnn->type_==cut)
{
}

if(*nnn->type_==in)
{
}

if(*nnn->type_==sp)
{
}
 

How can I rewrite the above tagging in Fortran, should I use  

 integer(selected_int_kind)  
 or
 enum, bind(c) ctype 
? I try both of them but cannot figure out what is wrong... I will appreciate any contribution, suggestion about the problem. Thanks.

6 帖子 / 0 全新
最新文章
如需更全面地了解编译器优化,请参阅优化注意事项

Are you interacting with C code, or are you rewriting something in Fortran exclusively?

If you want an enumeration that lines up exactly with the values and storage that you get in C, then the syntax is:


ENUM, BIND(C)

  ENUMERATOR :: out, cut, in, sp

END ENUM

Note that you don't name the enumeration, just the enumerators. If you want the kind used for the enumerators, then you can just use KIND(out), or similar.

If you are just working in the Fortran world, then you could just declare the integer constants that are the enumerators directly. Perhaps something like:


  INTEGER, PARAMETER :: ctype_kind = KIND(1)

  INTEGER(ctype_kind), PARAMETER :: out = 1

  INTEGER(ctype_kind), PARAMETER :: cut = 2

  INTEGER(ctype_kind), PARAMETER :: in = 3

  INTEGER(ctype_kind), PARAMETER :: sp = 4

In the above, the kind for the enumeration is just default kind you could change that depending on your requirements.

Practically the two forms are often equivalent - the kind of a enumeration that interoperates with C may well be default kind.

引文:

IanH 写道:

If you are just working in the Fortran world, then you could just declare the integer constants that are the enumerators directly. Perhaps something like:


  INTEGER, PARAMETER :: ctype_kind = KIND(1)

  INTEGER(ctype_kind), PARAMETER :: out = 1

  INTEGER(ctype_kind), PARAMETER :: cut = 2

  INTEGER(ctype_kind), PARAMETER :: in = 3

  INTEGER(ctype_kind), PARAMETER :: sp = 4

In the above, the kind for the enumeration is just default kind you could change that depending on your requirements.

Practically the two forms are often equivalent - the kind of a enumeration that interoperates with C may well be default kind.

I think, second one is my choice, my code will be in Fortran. The most important part of my problem is the "CALL" part. I want to call the ctype_kind and tag it, such as:


if(nnn%type_==out) then

!...statements

end if
if(nnn%type_==cut) then

!...statements

end if
if(nnn%type_==in) then

!...statements

end if
if(nnn%type_==sp) then

!...statements

end if

, where nnn is a pointer which points to a next pointer type_ and type_ has the enumerated values in, out, cut and sp.

引文:

emreka82 写道:

Quote:

IanH wrote:

If you are just working in the Fortran world, then you could just declare the integer constants that are the enumerators directly. Perhaps something like:

INTEGER, PARAMETER :: ctype_kind = KIND(1)

INTEGER(ctype_kind), PARAMETER :: out = 1

INTEGER(ctype_kind), PARAMETER :: cut = 2

INTEGER(ctype_kind), PARAMETER :: in = 3

INTEGER(ctype_kind), PARAMETER :: sp = 4

In the above, the kind for the enumeration is just default kind you could change that depending on your requirements.

Practically the two forms are often equivalent - the kind of a enumeration that interoperates with C may well be default kind.

I think, second one is my choice, my code will be in Fortran. The most important part of my problem is the "CALL" part. I want to call the ctype_kind and tag it, such as:


if(nnn%type_==out) then

!...statements

end if
if(nnn%type_==cut) then

!...statements

end if
if(nnn%type_==in) then

!...statements

end if
if(nnn%type_==sp) then

!...statements

end if

, where nnn is a pointer which points to a next pointer type_ and type_ has the enumerated values in, out, cut and sp.

I have written a module, a main program and two subroutines to clearly understand the problem, then I think I figure it out, can you check it ?

Module:

module param_mod
type c_type

        integer :: val

end type c_type
    type(c_type), parameter   :: out=c_type(0), cut=c_type(1), sp=c_type(2), in=c_type(3)
type c
type(c_type), pointer  :: type_
end type c
interface operator(==)

    module procedure operate

end interface
contains
logical function operate(a,b)

      type(c_type), intent(in) :: a,b

      operate = a%val.eq.b%val

end function operate
end module param_mod

Main program:

    program param
    use param_mod
    call example
    call system('pause')  
    end program param

Invoking subroutine:


subroutine invoke(nnn2)

    use param_mod
    type(c), pointer    :: nnn2
    allocate(nnn2)
    allocate(nnn2%type_)
    nnn2%type_=cut
end subroutine invoke

 

Example subroutine:

subroutine example
use param_mod
integer, target :: new
type(c), pointer :: nnn
allocate(nnn)
allocate(nnn%type_)
call invoke(nnn) ! here I tag the "nnn%type_" as "cut".
print*, nnn%type_ ! shows the value of the pointer
if(nnn%type_==out) then ! if nnn%type_= out, values are both 0
print*, "out"

!...statements
else if(nnn%type_==cut) then ! if nnn%type_= cut, values are both 1
print*, "cut"

!...statements
else if(nnn%type_==sp) then ! if nnn%type_= sp, values are both 2
print*, "sp"

!...statements
else  ! if nnn%type_= in, values are both 3
print*, "in"

!...statements
end if
    deallocate(nnn%type_)

    deallocate(nnn)
end subroutine example
 

As you can see above, I overload the operator ==, could the overloading result in any problem ? And do you have any suggestions for more clever and direct solution for the problem other than that above ? Thanks.

I don't understand what it is that you are trying to achieve.

Wrapping an integer component in a derived type with appropriate set and test (operator(==)) procedures is certainly one way to implement a strongly typed enumeration in Fortran. There are some disadvantages - for example you can't use such an enumeration directly in a SELECT CASE construct.

(Your invoke procedure in your example code has a dummy argument (nnn2) that is a pointer - an explicit interface is required.)

Firstly, thanks for the contribution Ian, you have been very helpful. I have some questions in my mind about your comments:

引文:

IanH 写道:

I don't understand what it is that you are trying to achieve.

Wrapping an integer component in a derived type with appropriate set and test (operator(==)) procedures is certainly one way to implement a strongly typed enumeration in Fortran. There are some disadvantages - for example you can't use such an enumeration directly in a SELECT CASE construct.

(Your invoke procedure in your example code has a dummy argument (nnn2) that is a pointer - an explicit interface is required.)

I am trying to tag a pointer(type_) as out, cut, sp or in. This pointer (type_) is a component of another pointer (nnn or nnn2).

引文:

IanH 写道:

Wrapping an integer component in a derived type with appropriate set and test (operator(==)) procedures is certainly one way to implement a strongly typed enumeration in Fortran. There are some disadvantages - for example you can't use such an enumeration directly in a SELECT CASE construct.

Then, my solution is correct, right ? Where would I need "SELECT CASE construct" ?

引文:

IanH 写道:

(Your invoke procedure in your example code has a dummy argument (nnn2) that is a pointer - an explicit interface is required.)

"explicit interface is required", then should I write an interface in the param_mod module, right ? Such as:

module param_mod

!......................
interface
subroutine invoke(nnn2)
    type(c), pointer    :: nnn2
end subroutine invoke
end interface

登陆并发表评论。