Operator Cast

Operator to convert a UDT (User Defined Type) variable into a specified 
data type

Syntax
   { Type | Class | Union } typename
      Declare Operator Cast () [ ByRef ] As datatype
      ...
   End { Type | Class | Union }

   Operator typename.Cast () [ ByRef ] As datatype [ Export ]
   ...

Usage
   Cast( datatype, expression )

Parameters
   typename 
      The name of the Type, Class, or Union
   datatype 
      The name of the type for conversion into it, a built-in data type 
      (standard data type) or a UDT different from typename
   expression 
      The expression to convert, an instance of typename

Description
   Converts an expression (a typename variable) into a different datatype.

   Cast Operator must be declared inside the Type, Class, or Union.
   As all non-static member procedures, it has passed a hidden This 
   parameter.

   The Cast Operator is the only operator (or function) that can be 
   declared multiple times when only the return type differs, but not the 
   same as the Type, Class, or Union they are declared in.

   The Cast Operator allows conversions that can also be used on the 
   right-hand side of expressions of construction (with initializer) and 
   assignment (see example 1 below).
   In addition to its explicit form usage Cast( datatype, expression ), the 
   Cast Operator allows also implicit conversion into datatype (see same 
   example 1 below). For this not explicit usage, the compiler may decide 
   which cast overload to call based on how the object is used (for example 
   on the Print keyword, the compiler calls the Cast() As String operator 
   if defined).

   Note: The overloaded Cast Operator can convert only a UDT instance (not 
   a built-in type variable) because it can be overloaded only as a member 
   Operator (not as a global operator).
   To convert a built-in type variable into a UDT (not working syntax: 
   Cast( UDT, built_in_type_variable )), the best way into the UDT is to 
   define a constructor or/and a Let operator, otherwise to use a Cast 
   Operator but with return by reference (by an assignment: Cast( 
   built_in_datatype, UDT_instance ) = built_in_type_variable).
   (see example 2 below)

   For implicit conversion from one UDT into another UDT, a Cast Operator 
   in the first UDT can replace (in second priority) a constructor and a 
   Let operator in the second UDT (see examples 3 and 4 below).

   Warning: For a Cast operator that returns by value (no byref), do not 
   use generally an exit code like Return expression (or Operator = 
   expression) if expression is an instance of typename.
   Such a Cast operator code will induce an infinite loop when called, 
   unless an implicit conversion from typename to datatype already exists 
   through a matched constructor (or a let operator) for datatype, so with 
   a higher priority (see example 5 below).

Example
   Very simple syntaxic example highlighting the conversion capabilities 
   (explicit and implicit) by using Cast operators:
   Type UDT
     Dim As Integer I
     Declare Operator Cast () As Integer
     Declare Operator Cast () As String
   End Type

   Operator UDT.Cast () As Integer
     Print "UDT.Cast() As Integer",
     Return This.I
   End Operator

   Operator UDT.Cast () As String
     Print "UDT.Cast() As String",
     Return Str(This.I)
   End Operator

   Dim As UDT u

   u.I = 12
   Print Cast(Integer, u)               '' explicit conversion using the defined "Cast() As Integer" operator
   Print Cast(String, u)                '' explicit conversion using the defined "Cast() As String" operator
   Print u                              '' implicit conversion by compiler using the defined "Cast() As String" operator
   Print

   u.I = 34
   Dim As Integer J = Cast(Integer, u)  '' construction with explicit initialization using the defined "Cast() As Integer" operator
   Print J
   Dim As Integer K = u                 '' construction with implicit initialization by compiler using the defined "Cast() As Integer" operator
   Print K
   Print

   u.I = 56
   J = Cast(Integer, u)                 '' explicit assignment using the defined "Cast() As Integer" operator
   Print J
   K = u                                '' implicit assignment by compiler using the defined "Cast() As Integer" operator
   Print K
   Print

   u.I = 78
   Dim As String S = Cast(String, u)    '' construction with explicit initialization using the defined "Cast() As String" operator
   Print S
   Dim As String G = u                  '' construction with implicit initialization by compiler using the defined "Cast() As String" operator
   Print G
   Print

   u.I = 90
   S = Cast(String, u)                  '' explicit assignment using the defined "Cast() As String" operator
   Print S
   G = u                                '' implicit assignment by compiler using the defined "Cast() As String" operator
   Print G
   Print

   Sleep
      

   Workarounds for the not working syntax: UDT_instance = Cast( UDT, 
   built_in_type_variable ):
   (using constructor, Let operator, and a Cast operator which returns by 
   reference)
   Type UDT
     As Integer I
     Declare Constructor ()
     Declare Constructor (ByVal I0 As Integer)
     Declare Operator Let (ByVal I0 As Integer)
     Declare Operator Cast () ByRef As Integer
   End Type

   Constructor UDT ()
   End Constructor

   Constructor UDT (ByVal I0 As Integer)
     Print "UDT.Constructor(Byval As Integer)",
     This.I = I0
   End Constructor

   Operator UDT.Let (ByVal I0 As Integer)
     Print "UDT.Let(Byval As Integer)",,
     This.I = I0
   End Operator

   Operator UDT.Cast () ByRef As Integer
     Print "UDT.Cast() Byref As Integer",,
     Return This.I
   End Operator

   Dim As UDT u

   'u = Cast(UDT, 12)     '' unsupported - error 20: Type mismatch
   u = UDT(34)            '' explicit conversion using the defined "Constructor(Byval As Integer)"
   Print u.I
   Print

   u = 56                 '' implicit conversion by compiler using the defined "Let(Byval As Integer)" operator
   Print u.I
   Print

   Cast(Integer, u) = 78  '' explicit conversion using the defined "Cast() Byref As Integer" operator with byref return
   Print u.I
   Print

   Sleep
      

   Conversion from UDT1 into UDT2, by using a constructor and a Let 
   operator in UDT2:
   Type _UDT1 As UDT1

   Type UDT2
     Dim As Integer I2
     Declare Constructor ()
     Declare Constructor (ByRef u As _UDT1)
     Declare Operator Let (ByRef u As _UDT1)
   End Type

   Constructor UDT2 ()
   End Constructor

   Type UDT1
     Dim As Integer I1
   End Type

   Constructor UDT2 (ByRef u As UDT1)
     Print "UDT2.Constructor(Byref As UDT1)",
     This.I2 = u.I1
   End Constructor

   Operator UDT2.Let (ByRef u As UDT1)
     Print "UDT2.Let(Byref As UDT1)",,
     This.I2 = u.I1
   End Operator

   Dim As UDT1 u1

   u1.I1 = 123
   Dim As UDT2 u2 = u1  '' implicit conversion by compiler using the defined "UDT2.Constructor(Byref As UDT1)"
   Print u2.I2
   Print

   u1.I1 = 456
   u2 = u1              '' implicit conversion by compiler using the defined "UDT2.Let(Byref As UDT1)" operator
   Print u2.I2
   Print

   Sleep
      

   Conversion from UDT1 into UDT2, by using a Cast operator in UDT1:
   Type UDT2
     Dim As Integer I2
   End Type

   Type UDT1
     Dim As Integer I1
     Declare Operator Cast () As UDT2
   End Type

   Operator UDT1.Cast () As UDT2
     Print "UDT1.Cast() As UDT2",,
     Dim As UDT2 u
     u.I2 = This.I1
     Return u
   End Operator

   Dim As UDT1 u1

   u1.I1 = 123
   Dim As UDT2 u2 = u1  '' implicit conversion by compiler using the defined "UDT1.Cast() As UDT2" operator
   Print u2.I2
   Print

   u1.I1 = 456
   u2 = u1              '' implicit conversion by compiler using the defined "UDT1.Cast() As UDT2" operator
   Print u2.I2
   Print

   Sleep
      

   Conversion from UDT1 into UDT2, by using in UDT1 a Cast operator exiting 
   by Return This, but without infinite loop thanks to a matched Let 
   operator in UDT2:
   Type _UDT1 As UDT1

   Type UDT2
     Dim As Integer I2
     Declare Operator Let (ByRef u As _UDT1)
   End Type

   Type UDT1
     Dim As Integer I1
     Declare Operator Cast () As UDT2
   End Type

   Operator UDT1.Cast () As UDT2
     Print "UDT1.Cast() As UDT2"
     Return This                       '' implicit conversion by compiler using the defined "UDT2.Let(Byref As UDT1)" operator
   End Operator

   Operator UDT2.Let (ByRef u As UDT1)
     Print "UDT2.Let(Byref As UDT1)"
     This.I2 = u.I1
   End Operator

   Dim As UDT1 u1
   u1.I1 = 123

   Print Cast(UDT2, u1).I2

   Sleep
      

Dialect Differences
   * Only available in the -lang fb dialect.

Differences from QB
   * New to FreeBASIC.

See also
   * Cast
   * CPtr
   * CInt
   * TypeOf
   * Coercion and Conversion
    
