Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Static array of procedure pointers

rakkota
Novice
2,194 Views

Hi,

I am trying to construct a static array of procedure pointers like this:

      abstract interface
        function USERFUNC_int (arg)
        integer USERFUNC_int
        integer, intent(IN) :: arg
        end function USERFUNC_int
      end interface

      procedure(USERFUNC_int), pointer :: pcfs(100)

 but the compiler complains about the "(":

error #5082: Syntax error, found '(' when expecting one of:  , <END-OF-STATEMENT> ; =>
      procedure(USERFUNC_int), pointer :: pcfs(100)

It is possible to declare a static array of procedure pointers? I am using ifort 13.1.3.0.

Thanks,

Rak

1 Solution
FortranFan
Honored Contributor III
2,194 Views

jimdempseyatthecove wrote:

...
And assume the user wishes to pass the "this" pointer...

Could the user then explicitly declare the "this" pointer in the function interface?

...

Jim,

Is the functionality shown in the code below what you're asking about?  It is standard Fortran.

   module pcf_mod
   
      type :: ARRPROCPOINTER 
         procedure(USERFUNC_int), pointer, pass(this) :: pcf
      end type ARRPROCPOINTER
      
      abstract interface
         function USERFUNC_int (arg, this)
            import :: ARRPROCPOINTER
            integer USERFUNC_int
            integer, intent(IN) :: arg
            class(ARRPROCPOINTER) :: this
         end function USERFUNC_int
      end interface
      
      type(ARRPROCPOINTER) :: pcfs(100)
   
   end module pcf_mod
   
   program p
      ..
      integer :: i, j, k
      ..
      pcfs(i)%pcf => foo
      ..
      k = pcfs(i)%pcf(j)
      .. 
   end program p

 

Note how the interface has been changed to refer to the invoking object via the "this" dummy argument.  You may also know that by using the PASS attribute in the PROCEDURE statement in the derived type declaration, the developer can make the "this" argument to be second, third, or wherever appropriate on the dummy argument list; it doesn't have to be first.  Also, the argument can be named "this", "self", "me", etc.  - whatever naming convention is preferred.

View solution in original post

13 Replies
rakkota
Novice
2,194 Views

Moreover, if I am trying to circumvent the problem by embedding the function pointer into a derived type as follows

      module pcf_mod

      abstract interface
        function USERFUNC_int (arg)
        integer USERFUNC_int
        integer, intent(IN) :: arg
        end function USERFUNC_int
      end interface

      type :: ARRPROCPOINTER 
        procedure(USERFUNC_int), pointer :: pcf
      end type ARRPROCPOINTER

      type(ARRPROCPOINTER) :: pcfs(100)

      end module pcf_mod

I am getting a totally unrelated compiler error:

error #8262: The passed-object dummy argument must be dummy data object with the same declared type as the type being defined.   [ARG]
        function USERFUNC_int (arg)

Removing the type related lines it compiles fine. It seems that I am stuck.

Rak 

Steven_L_Intel1
Employee
2,194 Views

As you found out, you have to use a derived type here. Fortran doesn't have the notion of an array of pointers.

The new error is simply a compiler bug. For some reason it thinks you're declaring a type-bound procedure, which you aren't. That's just weird - I will report it to the developers.

Izaak_Beekman
New Contributor II
2,194 Views

Steve Lionel (Intel) wrote:

The new error is simply a compiler bug. For some reason it thinks you're declaring a type-bound procedure, which you aren't. That's just weird - I will report it to the developers.

Steve, according to Fortran 95/2003 by M,R,C this is correct behavior:

When a procedure pointer component (or a type-bound procedure, Section 16.6) is invoked the object through which it is invoked is normally passed to the procedure as its first actual argument and the items in the parenthesized list are the other actual arguments. This could be undesirable; for instance, it might be wished to pass the object to a dummy argument other than the first or not to pass it at all.

Therefore, I don't think this is a compiler bug. For the OP to get the intended behavior, simply add the nopass attribute to the procedure pointer declaration in the derived type:

      type :: ARRPROCPOINTER
        procedure(USERFUNC_int), pointer, nopass :: pcf
      end type ARRPROCPOINTER

 

Steven_L_Intel1
Employee
2,194 Views

Well, I'll be darned. I'm always learning something new about this language.... Indeed you are correct, Zaak.

0 Kudos
Izaak_Beekman
New Contributor II
2,194 Views

Yeah, how they arrived at some of the finer points of the syntax for procedure pointer components really seems non-intuitive to me. 

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,194 Views

Zaak,

Assuming the nopass technique  corrects the compiler complaint of compliance to the standard...
And assume the user wishes to pass the "this" pointer...
Could the user then explicitly declare the "this" pointer in the function interface?

Jim Dempsey

 

0 Kudos
Izaak_Beekman
New Contributor II
2,194 Views

jimdempseyatthecove wrote:

Zaak,

Assuming the nopass technique  corrects the compiler complaint of compliance to the standard...

And assume the user wishes to pass the "this" pointer...

Could the user then explicitly declare the "this" pointer in the function interface?

Jim Dempsey

 

Jim,
I'm not sure what you mean by the "this" pointer. If the user did want to pass the object as an actual argument to type bound procedure (TBP) or procedure being pointed to by the procedure pointer component, then the canonical way of doing this is to specify the first dummy argument of the procedure as being type-compatible with the encompassing "this" object and without adding any pass or nopass attributes to the component specification. If the procedure had only this one dummy argument, then when it is invoked via the TBP or procedure-pointer component, the encompassing object is implicitly passed as the first actual argument, and the user can invoke the procedure with no (explicit) actual arguments. e.g., obj%method(). If one were to give the TBP/procedure-pointer component the nopass attribute then the procedure could be invoked explicitly passing the object: obj%method(obj). These two scenarios are identical. In general I think explicit is better than implicit, but in this context it is reasonable to expect a procedure bound to an object to modify the objects state and appreciate the decrease in verbosity associated with this language feature.

So, if I correctly understand your question, the answer is 'yes.' At any rate, between this post and Fortran Fan's hopefully we've covered the ins and outs of the pass(_____) and nopass attribute, and objects implicitly or explicitly passed as actual arguments to their TBPs/procedure-pointer components.

0 Kudos
FortranFan
Honored Contributor III
2,195 Views

jimdempseyatthecove wrote:

...
And assume the user wishes to pass the "this" pointer...

Could the user then explicitly declare the "this" pointer in the function interface?

...

Jim,

Is the functionality shown in the code below what you're asking about?  It is standard Fortran.

   module pcf_mod
   
      type :: ARRPROCPOINTER 
         procedure(USERFUNC_int), pointer, pass(this) :: pcf
      end type ARRPROCPOINTER
      
      abstract interface
         function USERFUNC_int (arg, this)
            import :: ARRPROCPOINTER
            integer USERFUNC_int
            integer, intent(IN) :: arg
            class(ARRPROCPOINTER) :: this
         end function USERFUNC_int
      end interface
      
      type(ARRPROCPOINTER) :: pcfs(100)
   
   end module pcf_mod
   
   program p
      ..
      integer :: i, j, k
      ..
      pcfs(i)%pcf => foo
      ..
      k = pcfs(i)%pcf(j)
      .. 
   end program p

 

Note how the interface has been changed to refer to the invoking object via the "this" dummy argument.  You may also know that by using the PASS attribute in the PROCEDURE statement in the derived type declaration, the developer can make the "this" argument to be second, third, or wherever appropriate on the dummy argument list; it doesn't have to be first.  Also, the argument can be named "this", "self", "me", etc.  - whatever naming convention is preferred.

FortranFan
Honored Contributor III
2,194 Views

Izaak Beekman wrote:

...

If one were to give the TBP/procedure-pointer component the nopass attribute then the procedure could be invoked explicitly passing the object: obj%method(obj). ...

In such a case, the invocation becomes analogous to that of a conventional Fortran subprogram: CALL method(obj,..) in the case of a subroutine and foo = method(obj,..) for a function.

0 Kudos
FortranFan
Honored Contributor III
2,194 Views

Izaak Beekman wrote:

Yeah, how they arrived at some of the finer points of the syntax for procedure pointer components really seems non-intuitive to me.

Things start to make a little bit of sense to me when I consider what would be required for consistency with legacy FORTRAN.  I assume that is what the Fortran 2003 standard writers had to contend with, trying to add new features while retaining syntax that, at a base level, is not alien to how it has been done since FORTRAN IV perhaps, or definitely FORTRAN 77.  Considering all the constraints that any standards body would normally face and when one piles all the legacy stuff on top of it, I think Fortran 2003 creators did a remarkable job.  But for many Fortran 2003 and 2008 features, I don't think I'll be writing any new code in Fortran!

0 Kudos
rakkota
Novice
2,194 Views

Thank you all for enlightening discussions on this subject. The code provided by FortranFan works like a charm. I have to admit that I would have never be able guess the correct syntax in this case, regardless of the modern FORTRAN bibliography worldwide available. The most puzzling for me is the presence of 'this' at lines 4, 8 and 12.

Rak

 

FortranFan wrote:

Quote:

jimdempseyatthecove wrote:

...

And assume the user wishes to pass the "this" pointer...



Could the user then explicitly declare the "this" pointer in the function interface?

...

 

Jim,

Is the functionality shown in the code below what you're asking about?  It is standard Fortran.

   module pcf_mod
   
      type :: ARRPROCPOINTER 
         procedure(USERFUNC_int), pointer, pass(this) :: pcf
      end type ARRPROCPOINTER
      
      abstract interface
         function USERFUNC_int (arg, this)
            import :: ARRPROCPOINTER
            integer USERFUNC_int
            integer, intent(IN) :: arg
            class(ARRPROCPOINTER) :: this
         end function USERFUNC_int
      end interface
      
      type(ARRPROCPOINTER) :: pcfs(100)
   
   end module pcf_mod
   
   program p
      ..
      integer :: i, j, k
      ..
      pcfs(i)%pcf => foo
      ..
      k = pcfs(i)%pcf(j)
      .. 
   end program p

 

Note how the interface has been changed to refer to the invoking object via the "this" dummy argument.  You may also know that by using the PASS attribute in the PROCEDURE statement in the derived type declaration, the developer can make the "this" argument to be second, third, or wherever appropriate on the dummy argument list; it doesn't have to be first.  Also, the argument can be named "this", "self", "me", etc.  - whatever naming convention is preferred.

0 Kudos
Izaak_Beekman
New Contributor II
2,194 Views

Rak,

You can just use the code you posted in your second example, but change 

      type :: ARRPROCPOINTER 
        procedure(USERFUNC_int), pointer :: pcf
      end type ARRPROCPOINTER

with this:

      type :: ARRPROCPOINTER 
        procedure(USERFUNC_int), pointer, nopass :: pcf
      end type ARRPROCPOINTER

Fortran Fan was answering Jim's question. You do not need the extraneous dummy argument 'this' just add the nopass attribute to the procedure pointer component in your original code from your second post, as I showed above. I highly recommend this route over adding the unused dummy argument.

0 Kudos
rakkota
Novice
2,194 Views

Thanks Izaak, nopass does the job as well.

Rak

 

Izaak Beekman wrote:

Rak,

You can just use the code you posted in your second example, but change 

      type :: ARRPROCPOINTER 
        procedure(USERFUNC_int), pointer :: pcf
      end type ARRPROCPOINTER

with this:

      type :: ARRPROCPOINTER 
        procedure(USERFUNC_int), pointer, nopass :: pcf
      end type ARRPROCPOINTER

Fortran Fan was answering Jim's question. You do not need the extraneous dummy argument 'this' just add the nopass attribute to the procedure pointer component in your original code from your second post, as I showed above. I highly recommend this route over adding the unused dummy argument.

0 Kudos
Reply