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

Abstract interface and procedure declaration for character function

ender01
New Contributor I
576 Views

Hello all,

I'm trying to construct an interface for a character function that returns a string whose length is determined by the input object, a derived type foo:

type foo

integer(kind=1) :: size
character, dimension(:), allocatable :: token
procedure(charStr_func), pointer :: fooBar
end type foo

The function, bar, returns a string constructed by concatenating the elements of foo%token and I want to size the string as an auotmatic object:

function bar(foo_bar) result(bar_foo)
type(foo), intent(in) :: foo_bar
character(len = foo_bar%size) :: bar_foo
...
end function bar

I want to define a function pointer so I define the abstract interface

abstract interface
function charStr_func(foo_bar)
import
type(foo), intent(in) :: foo_bar
character(len=foo_bar%size) :: charStr_func
end function charStr_func
end interface

So far so good, then I try to associate the pointer:

type(foo) :: foo1
...
foo1%fooBar => bar

and I get the compilation error #8178: The procedure pointer and the procedure target must have matching arguments. (This occurs regardless of whether or not I use the result clause in the function definition).

Any ideas?

Thanks,

Rich

0 Kudos
4 Replies
Steven_L_Intel1
Employee
576 Views

Is bar a contained procedure? If so, this is possibly bug DPD200050116, but the fix for that is not yet in a scheduled update. It would help if you could provide a short but complete example of the problem.

0 Kudos
ender01
New Contributor I
576 Views

Is bar a contained procedure? If so, this is possibly bug DPD200050116, but the fix for that is not yet in a scheduled update. It would help if you could provide a short but complete example of the problem.

Hi Steve,

Yes, bar is a contained procedure. The complete module looks like this:

[cpp]module foo_Mod
   use Basic_Numerics   ! Module defining kind parameters among other things
   implicit none

   private
   public :: foo, assignment(), len, ..., bar, ...

   !  Define object
   type foo
      integer(kind=I_LO) :: size
      character(len=1), dimension(:), allocatable :: token
      procedure(charStr_func), pointer :: getToken
   end type foo

   !  Define interfaces
   ...

   interface len
      module procedure get_Size
   end interface
   ...

   !  Define abstract interfaces for type-bound procedures
   abstract interface
      function charStr_func(foo_var)
         import
         type(foo), intent(in) :: foo_var
         character(len=len(foo_var)) :: charStr_func
      end function charStr_func
   end interface

   !  Define module procedures
   contains
      ...
      function get_Token(foo_var)  result(foo_Token)
         
         type(symbol), intent(in)  :: foo_var
         character(len=len(base_Symbol)) :: foo_Token
         integer(kind=I_LO) :: kount
			
         !  Loop over elements of token and assemble the output character string
         foo_Token(1:len(foo_var)) = foo_var%token(1)
         do kount = 2,len(foo_var)
            current_Token(1:len(foo_var)) = trim(foo_Token)// &
foo_var%token(kount) end do end function get_Token pure function get_Size(foo_var) result(foo_Size) type(foo), intent(in) :: foo_var integer(kind=I_LO) :: foo_Size ! Extract token size foo_Size = foo_var%size end function get_Size ... end module foo_Mod[/cpp]

Let me know if this is complete enough. Thanks!

Rich

0 Kudos
Steven_L_Intel1
Employee
576 Views

There's no pointer assignment here, but from what you've posted it looks like the same bug to me. I'll follow up with development.

0 Kudos
ender01
New Contributor I
576 Views

There's no pointer assignment here, but from what you've posted it looks like the same bug to me. I'll follow up with development.

I just noticed that I had omitted the module procedure doing the pointer assignment. This procedure is contained in the above module as well:

[cpp]subroutine set_Token(foo_var,foo_Token)

   type(symbol), intent(inout)  :: foo_var
   character(len=*), intent(in) :: foo_Token
			
   integer(kind=I_LO) :: kount, new_Size
   logical :: alloc_Flag, assoc_Flag
			
   !  Get length of new token
    new_Size = len(foo_Token)
			
   !  As this may be a redefinition of the foo object check allocation
   !  status and set alloc_Flag to true if token must be allocated
   alloc_Flag = .not. allocated(foo_var%token)
         
   !  Test that any allocation is appropriate
   if (.not. alloc_Flag) then
      !  Token has already been allocated, is it the right size
      alloc_Flag = len(foo_var) /= new_Size
            
      !  If token has the wrong size, deallocate
      if (alloc_Flag) then
         deallocate(foo_var%token)
      end if
   end if

   !  If necessary, resize and allocate storage array
   if (alloc_Flag) then
      foo_var%size = new_Size
      allocate(foo_var%token(new_Size))
   end if

   !  Assign new token to base symbol object
   do kount = 1,foo_var%size
       foo_var%token(kount) = foo_Token(kount:kount)
   end do
         
   !  If not already associated, want to have function pointers
   !  set.  Set assoc_Flag to .True. if function pointer needs
   !  to be associated
   assoc_Flag = .not. associated(foo_var%getToken)
   if (assoc_Flag) then
      foo_var%getToken => get_Token
   end if

end subroutine set_Token[/cpp]

Thanks again,

Rich

0 Kudos
Reply