Search code examples
fortranderived-types

Fortran derived types: Overloaded assignment operator not working with 'PARAMETER' attribute


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).


Solution

  • 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.