这是我较早开始的线程中的跟进问题here.
基本上,我要实现的是定义一个延迟类型,该类型将自动分配原始类型(实数,整数,字符和逻辑)。在上述链接中可以看到一个有效的示例,它用gcc version 7.3.0
和ifort version 18.0.0
编译。
我现在扩展了代码,以便在不知道分配了什么原始类型的情况下“使用”延迟的数据类型。这可以通过覆盖基本运算符来实现。为了简单起见,在下面的示例中,我仅包括了+
运算符。该示例可以使用 gfortran 进行编译,但是使用 ifort 进行编译时却给了我一个错误:
错误#6303:对于两个操作数的数据类型,赋值操作或二进制表达式操作无效。 [PLUS_FUNC_CLASS] c%i = a%i + b%i
有人知道这是什么问题吗?我已经在错误中进行了搜索,但是我找不到自己在做什么。
为了匹配精度,我使用了以下编译标志
ifort -r8 -i8 tst.f90
gfortran -fdefault-real-8 -fdefault-integer-8 -fdefault-double-8 tst.f90
这是示例代码:
module DervType
implicit none
type, public :: mytype
real :: r
integer :: i
character(len=:), allocatable :: c
logical :: l
end type
interface assignment(=)
module procedure equal_func_class
end interface
interface operator(+)
module procedure plus_func_class
end interface
contains
subroutine equal_func_class(a,b)
type(mytype), intent(out):: a
class(*), intent(in) :: b
select type (b)
type is (mytype)
print *, "is mytype"
if ( .not. a%r == b%r ) a%r = b%r !! <-- ugly, but necessary not to end up in an endless loop when reassigning mytype (only testing and assigning real here)
type is (real)
print *, "is real"
a%r = b
type is (integer)
print *, "is int"
a%i = b
type is (character(len=*))
print *, "is char"
a%c = b
type is (logical)
print *, "is logical"
a%l = b
end select
return
end subroutine equal_func_class
recursive function plus_func_class(a,b) result(c)
class(*), intent(in) :: a
class(*), intent(in) :: b
type(mytype) :: c
select type (a)
type is (mytype)
print *, "left side is mytype"
!! -------------------------------
!! only testing one case here and only real operations are
!! taken care of!
!! -------------------------------
select type (b)
type is (mytype)
print *, "right side is mytype"
c%i = a%i + b%i !! <-- this is where ifort throws the error
c%r = a%r + b%r !! <-- this is where ifort throws the error
type is (real)
print *, "right side is real", a%r
c = a%r + b
end select
!! do similar logic when the operands changing sides
type is (real)
print *, "left side is real"
end select
!c = 1.
return
end function plus_func_class
end module DervType
program TestType
use DervType
implicit none
type(mytype) :: test, test2, res, res2
real, parameter :: tt = 2.
test = 1.
test = 1
test = "Hey Tapir"
test = .true.
test2 = 2.
test = test2
print *, "test = ", test%r
res = test + 1.0
res2 = test + tt
print *, "Calculation 1 (real) : ", res%r
print *, "Calculation 2 (real) : ", res2%r
end program TestType
使用gfortran
进行编译并运行程序时,将产生以下输出:
is real
is int
is char
is logical
is real
is mytype
test = 2.0000000000000000
left side is mytype
right side is real 2.0000000000000000
is real
is mytype
left side is mytype
right side is real 2.0000000000000000
is real
is mytype
Calculation 1 (real) : 3.0000000000000000
Calculation 2 (real) : 4.0000000000000000
答案 0 :(得分:4)
让我们将此示例程序简化为更易于管理的内容:
module DervType
implicit none
type mytype
integer i
end type mytype
interface operator(+)
module procedure plus_func_class
end interface
contains
recursive function plus_func_class(a,b) result(c)
class(*), intent(in) :: a
class(*), intent(in) :: b
type(mytype) :: c
c%i = 1+1
end function plus_func_class
end module DervType
我的ifort 18.0.3对此抱怨:
error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. [PLUS_FUNC_CLASS]
c%i = 1+1
-----------^
熟悉吗?
好吧,看起来好像是因为我们有plus_func_class
的参数,因为无限多态ifort决定将此函数作为带有表达式operator(+)
的通用1+1
的特定过程。 (删除recursive
前缀以查看更多信息。)
我们不希望它那样做。我们可以说服它不这样做吗?
我们希望我们的真函数考虑左侧或右侧为class(mytype)
的情况,因为我们不希望重新实现intrinsic+intrinsic
。我不会详细说明,但是您可以两次实现该功能:一次使用LHS class(mytype)
和RHS class(*)
,一次使用LHS class(*)
和RHS class(mytype)
即使最初只是简单地将这种方法视为“编译器错误解决方法”,也确实值得实现定义的操作,而不必在加法操作的两侧都使用无限多态参数。
当您要创建新类型mytype2
时,您不想使用函数plus_func_class
定义操作。不过,您需要这样做,因为如果您为通用operator(+)
创建新的特定函数,则会有一个模棱两可的接口。