问题
I am using a derived type (bicomplex), and an overload of the assignment operator (=), so that one can assign a real*8
to bicomplex
. A MWE of the bicplx module follows:
MODULE bicplx
type bicomplex
COMPLEX*16 :: a
COMPLEX*16 :: b
end type
interface assignment(=)
module procedure dble_assign_bicplx
end interface
contains
subroutine dble_assign_bicplx(qleft, xright)
implicit none
type(bicomplex), intent(out) :: qleft
double precision, intent(in) :: xright
qleft%a = xright
qleft%b = 0.0d0
return
end subroutine dble_assign_bicplx
end MODULE
The assignment of real to complex is handled intrinsically by Fortran. This method works well when used on "typical" bicomplex variables, but breaks when I want to assign a real*8
to a bicomplex which has the PARAMETER
attribute:
TYPE(bicomplex) :: test1
test1 = 1.d0
works perfectly, but:
TYPE(bicomplex), parameter :: test1 = 1.d0
does not compile and gives 2 errors: Error: Incompatible derived type in PARAMETER at (1)
, and Error: Can't convert REAL(8) to TYPE(bicomplex) at (1)
.
However,
TYPE(bicomplex), parameter :: test1 = bicomplex(1.d0, 0.d0)
works perfectly.
Is there something I am missing, or is it part of the standards that a parameter can not be assigned by using an overloaded assignment operator? Ideally, I'd like to solve this using F90/F95 (and not 2003 or 2008).
回答1:
A "parameter" is a named constant. The rules of the language require that the value of a named constant can be determined at "compile time" - i.e. before the program is executed. That means that the expression used to give a named constant its value need to be able to be determined at compile time. The language terminology for this in recent standards is "constant expression", in earlier standards it was also called "initialization expression" (something that could be used as an initializer - before program execution).
Defined assignment is an executable action - when run the program executes the statements in the procedure that sits behind the defined assignment. This is not something that can generally be done at compile time.
As you have discovered, you can use structure constructors where the component initializers are constant expressions to initialize derived type named constants.
回答2:
My reading of the standard is that one cannot use a defined operator here. My thinking is that this is because the operator is for defined assignment where for a named constant initialization is used (see R503 and C507 of Fortran 2008, in section 5.2.1).
In Fortran 2008 section 5.2.3, regarding initialization:
If initialization is = constant-expr, the variable is initially defined with the value specified by the constant-expr; if necessary, the value is converted according to the rules of intrinsic assignment
There may be some ambiguity in that paragraph (not shown) as it starts by referring to entities without the parameter
attribute. So, looking on, in section 5.3.13 for the parameter
attribute:
The entity has the value specified by its constant-expr, converted, if necessary, to the type, type parameters and shape of the entity.
However, section 5.4.11 (for the parameter
statement) perhaps reinforces that this conversion is by intrinsic assignment:
The value of each named constant is that specified by the corresponding constant expression; if necessary, the value is converted according to the rules of intrinsic assignment
For the first named constant case there is no intrinsic assignment from the intrinsic type to the derived type. In the second case, using the constructor for the derived type, intrinsic assignment is indeed being used.
来源:https://stackoverflow.com/questions/25495549/fortran-derived-types-overloaded-assignment-operator-not-working-with-paramete