I would like to use the generic name of a function to overload the '*' operator as in the example below:
interface scala
module procedure :: scalapr,scalarp
end interface scala
interface operator(*)
module procedure :: scala
end interface operator(*)
However, compiling with gfortran, I get:
Error: Procedure 'scala' in intrinsic '*' operator at (1) is neither function nor subroutine
Is there any turn-around ?
You must overload with the specific function
interface scala
module procedure :: scalapr,scalarp
end interface scala
interface operator(*)
module procedure :: scalapr, scalarp
end interface operator(*)
The generic is not a module procedure, so it cannot appear in module procedure.
There is also just procedure, but that won't help here. It is for procedures not coming form the current module. But anyway, the functions in the generic interface block must be specific functions.
See Fortran 2008 12.4.3.4 Generic interfaces:
1 A generic interface block specifies a generic interface for each of
the procedures in the interface block. The PROCEDURE statement lists
procedure pointers, external procedures, dummy procedures, or module
procedures that have this generic interface. ...
According to 7.1.6:
5 A function defines the binary operation x1 op x2 if
(2) either
(a) a generic interface (12.4.3.2) provides the function with a generic-spec of OPERATOR (op),
or
(b) there is a generic binding (4.5.5) in the declared type
so the rules above do apply as does the constraint
C1207 (R1206) A procedure-name shall be a nonintrinsic procedure that
has an explicit interface.
A generic-name does not conform to C1207.
Related
MODULE MyTypeMod
TYPE MyType
PRIVATE
INTEGER, ALLOCATABLE :: Num
CONTAINS
PROCEDURE, PUBLIC :: IsNum!To check Allocation of Num
...
END TYPE MyType
CONTAINS
...
END MODULE MyTypeMod
PROGRAM testMyType
USE MyTypeMod, ONLY : MyType
...
END PROGRAM testMyType
Here In this Module and Program, Can we modify accessibility status "IsNum" type-bound procedure? Can we make the "IsNum" procedure PRIVATE in just the testMyTypeMod PROGRAM?
According to paragraph 9 of section 7.5.5 of the Fortran 2018 draft standard
A public type-bound procedure is accessible via any accessible object of the type. A private type-bound procedure is accessible only within the module containing the type definition, and within its descendants.
And so changing the accessibility of a type-bound procedure is not possible.
There is currently a proposal to update a future Fortran standard that suggests making a subset of what you want to do possible.
You may want to make a new proposal to update the standard. This is also likely the best way to find out why what you want to do is not currently possible.
Consider the following code, which defines an abstract type foo with a deferred procedure sub, and a type foo2 which extends foo:
MODULE m
TYPE, ABSTRACT:: foo
CONTAINS
PROCEDURE(sub_int), DEFERRED:: sub
END TYPE
INTERFACE
SUBROUTINE sub_int(THIS, x)
IMPORT:: foo
CLASS(foo), INTENT(IN):: THIS
DOUBLE PRECISION, INTENT(INOUT):: x
END SUBROUTINE
END INTERFACE
TYPE, EXTENDS(foo):: foo2
CONTAINS
PROCEDURE:: sub
END TYPE
INTERFACE
MODULE SUBROUTINE sub(THIS, x)
CLASS(foo2), INTENT(IN):: THIS
DOUBLE PRECISION, INTENT(INOUT):: x
END SUBROUTINE
END INTERFACE
END MODULE
SUBMODULE (m) s
CONTAINS
MODULE PROCEDURE sub
x= x**2
END PROCEDURE
END SUBMODULE
Is there a way to avoid writing the second interface?
I understand that it is needed in order to declare sub as a module procedure (otherwise the implementation would need to be done in the module, and not in the submodule), but is this the only way to do it?
In other words, is it possible to implement the procedure sub for foo2 without rewriting the entire interface for it?
It is not possible. A separate module subprogram requires an interface block, either in its defining submodule or an ancestor of its defining submodule.
Whether a procedure happens to be nominated by one (or more!) bindings of one (or more!) types is totally irrelevant.
For instance, I have a definition of type A in moduleA:
Module moduleA
implicit none
type A
private
integer::N
contains
...
procedure,pass::f=>f1
endtype
private::f1
contains
real function f1(self,x)
real::x(self%n)
end function
...
end Module
Then I found I meet a trouble when I override function f in other modules since I can not get the value of N. Even though I can have a method to get that, it seems that something like real :: x(self%get()) is impossible in the declaration. I want to keep the rule of "private" in OPP. So what choices can I have?
You cannot do that. At least in the way you describe. It would be better to see an example of the overriding to suggest other options.
The private attribute works differently in Fortran and therefore you should not directly use rules from other languages that use OOP where private means something different.
In Fortran private is about the local module, in C++ it is about the derived classes. This is very different and you cannot use the C++ (or Java, etc.) rules for private in Fortran when private in fact means something else.
To be clear, I assume you wanted this kind of overriding:
real function f2(self,x)
class(B) :: self
real::x(self%get())
end function
You than get these messages:
private.f90(15): error #8497: Illegal use of a procedure name in an expression, possibly a function call missing parenthesis. [GET]
real::x(self%get())
---------------------^
or
real::x(self%get())
1
Error: 'get' at (1) should be a FUNCTION
So the compilers will not accept a type-bound procedure in the declaration. They would accept an ordinary procedure.
This compiles in gfortran, but not in Intel Fortran. But get() must be public, which you might not want:
real function f1(self,x)
class(A) :: self
real::x(get(self))
end function
real function f2(self,x)
class(B) :: self
real::x(get(self))
end function
In ifort I get
error #8383: The dummy arguments of an overriding and overridden binding that correspond by position must have the same characteristics, except for the type of the passed object dummy arguments.
which is weird.
I read this link, it talks about Self-defining INTERFACE.
But I got confused about the saying
A Procedure should be able to read it’s own interface specification in
and INTERFACE block.
What is own interface specification? What does this link mean?
Before I start: This is about explicit interfaces. If in doubt, you should use MODULES so you don't have to worry about this.
Now to the question.
If you have a function, say this:
function square(a)
implicit none
real, intent(in) :: a
real :: square
square = a * a
end function square
And this function is in a separate file, to be compiled separately from the calling routine, then it would be advisable that the calling routine is told of the interface of this function. Something like this:
interface
function square(a)
implicit none
real, intent(in) :: a
real :: square
end function square
end interface
should be in the calling routine's declaration block. This way, the calling routine, while not knowing how the square function works, knows what types of parameters to pass to it, and what to expect back.
It is quite common to put this into a separate file, and include this file everywhere this function might be called.
Here's the issue: There are no checks that the interface block actually matches the real thing. So the idea of this proposal seems to be that in the code implementing the square function, you should be able to also include this separate file and then the compiler could check whether the interface block matches the declaration, and throw an error if wrong.
At the moment, though, including this interface block is explicitly forbidden by the standard.
When I try to mix both regular procedures and deferred procedures in one abstract type, gfortran balks at any invocation of the regular procedures:
" Error: Base object for type-bound procedure call at (1) is of ABSTRACT type 'tbody' "
type, abstract :: tBody
private
...
contains
procedure :: init => new_Body
...
procedure (contained), deferred :: PointIn
end type tBody
abstract interface
logical(LGT) pure function contained( Body, Point )
import :: tBody, tAffinePoint, LGT
class(tBody), intent(IN) :: Body
type(tAffinePoint), intent(IN) :: Point
end function contained
end interface
subroutine newCuboid( this, ... )
class(tCuboid), intent(OUT) :: this
...
call this%tBody%init( ... )
.... [gfortran halts here]
end subroutine newCuboid
Is there a way to arrange the type tBody so that I can have both abstract, deferred procedures and regular, instantiated procedures?
No.
There's a simple solution - replace call this%tBody%init(...) with call new_Body(...) (you may need to make appropriate accessibility changes).
Possibly feeble rationalisation - you are not resolving the procedure on the basis of the type of the reference (because that's hard coded), so don't use type bound procedure syntax.
Another solution in some cases is to split the type hierarchy further, so that the abstract type tBody has a non-abstract parent that hosts the initial implementation of the "not deferred" procedures.