class(*) intrinsic assignment

class(*) intrinsic assignment

When trying to compile a module to assign class(*) to an integer I get the following error:

stl.f90(10): error #6762: The type for the arguments of this specific subroutine for a defined ASSIGNMENT redefines intrinsic assignment operations.   [ASSIGN_CLASS_STAR_TO_INT]

 

module stl
implicit none

interface assignment(=)
    module procedure assign_class_star_to_int
end interface

contains

subroutine assign_class_star_to_int(a, b)
implicit none
integer, intent(out) :: a
class(*), intent(in) :: b

select type(b)
    type is (integer)
        a = b
end select

end subroutine assign_class_star_to_int

end module stl

This would suggest that I can use a built-in intrinsic to assign a class(*) to an integer. If I try to compile the following program, I get the error:

test.f90(22): error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands.

module foo_m

contains

function foo() result(f)
implicit none
integer :: i
class(*), allocatable :: f

i=10
allocate(f, source=i)

end function foo

end module foo_m

program main
use foo_m
implicit none
integer :: i

i = foo()

end program main

 

 

What am I missing here?

Thanks for your help.

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

With your first example, your subroutine would be matched by an assignment such as:

integer :: i
i = 3

This could present various quandries for the Fortran language, Fortran programmers and Fortran compilers (the defined assignment could specify that the resulting value of i is 2!) - so it is not permitted to keep everybody sane.

For your second example, the dynamic type of the right hand side may be something that is not an integer (or not convertible to an integer by the rules of intrinsic assignment) - so that is also not permitted.

As of Fortran 2008 (and soon-to-be-current ifort) you can assign to a left hand side variable that is an allocatable unlimited polymorphic object.

program p
  implicit none
  class(*), allocatable :: lhs
  lhs = 1
  
  select type (lhs)
  type is (integer)
    print *, lhs
  class default
    print "('what??')"
  end select
end program p

If you want to convert an unlimited polymorphic object to an integer, then you can write a function that does so:

module m
  implicit none
  private
  public :: operator(.GetAsInteger.)
  interface operator(.GetAsInteger.)
    procedure :: GetAsInteger
  end interface operator(.GetAsInteger.)
contains
  function GetAsInteger(rhs)
    class(*), intent(in) :: rhs
    integer :: GetAsInteger
    
    select type (rhs)
    type is (integer)
      GetAsInteger = rhs
    class default
      GetAsInteger = -1
    end select
  end function GetAsInteger
end module m

program p
  use m
  implicit none
  
  class(*), allocatable :: thing
  integer :: i
  allocate(thing, source = 99)   ! or with F2008: thing = 99
  
  i = .GetAsInteger. thing
  
  print *, i
end program p

Leave a Comment

Please sign in to add a comment. Not a member? Join today