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

Interface of an internal module function as class constructor

lccostajr
Beginner
1,000 Views
I am trying to compile the following code with Intel Fortran 11.1, where I would like to have the constructor function to be called by a function with the same name of my class.


************************************** shape.f90 **************************************
module shape_mod
private ! hide the type-bound procedure implementation procedures
public :: shape ! allow access to shape & constructor procedure

type shape
private ! hide the underlying details
integer :: color
logical :: filled
integer :: x
integer :: y
contains
private ! hide the type bound procedures by default
procedure :: initShape ! private type-bound procedure
procedure, public :: isFilled ! allow access to isFilled type-bound procedure
procedure, public :: print ! allow access to print type-bound procedure
end type shape

interface shape
procedure constructor
end interface

contains

function constructor(color, filled, x, y)
type(shape) :: constructor
integer :: color
logical :: filled
integer :: x
integer :: y
call constructor%initShape(color, filled, x, y)
end function

logical function isFilled(this)
class(shape) :: this
isFilled = this%filled
end function

subroutine initShape(this, color, filled, x, y)
! initialize shape objects
class(shape) :: this
integer :: color
logical :: filled
integer :: x
integer :: y

this%color = color
this%filled = filled
this%x = x
this%y = y
end subroutine

subroutine print(this)
class(shape) :: this
print *, this%color, this%filled, this%x, this%y
end subroutine
end module

program shape_prg
use shape_mod
type(shape) :: sh
logical filled
sh = shape(5, .true., 100, 200) ! invoke constructor through shape generic interface
call sh%print()
end
************************************** shape.f90 **************************************

But I am getting the following error:

*************************************************************************************
d:\\lc\\shape\\src> ifort shape.f90
Intel Visual Fortran Intel 64 Compiler Professional for applications running on Intel 64, Version 11.1 Build 20100414 Package ID: w_cprof_p_11.1.065
Copyright (C) 1985-2010 Intel Corporation. All rights reserved.

shape.f90(19): error #6643: This statement is incorrectly positioned.
procedure constructor
----------------^
shape.f90(19): error #8168: Parentheses are required after the PROCEDURE keyword.
procedure constructor
----------------^
shape.f90(62): error #6296: The type of this structure constructor is use associated with the PRIVATE fields attribute
[SHAPE]
sh = shape(5, .true., 100, 200) ! invoke constructor through shape generic interface
-------------^
compilation aborted for shape.f90 (code 1)
*************************************************************************************

What am I doing wrong?

Thanks in advance,
Luiz
0 Kudos
8 Replies
Steven_L_Intel1
Employee
1,000 Views
I don't think you're doing anything wrong. I know that the 11.1 and 12.0 compiler does not accept "procedure" in a generic interface. The 12.0 compiler actually does worse on this, triggering an internal compiler error. I already have a bug report filed on this - I will verify that yours is the same issue.
0 Kudos
IanH
Honored Contributor III
1,000 Views
I got it to work with 12.0.3 if I renamed the generic interface and derived type to something other than shape (clash with the intrinsic?) and added the module keyword to the procedure-stmt.
0 Kudos
Steven_L_Intel1
Employee
1,000 Views
It is indeed the intrinsic SHAPE that is conflicting here, though the compiler's response to that is not very nice. I will report that. Issue ID is DPD200169073.

The standard considers intrinsic procedures and type names to be of the same "local identifier class". It says (F2008, 16.3.1):

"Within its scope, a local identifier of one class shall not be the same as another local identifier of the same class, except that a generic name may be the same as the name of a procedure as explained in 12.4.3.4 or the same name as a derived type (4.5.10)."

So it is fine to have the generic have the same name as the type, but not ok to have the type the same name as an intrinsic. Unfortunately, while the language has a way of "affirming" that an identifier is an intrinsic, it doesn't have a good way of specifying that it is NOT an intrinsic for the purpose of defining a type name.

As Ian writes, Intel Fortran currently insists on the "module" keyword, which will prevent you from using procedure pointers in a generic interface. That has already been reported.
0 Kudos
IanH
Honored Contributor III
1,000 Views
The compiler is having a bit of a bet both ways then, as 12.0.3 happily accepts:

[fortran]PROGRAM ShapeShifter
  IMPLICIT NONE
  
  TYPE :: Shape
    INTEGER :: i
  END TYPE Shape
  TYPE(Shape) :: z

  !***
  
  z%i = 1
  PRINT "(I0)", z%i
  
  z = Shape(i=3)  
  PRINT "(I0)", z%i  
END PROGRAM ShapeShifter
[/fortran]
0 Kudos
Steven_L_Intel1
Employee
1,000 Views
My explanation was, as "Click and Clack" (The NPR Car Talk guys) would say, BOOOOO-GUSSSS! Something else is going on here and we'll figure out what it is. My point about the MODULE keyword still applies.
0 Kudos
Steven_L_Intel1
Employee
1,000 Views
A derived type may have the same name as a generic function. If a reference could be interpreted as either a generic function reference or a structure constructor, it is to be treated as a generic function reference. We arenot doing this right and will fix it.
0 Kudos
Steven_L_Intel1
Employee
1,000 Views
This problem has been fixed in our sources. The fix will appear in a future update.
0 Kudos
Steven_L_Intel1
Employee
1,000 Views
The internal compiler error is fixed in Update 7. You still need the "module" prefix to "procedure" in the interface block - that will be remedied in a future version.
0 Kudos
Reply