Conversion/Inheritance relating to UDTs via constructors and operators

General FreeBASIC programming questions.
Post Reply
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

Conversion

I took advantage of the 'BUG : Illicit "error 202: Illegal member access, UDT.operator.cast" compiler error message' analysis to redo and complete all the conversion cases relating to UDTs.

I also updated and completed the below paragraph of the Coercion and Conversion (Variables and Datatypes) documentation page of the Programmer's Guide:
  • .....
Conversions using User Data Type constructors and operators
  • For conversion between built-in types (among standard types like between numeric types as above or between string types), the compiler knows what to do without the need for instructions from user.
    This is called the implicit internal conversion (or coercion).

    When one of the two types is at least a UDT (User Defined Type), the user has to code some UDT procedures to define how do the conversion.
    Then, the conversion execution can be explicit if the user specifies what UDT procedure must be used, or implicit if the user leaves the choice to compiler.

    In the world of UDTs, conversions can be controlled by means of three member procedures:
    • - Single-argument constructor: allow conversion from a particular type to initialize an object.
      - Assignment operator: allow conversion from a particular type on assignment.
      - Type-cast operator: allow conversion to a particular type.
    For a construction with implicit initialization ('Dim As UDT u = v'), the compiler usually searches:
    • - Firstly a matched constructor (for u type from v type).
      - Secondly a cast operator (for v type to special type (*)) and its matching conversion-constructor (for u type from special type (*)).
      - Thirdly finally a matched cast operator (for v type to u type).
      (a matched let operator (for u type from v type) is not searched by compiler on a construction with implicit initialization)
    For an implicit copy-construction ('Byval As u_type') when passing a v type parameter, the compiler usually searches:
    • - Firstly a matched cast operator (for v type to u type).
      - Secondly a matched constructor (for u type from v type).
      - Thirdly finally a cast operator (for v type to special type (*)) and its matching conversion-constructor (for u type from special type (*)).
      (a matched let operator (for u type from v type) is not searched by compiler on a construction with implicit initialization)
    For an implicit assignment ('u = v'), or an implicit return from function by assigning ('Function = v') with function returning u type, the compiler usually searches:
    • - Firstly a matched let operator (for u type from v type).
      - Secondly a cast operator (for v type to special type (*)) and its matching let operator (for u type from special type (*)).
      - Thirdly a matched cast operator (for v type to u type).
      - Fourthly finally a matched constructor (for u type from v type) and an explicit copy-let operator (u type).
    For an implicit return from function by exiting immediately ('Return v') with function returning u type, the compiler usually searches:
    • - Firstly a matched constructor (for u type from v type).
      - Secondly a cast operator (for v type to special type (*)) and its matching conversion-constructor (for u type from special type (*)).
      If an explicit copy-constructor (u type) exists:
      - Thirdly a matched cast operator (for v type to u type).
      - Fourthly finally a matched let operator (for u type from v type).
      Else (an explicit copy-constructor (u type) does not exist):
      - Thirdly a matched let operator (for u type from v type).
      - Fourthly finally a matched cast operator (for v type to u type).
    special type (*) : pointer or string, or UDT if there is no explicit copy-constructor / explicit copy-assignment operator for u type
.....



Code to check the precedence list above:
This code allows to check the precedence of the constructors/operators for each conversion case (among the five) by commenting or not the #define lines only.

Code: Select all

'' This code allows to check the precedence of the constructors/operators
''    for each conversion case (among the five)
''    by commenting or not the #define lines only.

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
#define equal_as_TU_from_TV
#define function_equal_from_TV_to_TU
#define return_from_TV_to_TU

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Type _TV As TV

Type TU
    Dim As Integer I
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_string
        Declare Constructor(Byref s As String)
    #endif
    #ifdef TU_let_from_TV
        Declare Operator Let(Byref v As _TV)
    #endif
    #ifdef TU_let_from_string
        Declare Operator Let(Byref s As String)
    #endif
    
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef TU_let_from_TU
        Declare Operator Let(Byref u As TU)
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_string
        Declare Operator Cast() As String
    #endif
    #ifdef TV_cast_to_TU
        Declare Operator Cast() As TU
    #endif
End Type

Dim Shared As TU u0
Dim Shared As TV v

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "   Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_string
    Constructor TU(Byref s As String)
        Print "   Constructor TU(Byref As String)"
    End Constructor
#endif

#ifdef TU_let_from_TV
    Operator TU.Let(Byref v As TV)
        Print "   Operator TU.Let(Byref As TV)"
    End Operator
#endif

#ifdef TU_let_from_string
    Operator TU.Let(Byref s As String)
        Print "   Operator TU.Let(Byref As String)"
    End Operator
#endif

Constructor TU()
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef TU_let_from_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#endif

#ifdef TV_cast_to_string
    Operator TV.Cast() As String
        Print "   Operator TV.Cast() As String"
        Return ""
    End Operator
#endif

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef dim_as_TU_from_TV
    Print "'Dim As TU u = v':"
    Dim As TU u = v
    Print
#else
    Dim As TU u
#endif

#ifdef byval_as_TU_from_TV
    Sub s(Byval u As TU)
    End Sub
    Print "'Byval As TU' (from TV):"
    s(v)
    Print
#endif

#ifdef equal_as_TU_from_TV
    Print "'u = v':"
    u = v
    Print
#endif

#ifdef function_equal_from_TV_to_TU
    Function f1() As TU
        Function = v
    End function
    Print "'Function = v' to TU:"
    f1()
    Print
#endif

#ifdef return_from_TV_to_TU
    Function f2() As TU
        Return v
    End function
    Print "'Return v' to TU:"
    f2()
    Print
#endif

Sleep

For the conversion case : 'Dim As TU u = v'

Code: Select all

'' test cases selected:
#define dim_as_TU_from_TV
'#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU
- Precedence 1:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Dim As TU u = v':
   Constructor TU(Byref As TV)
- Precedence 2:

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Dim As TU u = v':
   Operator TV.Cast() As String
   Constructor TU(Byref As String)
- Precedence 3 (also works with just the implicit TU.copy-ctor):

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
'#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Dim As TU u = v':
   Operator TV.Cast() As TU
   Constructor TU(Byref As TU)
   Constructor TU(Byref As TU)

For the conversion case : 'Byval As TU' (from TV)

Code: Select all

'' test cases selected:
'#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU
- Precedence 1 (also works with just the implicit TU.copy-ctor):

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Byval As TU' (from TV):
   Operator TV.Cast() As TU
   Constructor TU(Byref As TU)
   Constructor TU(Byref As TU)
- Precedence 2:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
'#define TV_cast_to_TU

Code: Select all

'Byval As TU' (from TV):
   Constructor TU(Byref As TV)
- Precedence 3:

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
'#define TV_cast_to_TU

Code: Select all

'Byval As TU' (from TV):
   Operator TV.Cast() As String
   Constructor TU(Byref As String)

For the conversion case : 'u = v'

Code: Select all

'' test cases selected:
'#define dim_as_TU_from_TV
'#define byval_as_TU_from_TV
#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU
- Precedence 1:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'u = v':
   Operator TU.Let(Byref As TV)
- Precedence 2:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
'#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'u = v':
   Operator TV.Cast() As String
   Operator TU.Let(Byref As String)
- Precedence 3 (also works with just the implicit TU.copy-ctor and just the implicit TU.copy-let operato):

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
'#define TU_let_from_TV
'#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'u = v':
   Operator TV.Cast() As TU
   Constructor TU(Byref As TU)
   Operator TU.Let(Byref As TU)
- Precedence 4:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
'#define TU_let_from_TV
'#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
'#define TV_cast_to_TU

Code: Select all

'u = v':
   Constructor TU(Byref As TV)
   Operator TU.Let(Byref As TU)

For the conversion case : 'Function = v' to TU

Code: Select all

'' test cases selected:
'#define dim_as_TU_from_TV
'#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU
- Precedence 1:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Function = v' to TU:
   Operator TU.Let(Byref As TV)
- Precedence 2:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
'#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Function = v' to TU:
   Operator TV.Cast() As String
   Operator TU.Let(Byref As String)
- Precedence 3 (also works with just the implicit TU.copy-ctor and just the implicit TU.copy-let operator):

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
'#define TU_let_from_TV
'#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Function = v' to TU:
   Operator TV.Cast() As TU
   Constructor TU(Byref As TU)
   Operator TU.Let(Byref As TU)
- Precedence 4:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
'#define TU_let_from_TV
'#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
'#define TV_cast_to_TU

Code: Select all

'Function = v' to TU:
   Constructor TU(Byref As TV)
   Operator TU.Let(Byref As TU)

For the conversion case : 'Return v' to TU

Code: Select all

'' test cases selected:
'#define dim_as_TU_from_TV
'#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
#define return_from_TV_to_TU
- Precedence 1:

Code: Select all

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Return v' to TU:
   Constructor TU(Byref As TV)
- Precedence 2:

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Return v' to TU:
   Operator TV.Cast() As String
   Constructor TU(Byref As String)
- Precedence 3 if explicit TU.copy-ctor defined:

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
'#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Return v' to TU:
   Operator TV.Cast() As TU
   Constructor TU(Byref As TU)
   Constructor TU(Byref As TU)
- Precedence 4 if explicit TU.copy-ctor defined:

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
'#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
'#define TV_cast_to_TU

Code: Select all

'Return v' to TU:
   Operator TU.Let(Byref As TV)
- Precedence 3 if explicit TU.copy-ctor not defined:

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
'#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
'#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Return v' to TU:
   Operator TU.Let(Byref As TV)
- Precedence 4 if explicit TU.copy-ctor not defined (also works with just the implicit TU.copy-let operator):

Code: Select all

'' constructors/operators defined:
'#define TU_ctor_from_TV
'#define TU_ctor_from_string
'#define TU_let_from_TV
#define TU_let_from_string
'#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
#define TV_cast_to_TU

Code: Select all

'Return v' to TU:
   Operator TV.Cast() As TU
   Operator TU.Let(Byref As TU)
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

Conversion

If we focus only on the configuration tested first ("Firstly" .....) for the 5 conversion cases ('Dim As UDT u = v', 'Byval As u_type', 'u = v', 'Function = v', 'Return v'), we can notice that in general either the matching constructor or the matching let operator is firstly tested (existing), except for the 'Byval ... As ...' conversion for which the matching cast operator is first tested (existing).

For the 'Dim As UDT u = v' conversion case, the test order is:
1. exists a matching constructor,
2. exists a cast operator and its matching conversion-constructor,
3. exists a matching cast operator.
The expected in the first position is rightly the matching constructor.
Example:

Code: Select all

'' This code allows to check the precedence of the constructors/operators
''    for each conversion case (among the five)
''    by commenting or not the #define lines only.

'' test cases selected:
#define dim_as_TU_from_TV
'#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Type _TV As TV

Type TU
    Dim As Integer I
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_string
        Declare Constructor(Byref s As String)
    #endif
    #ifdef TU_let_from_TV
        Declare Operator Let(Byref v As _TV)
    #endif
    #ifdef TU_let_from_string
        Declare Operator Let(Byref s As String)
    #endif
    
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef TU_let_from_TU
        Declare Operator Let(Byref u As TU)
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_string
        Declare Operator Cast() As String
    #endif
    #ifdef TV_cast_to_TU
        Declare Operator Cast() As TU
    #endif
End Type

Dim Shared As TU u0
Dim Shared As TV v

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "   Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_string
    Constructor TU(Byref s As String)
        Print "   Constructor TU(Byref As String)"
    End Constructor
#endif

#ifdef TU_let_from_TV
    Operator TU.Let(Byref v As TV)
        Print "   Operator TU.Let(Byref As TV)"
    End Operator
#endif

#ifdef TU_let_from_string
    Operator TU.Let(Byref s As String)
        Print "   Operator TU.Let(Byref As String)"
    End Operator
#endif

Constructor TU()
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef TU_let_from_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#endif

#ifdef TV_cast_to_string
    Operator TV.Cast() As String
        Print "   Operator TV.Cast() As String"
        Return ""
    End Operator
#endif

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef dim_as_TU_from_TV
    Print "'Dim As TU u = v':"
    Dim As TU u = v
    Print
#else
    Dim As TU u
#endif

#ifdef byval_as_TU_from_TV
    Sub s(Byval u As TU)
    End Sub
    Print "'Byval As TU' (from TV):"
    s(v)
    Print
#endif

#ifdef equal_as_TU_from_TV
    Print "'u = v':"
    u = v
    Print
#endif

#ifdef function_equal_from_TV_to_TU
    Function f1() As TU
        Function = v
    End function
    Print "'Function = v' to TU:"
    f1()
    Print
#endif

#ifdef return_from_TV_to_TU
    Function f2() As TU
        Return v
    End function
    Print "'Return v' to TU:"
    f2()
    Print
#endif

Sleep

Code: Select all

'Dim As TU u = v':
   Constructor TU(Byref As TV)

For this ''Byval As u_type'' conversion case, the test order is:
1. exists a matching cast operator,
2. exists a matching constructor,
3. exists a cast operator and its matching conversion-constructor.
The expected in the first position would be the matching constructor rather the matching cast operator.
Example:

Code: Select all

'' This code allows to check the precedence of the constructors/operators
''    for each conversion case (among the five)
''    by commenting or not the #define lines only.

'' test cases selected:
'#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TV_cast_to_string
#define TV_cast_to_TU

Type _TV As TV

Type TU
    Dim As Integer I
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_string
        Declare Constructor(Byref s As String)
    #endif
    #ifdef TU_let_from_TV
        Declare Operator Let(Byref v As _TV)
    #endif
    #ifdef TU_let_from_string
        Declare Operator Let(Byref s As String)
    #endif
    
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef TU_let_from_TU
        Declare Operator Let(Byref u As TU)
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_string
        Declare Operator Cast() As String
    #endif
    #ifdef TV_cast_to_TU
        Declare Operator Cast() As TU
    #endif
End Type

Dim Shared As TU u0
Dim Shared As TV v

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "   Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_string
    Constructor TU(Byref s As String)
        Print "   Constructor TU(Byref As String)"
    End Constructor
#endif

#ifdef TU_let_from_TV
    Operator TU.Let(Byref v As TV)
        Print "   Operator TU.Let(Byref As TV)"
    End Operator
#endif

#ifdef TU_let_from_string
    Operator TU.Let(Byref s As String)
        Print "   Operator TU.Let(Byref As String)"
    End Operator
#endif

Constructor TU()
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef TU_let_from_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#endif

#ifdef TV_cast_to_string
    Operator TV.Cast() As String
        Print "   Operator TV.Cast() As String"
        Return ""
    End Operator
#endif

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef dim_as_TU_from_TV
    Print "'Dim As TU u = v':"
    Dim As TU u = v
    Print
#else
    Dim As TU u
#endif

#ifdef byval_as_TU_from_TV
    Sub s(Byval u As TU)
    End Sub
    Print "'Byval As TU' (from TV):"
    s(v)
    Print
#endif

#ifdef equal_as_TU_from_TV
    Print "'u = v':"
    u = v
    Print
#endif

#ifdef function_equal_from_TV_to_TU
    Function f1() As TU
        Function = v
    End function
    Print "'Function = v' to TU:"
    f1()
    Print
#endif

#ifdef return_from_TV_to_TU
    Function f2() As TU
        Return v
    End function
    Print "'Return v' to TU:"
    f2()
    Print
#endif

Sleep

Code: Select all

'Byval As TU' (from TV):
   Operator TV.Cast() As TU
   Constructor TU(Byref As TU)
   Constructor TU(Byref As TU)
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

Conversion

On the other hand, we can see in the first post above that both the matched constructor (for u type from v type) and the matched let operator (for u type from v type) can be used (among the 4 possibilities) for the last two conversion cases, but only the matched constructor (for u type from v type) can be used (among the 3 possibilities) for the first two conversion cases.
(while we could also have had the matched let operator (for u type from v type) used (in a 4th possibility) for the first two conversion cases)

Example that fails:

Code: Select all

'' This code allows to check the precedence of the constructors/operators
''    for each conversion case (among the five)
''    by commenting or not the #define lines only.

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
'#define equal_as_TU_from_TV
'#define function_equal_from_TV_to_TU
'#define return_from_TV_to_TU

'' constructors/operators defined:
'#define TU_ctor_from_TV
'#define TU_ctor_from_string
#define TU_let_from_TV
#define TU_let_from_string
#define TU_ctor_from_TU
#define TU_let_from_TU
'#define TV_cast_to_string
'#define TV_cast_to_TU

Type _TV As TV

Type TU
    Dim As Integer I
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_string
        Declare Constructor(Byref s As String)
    #endif
    #ifdef TU_let_from_TV
        Declare Operator Let(Byref v As _TV)
    #endif
    #ifdef TU_let_from_string
        Declare Operator Let(Byref s As String)
    #endif
    
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef TU_let_from_TU
        Declare Operator Let(Byref u As TU)
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_string
        Declare Operator Cast() As String
    #endif
    #ifdef TV_cast_to_TU
        Declare Operator Cast() As TU
    #endif
End Type

Dim Shared As TU u0
Dim Shared As TV v

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "   Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_string
    Constructor TU(Byref s As String)
        Print "   Constructor TU(Byref As String)"
    End Constructor
#endif

#ifdef TU_let_from_TV
    Operator TU.Let(Byref v As TV)
        Print "   Operator TU.Let(Byref As TV)"
    End Operator
#endif

#ifdef TU_let_from_string
    Operator TU.Let(Byref s As String)
        Print "   Operator TU.Let(Byref As String)"
    End Operator
#endif

Constructor TU()
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef TU_let_from_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#endif

#ifdef TV_cast_to_string
    Operator TV.Cast() As String
        Print "   Operator TV.Cast() As String"
        Return ""
    End Operator
#endif

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef dim_as_TU_from_TV
    Print "'Dim As TU u = v':"
    Dim As TU u = v
    Print
#else
    Dim As TU u
#endif

#ifdef byval_as_TU_from_TV
    Sub s(Byval u As TU)
    End Sub
    Print "'Byval As TU' (from TV):"
    s(v)
    Print
#endif

#ifdef equal_as_TU_from_TV
    Print "'u = v':"
    u = v
    Print
#endif

#ifdef function_equal_from_TV_to_TU
    Function f1() As TU
        Function = v
    End function
    Print "'Function = v' to TU:"
    f1()
    Print
#endif

#ifdef return_from_TV_to_TU
    Function f2() As TU
        Return v
    End function
    Print "'Return v' to TU:"
    f2()
    Print
#endif

Sleep
Wished output for example:

Code: Select all

'Dim As TU u = v':
   Operator TU.Let(Byref As TV)
   Constructor TU(Byref As TU)

'Byval As TU' (from TV):
   Operator TU.Let(Byref As TV)
   Constructor TU(Byref As TU)
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

fxm wrote: Nov 10, 2022 13:27 If we focus only on the configuration tested first ("Firstly" .....) for the 5 conversion cases ('Dim As UDT u = v', 'Byval As u_type', 'u = v', 'Function = v', 'Return v'), we can notice that in general either the matching constructor or the matching let operator is firstly tested (existing), except for the 'Byval As ...' conversion for which the matching cast operator is first tested (existing).

Inheritance

Similarly, if we go from conversion to inheritance (Parent <- Child), for the following 5 expression cases:
'Dim Shared As Child c1'
'Dim As Child c2 = c1'
'Byval c As Child'
'Function = c1'
'Return c1'

We can notice below that the explicit Parent's constructor and the explicit Parent's let operator are both called, except for the 'Byval c As Child' expression for which this is true only if an explicit Parent's destructor is additionally defined (otherwise an internal construction and a shallow copy are executed for the Parent's part).

Test code:

Code: Select all

#define Parent_dtor

Type Parent
    Dim As Integer I
    Declare Constructor()
    Declare Constructor(Byref u As Parent)
    Declare Operator Let(Byref u As Parent)
    #ifdef Parent_dtor
        Declare Destructor()
    #endif
End Type

Constructor Parent()
    Print "   Constructor Parent()"
End Constructor

Constructor Parent(Byref u As Parent)
    Print "   Constructor Parent(Byref As Parent)"
End Constructor

Operator Parent.Let(Byref u As Parent)
    Print "   Operator Parent.Let(Byref As Parent)"
End Operator

#ifdef Parent_dtor
    Destructor Parent()
    End destructor
#endif

Type Child Extends Parent
End Type

Dim Shared As Child c1
Print

Print "'Dim As Child c2 = c1':"
Dim As Child c2 = c1
Print

Sub s(Byval c As Child)
End Sub
Print "'Byval As Child' from Child:"
s(c1)
Print

Function f1() As Child
    Function = c1
End function
Print "'Function = c1' to Child:"
f1()
Print

Function f2() As Child
    Return c1
End function
Print "'Return c1' to Child:"
f2()
Print

Sleep

With explicit Base destructor:

Code: Select all

#define Parent_dtor

Code: Select all

   Constructor Parent()

'Dim As Child c2 = c1':
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)

'Byval As Child' from Child:
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)

'Function = c1' to Child:
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)

'Return c1' to Child:
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)

Without explicit Base destructor:

Code: Select all

'#define Parent_dtor

Code: Select all

   Constructor Parent()

'Dim As Child c2 = c1':
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)

'Byval As Child' from Child:

'Function = c1' to Child:
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)

'Return c1' to Child:
   Constructor Parent()
   Operator Parent.Let(Byref As Parent)
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

Conversion/Inheritance

So for the two features which are conversion (see 3 posts before) and inheritance (post above) relating to UDTs, we can notice that the 'Byval ... As UDT' expression has a degraded performance compared to other 2 copy-construction expressions ('Dim As UDT ... = ...' and 'Return ...').

Test code combining conversion (v -> u) and inheritance (TU <- TW) to highlight the behavior of 'Byval ... As UDT', compared to 'Dim As UDT ... = ...' and 'Return ...':

Code: Select all

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
#define return_from_TV_to_TU
#define dim_as_TW_from_TW
#define byval_as_TW_from_TW
#define return_from_TW_to_TW

'' constructors/operators defined:
#define TU_dtor
#define TV_cast_to_TU

Type _TV As TV

Type TU
    Dim As Integer I
    Declare Constructor()
    Declare Constructor(Byref v As _TV)
    Declare Operator Let(Byref u As TU)
    #ifdef TU_dtor
        Declare Destructor()
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_TU
        Declare Operator Cast() As TU
    #endif
End Type

Type TW Extends TU
End Type

Dim Shared As TU u0
Dim Shared As TV v
Dim Shared As TW w

Constructor TU()
    If (@This <> @u0) And (@This <> @w) Then
        Print "   Constructor TU()"
    End If
End Constructor

Constructor TU(Byref v As TV)
    Print "   Constructor TU(Byref As TV)"
End Constructor

Operator TU.Let(Byref u As TU)
    Print "   Operator TU.Let(Byref As TU)"
End Operator

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef TU_dtor
    Destructor TU()
    End Destructor
#endif

#ifdef dim_as_TU_from_TV
    Print "'Dim As TU u = v':"
    Dim As TU u = v
    Print
#endif

#ifdef byval_as_TU_from_TV
    Sub s1(Byval u As TU)
    End Sub
    Print "'Byval As TU' (from TV):"
    s1(v)
    Print
#endif

#ifdef return_from_TV_to_TU
    Function f1() As TU
        Return v
    End function
    Print "'Return v' to TU:"
    f1()
    Print
#endif

#ifdef dim_as_TW_from_TW
    Print "'Dim As TW w1 = w':"
    Dim As TW w1 = w
    Print
#endif

#ifdef byval_as_TW_from_TW
    Sub s2(Byval w As TW)
    End Sub
    Print "'Byval As TW' (from TW):"
    s2(w)
    Print
#endif

#ifdef return_from_TW_to_TW
    Function f2() As TW
        Return w
    End function
    Print "'Return w' to TW:"
    f2()
    Print
#endif

Sleep

1) Conversion (v -> u):

Code: Select all

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
#define return_from_TV_to_TU
'#define dim_as_TW_from_TW
'#define byval_as_TW_from_TW
'#define return_from_TW_to_TW
Without cast operator in TV => OK:

Code: Select all

'' constructors/operators defined:
#define TU_dtor
'#define TV_cast_to_TU

Code: Select all

'Dim As TU u = v':
   Constructor TU(Byref As TV)

'Byval As TU' (from TV):
   Constructor TU(Byref As TV)

'Return v' to TU:
   Constructor TU(Byref As TV)
With cast operator in TV => NOK for 'Byval As TU' (from TV):
(cast operator instead of conversion-constructor)

Code: Select all

'' constructors/operators defined:
#define TU_dtor
#define TV_cast_to_TU

Code: Select all

'Dim As TU u = v':
   Constructor TU(Byref As TV)

'Byval As TU' (from TV):
   Operator TV.Cast() As TU

'Return v' to TU:
   Constructor TU(Byref As TV)

2) Inheritance (TU <- TW):

Code: Select all

'' test cases selected:
'#define dim_as_TU_from_TV
'#define byval_as_TU_from_TV
'#define return_from_TV_to_TU
#define dim_as_TW_from_TW
#define byval_as_TW_from_TW
#define return_from_TW_to_TW
With destructor in TU => OK:

Code: Select all

'' constructors/operators defined:
#define TU_dtor
#define TV_cast_to_TU

Code: Select all

'Dim As TW w1 = w':
   Constructor TU()
   Operator TU.Let(Byref As TU)

'Byval As TW' (from TW):
   Constructor TU()
   Operator TU.Let(Byref As TU)

'Return w' to TW:
   Constructor TU()
   Operator TU.Let(Byref As TU)
Without destructor in TU => NOK for 'Byval As TW' (from TW):
(interne construction + shallow copy, instead of explicit default-constructor + explicit copy-let operator)

Code: Select all

'' constructors/operators defined:
'#define TU_dtor
#define TV_cast_to_TU

Code: Select all

'Dim As TW w1 = w':
   Constructor TU()
   Operator TU.Let(Byref As TU)

'Byval As TW' (from TW):

'Return w' to TW:
   Constructor TU()
   Operator TU.Let(Byref As TU)

3) Conversion with Inheritance (w -> u with TU <- TW)
Same bad behavior of 'Byval As TU' (from TW) if there is no explicit copy-constructor defined in TU, but all the time whether there is an explicit destructor defined in TU or not:

Code: Select all

'' test cases selected:
#define dim_as_TU_from_TW
#define byval_as_TU_from_TW
#define return_from_TW_to_TU

'' constructors/operators defined:
'#define TU_ctor_from_TU
#define TU_dtor

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    Declare Operator Let(Byref u As TU)
    #ifdef TU_dtor
        Declare Destructor()
    #endif
End Type

Type TW Extends TU
End Type

Dim Shared As TW w

Constructor TU()
    If @This <> @w Then
        Print "   Constructor TU()"
    End If
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor(Byref u As TU)"
    End constructor
#endif

Operator TU.Let(Byref u As TU)
    Print "   Operator TU.Let(Byref As TU)"
End Operator

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef TU_dtor
    Destructor TU()
    End Destructor
#endif

#ifdef dim_as_TU_from_TW
    Print "'Dim As TU u = w':"
    Dim As TU u = w
    Print
#endif

#ifdef byval_as_TU_from_TW
    Sub s(Byval u As TU)
    End Sub
    Print "'Byval As TU' (from TW):"
    s(W)
    Print
#endif

#ifdef return_from_TW_to_TU
    Function f() As TU
        Return w
    End function
    Print "'Return w' to TU:"
    f()
    Print
#endif

Sleep

Code: Select all

'Dim As TU u = w':
   Constructor TU()
   Operator TU.Let(Byref As TU)

'Byval As TU' (from TW):

'Return w' to TU:
   Constructor TU()
   Operator TU.Let(Byref As TU)

In summary, in a lot of configurations, 'Byval ... As UDT' does not behave (degraded performance) like the other 2 copy-constructions 'Dim As UDT ... = ...' and 'Return ...'.
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

Conversion/inheritance

A most complete code allowing to test all the conversion/inheritance cases seen in all the previous posts:

Code: Select all

'' This code allows to check the precedence of the constructors/operators (among the nine)
''    for each conversion/inheritance case (among the fifteen)
''    by commenting or not the #define lines only.

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
#define equal_as_TU_from_TV
#define function_equal_from_TV_to_TU
#define return_from_TV_to_TU
#define dim_as_TW_from_TW
#define byval_as_TW_from_TW
#define equal_as_TW_from_TW
#define function_equal_from_TW_to_TW
#define return_from_TW_to_TW
#define dim_as_TU_from_TW
#define byval_as_TU_from_TW
#define equal_as_TU_from_TW
#define function_equal_from_TW_to_TU
#define return_from_TW_to_TU

'' constructors/operators defined:
#define TU_ctor_from_TV
#define TU_ctor_from_TX
#define TU_let_from_TV
#define TU_let_from_TX
#define TU_ctor_from_TU
#define TU_let_from_TU
#define TU_dtor
#define TV_cast_to_TX
#define TV_cast_to_TU

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
#define TX_as_string
'#define TX_as_UDT_with_integer
'#define TX_as_UDT_with_string

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Dim Shared As TX x0

Type _TV As TV

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef TU_let_from_TU
        Declare Operator Let(Byref u As TU)
    #endif
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_TX
        Declare Constructor(Byref s As TX)
    #endif
    #ifdef TU_let_from_TV
        Declare Operator Let(Byref v As _TV)
    #endif
    #ifdef TU_let_from_TX
        Declare Operator Let(Byref s As TX)
    #endif
    #ifdef TU_dtor
        Declare Destructor()
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_TX
        Declare Operator Cast() As TX
    #endif
    #ifdef TV_cast_to_TU
        Declare Operator Cast() As TU
    #endif
End Type

Type TW Extends TU
End Type

Dim Shared As TU u0
Dim Shared As TV v
Dim Shared As TW w0, w1

Constructor TU()
    If (@This <> @u0) And (@This <> @w0) AND (@This <> @w1) Then
        Print "   Constructor TU()"
    End If
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "   Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_TX
    Constructor TU(Byref s As TX)
        Print "   Constructor TU(Byref As TX)"
    End Constructor
#endif

#ifdef TU_let_from_TV
    Operator TU.Let(Byref v As TV)
        Print "   Operator TU.Let(Byref As TV)"
    End Operator
#endif

#ifdef TU_let_from_TX
    Operator TU.Let(Byref s As TX)
        Print "   Operator TU.Let(Byref As TX)"
    End Operator
#endif

#ifdef TU_let_from_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#endif

#ifdef TU_dtor
    Destructor TU()
    End destructor
#endif

#ifdef TV_cast_to_TX
    Operator TV.Cast() As TX
        Print "   Operator TV.Cast() As TX"
        Return x0
    End Operator
#endif

#ifdef TV_cast_to_TU
    Operator TV.Cast() As TU
        Print "   Operator TV.Cast() As TU"
        Return u0
    End Operator
#endif

#ifdef byval_as_TU_from_TV
    Sub s1(Byval u As TU)
    End Sub
#endif

#ifdef function_equal_from_TV_to_TU
    Function f11() As TU
        Function = v
    End function
#endif

#ifdef return_from_TV_to_TU
    Function f12() As TU
        Return v
    End function
#endif

#ifdef byval_as_TW_from_TW
    Sub s21(Byval w As TW)
    End Sub
#endif

#ifdef function_equal_from_TW_to_TW
    Function f21() As TW
        Function = w0
    End function
#endif

#ifdef return_from_TW_to_TW
    Function f22() As TW
        Return w0
    End function
#endif

#ifdef byval_as_TU_from_TW
    Sub s31(Byval u As TU)
    End Sub
#endif

#ifdef function_equal_from_TW_to_TU
    Function f31() As TU
        Function = w0
    End function
#endif

#ifdef return_from_TW_to_TU
    Function f32() As TU
        Return w0
    End function
#endif

Print "-------------------- Conversion (v -> u) ---------------------"
Print

Scope
    #ifdef dim_as_TU_from_TV
        Print "'Dim As TU u = v':"
        Dim As TU u = v
        Print
    #else
        Dim Byref As TU u = u0
    #endif

    #ifdef byval_as_TU_from_TV
        Print "'Byval As TU' (from TV):"
        s1(v)
        Print
    #endif

    #ifdef equal_as_TU_from_TV
        Print "'u = v':"
        u = v
        Print
    #endif

    #ifdef function_equal_from_TV_to_TU
        Print "'Function = v' to TU:"
        f11()
        Print
    #endif

    #ifdef return_from_TV_to_TU
        Print "'Return v' to TU:"
        f12()
        Print
    #endif
End Scope

Print "------------------- Inheritance (TU <- TW) -------------------"
Print

Scope
    #ifdef dim_as_TW_from_TW
        Print "'Dim As TW w = w0':"
        Dim As TW w = w0
        Print
    #else
        Dim Byref As TW w = w0
    #endif

    #ifdef byval_as_TW_from_TW
        Print "'Byval As TW' (from TW):"
        s21(w)
        Print
    #endif

    #ifdef equal_as_TW_from_TW
        Print "'w = w0':"
        w = w0
        Print
    #endif

    #ifdef function_equal_from_TW_to_TW
        Print "'Function = w' to TW:"
        f21()
        Print
    #endif

    #ifdef return_from_TW_to_TW
        Print "'Return w' to TW:"
        f22()
        Print
    #endif
End Scope

Print "----- Conversion with Inheritance (w -> u with TU <- TW) -----"
Print

Scope
    Dim Byref As TW w = w0
    #ifdef dim_as_TU_from_TW
        Print "'Dim As TU u = w':"
        Dim As TU u = w
        Print
    #endif

    #ifdef byval_as_TU_from_TW
        Print "'Byval As TU' (from TW):"
        s31(w)
        Print
    #endif

    #ifdef equal_as_TU_from_TW
        Print "'u = w':"
        u0 = w
        Print
    #endif

    #ifdef function_equal_from_TW_to_TU
        Print "'Function = w' to TU:"
        f31()
        Print
    #endif

    #ifdef return_from_TW_to_TU
        Print "'Return w' to TU:"
        f32()
        Print
    #endif
End Scope

Sleep
fxm
Moderator
Posts: 11414
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Conversion/Inheritance relating to UDTs via constructors and operators

Post by fxm »

Indirect Conversion

Conversion between two UDTs 'TU' and 'TV' : v -> u , but via a third-party type 'TX' : v -> x -> u

This kind of conversion (via a third-party type) uses a cast operator in the 'TV' type (v -> x), and a conversion-constructor or copy-assignment operator in the 'TU' type (x -> u).

All types are not illegible as third-party type for this indirect conversion:
- elementary built-in types: only pointer and string, the other numeric types do not work.
- UDT but only if there is no explicit copy-constructor or explicit copy-assignment operator (depending on the conversion expression) for the 'TU' type.

Simple example for copy-construction with indirect conversion:
'Dim As TU u = v'
performed via:
'Dim As TU u = x' with 'x = Cast(TX, v)'
so:
'TU.Ctor_from_TX( TV.Cast_to_TX( v ) )'
We can select the kind of the 'TX' type and if an explicit copy-constructor exists for the 'TU' type.
1) Example with string as third-party type:

Code: Select all

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
#define TX_as_string
'#define TX_as_UDT_with_integer
'#define TX_as_UDT_with_string

'' constructors defined:
#define copy_constructor_TU

'----------------------------

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef copy_constructor_TU
        Declare Constructor(Byref u As TU)
    #endif
    Declare Constructor(Byref x As TX)
End Type

Constructor TU()
End constructor

#ifdef copy_constructor_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

Constructor TU(Byref x As TX)
    Print "   Constructor TU(Byref As TX)"
End Constructor

Type TV
    Dim As Integer I
    Declare Operator Cast() As TX
End Type

Operator TV.Cast() As TX
    Print "   Operator TV.Cast() As TX"
    Dim As TX x0
    Return x0
End Operator

Dim As TV v

Print "'Dim As TU u = v':"
Dim As TU u = v

Sleep

Code: Select all

'Dim As TU u = v':
   Operator TV.Cast() As TX
   Constructor TU(Byref As TX)
2) Example with UDT (with integer field) as third-party type and with explicit copy-constructor for 'TU' type:

Code: Select all

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
'#define TX_as_string
#define TX_as_UDT_with_integer
'#define TX_as_UDT_with_string

'' constructors defined:
#define copy_constructor_TU

'----------------------------

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef copy_constructor_TU
        Declare Constructor(Byref u As TU)
    #endif
    Declare Constructor(Byref x As TX)
End Type

Constructor TU()
End constructor

#ifdef copy_constructor_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

Constructor TU(Byref x As TX)
    Print "   Constructor TU(Byref As TX)"
End Constructor

Type TV
    Dim As Integer I
    Declare Operator Cast() As TX
End Type

Operator TV.Cast() As TX
    Print "   Operator TV.Cast() As TX"
    Dim As TX x0
    Return x0
End Operator

Dim As TV v

Print "'Dim As TU u = v':"
Dim As TU u = v

Sleep
C:\.....\FBIDETEMP.bas(73) error 58: Type mismatch, at parameter 1 (u) of TU.constructor(as TU) in 'Dim As TU u = v'
3) Example with UDT (with integer field) as third-party type and without explicit copy-constructor for 'TU' type:

Code: Select all

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
'#define TX_as_string
#define TX_as_UDT_with_integer
'#define TX_as_UDT_with_string

'' constructors defined:
'#define copy_constructor_TU

'----------------------------

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef copy_constructor_TU
        Declare Constructor(Byref u As TU)
    #endif
    Declare Constructor(Byref x As TX)
End Type

Constructor TU()
End constructor

#ifdef copy_constructor_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

Constructor TU(Byref x As TX)
    Print "   Constructor TU(Byref As TX)"
End Constructor

Type TV
    Dim As Integer I
    Declare Operator Cast() As TX
End Type

Operator TV.Cast() As TX
    Print "   Operator TV.Cast() As TX"
    Dim As TX x0
    Return x0
End Operator

Dim As TV v

Print "'Dim As TU u = v':"
Dim As TU u = v

Sleep

Code: Select all

'Dim As TU u = v':
   Operator TV.Cast() As TX
   Constructor TU(Byref As TX)
4) Example with UDT (with string field) as third-party type and with explicit copy-constructor for 'TU' type:

Code: Select all

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
'#define TX_as_string
'#define TX_as_UDT_with_integer
#define TX_as_UDT_with_string

'' constructors defined:
#define copy_constructor_TU

'----------------------------

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef copy_constructor_TU
        Declare Constructor(Byref u As TU)
    #endif
    Declare Constructor(Byref x As TX)
End Type

Constructor TU()
End constructor

#ifdef copy_constructor_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

Constructor TU(Byref x As TX)
    Print "   Constructor TU(Byref As TX)"
End Constructor

Type TV
    Dim As Integer I
    Declare Operator Cast() As TX
End Type

Operator TV.Cast() As TX
    Print "   Operator TV.Cast() As TX"
    Dim As TX x0
    Return x0
End Operator

Dim As TV v

Print "'Dim As TU u = v':"
Dim As TU u = v

Sleep
C:\.....\FBIDETEMP.bas(73) error 98: Ambiguous call to overloaded function, TU.constructor() in 'Dim As TU u = v'
5) Example with UDT (with string field) as third-party type and without explicit copy-constructor for 'TU' type:

Code: Select all

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
'#define TX_as_string
'#define TX_as_UDT_with_integer
#define TX_as_UDT_with_string

'' constructors defined:
'#define copy_constructor_TU

'----------------------------

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef copy_constructor_TU
        Declare Constructor(Byref u As TU)
    #endif
    Declare Constructor(Byref x As TX)
End Type

Constructor TU()
End constructor

#ifdef copy_constructor_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

Constructor TU(Byref x As TX)
    Print "   Constructor TU(Byref As TX)"
End Constructor

Type TV
    Dim As Integer I
    Declare Operator Cast() As TX
End Type

Operator TV.Cast() As TX
    Print "   Operator TV.Cast() As TX"
    Dim As TX x0
    Return x0
End Operator

Dim As TV v

Print "'Dim As TU u = v':"
Dim As TU u = v

Sleep

Code: Select all

'Dim As TU u = v':
   Operator TV.Cast() As TX
   Constructor TU(Byref As TX)

For copy-assignment with indirect conversion, the behavior is a bit more complex.
Usually:
'u = v'
performed via:
'u = x' with 'x = Cast(TX, v)'
so:
'TU.Let_from_TX( TV.Cast_to_TX ( v ) )'
But in the case where the third-party type is a UDT with an integer field (and not a string field) a second behavior is encountered if an explicit copy-assignment operator exists for the 'TU' type:
'u = v'
performed via:
'u = u0' with ('Dim As TU u0 = x' with 'x = Cast(TX, v)')
so:
'TU.Let_from_TU( TU.Ctor_from_TX( TV.Cast_to_TX( v ) ) )'
Code allowing to check all this, but parameterized here for the non-usual case

Code: Select all

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
'#define TX_as_string
#define TX_as_UDT_with_integer
'#define TX_as_UDT_with_string

'' constructors defined:
'#define copy_constructor_TU
#define copy_assignment_TU

'----------------------------

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef copy_constructor_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef copy_assignment_TU
        Declare Operator Let(Byref u As TU)
    #endif
    Declare Constructor(Byref x As TX)
    Declare Operator Let(Byref x As TX)
End Type

Constructor TU()
End constructor

#ifdef copy_constructor_TU
    Constructor TU(Byref u As TU)
        Print "   Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef copy_assignment_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#endif

Constructor TU(Byref x As TX)
    Print "   Constructor TU(Byref As TX)"
End Constructor

Operator TU.Let(Byref x As TX)
    Print "   Operator TU.Let(Byref As TX)"
End Operator

Type TV
    Dim As Integer I
    Declare Operator Cast() As TX
End Type

Operator TV.Cast() As TX
    Print "   Operator TV.Cast() As TX"
    Dim As TX x0
    Return x0
End Operator

Dim As TU u
Dim As TV v

Print "'u = v':"
u = v

Sleep

Code: Select all

'u = v':
   Operator TV.Cast() As TX
   Constructor TU(Byref As TX)
   Operator TU.Let(Byref As TU)
Post Reply