Conversion/Inheritance relating to UDTs via constructors and operators

General FreeBASIC programming questions.
coderJeff
Site Admin
Posts: 4081
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

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

Post by coderJeff »

coderJeff wrote: Dec 28, 2022 17:06 I have an idea how to correct the troublesome case posted, but thought I should try and get some of these tests in to the test-suite to help check any regressions.
I think I have a change is fairly precise, and I think is correct. Here are the proposed changes based on the first test code at the top of this thread.

Brief description:
- in some places where we would have had TV.CAST() as TU + TU.constructor(TU)
- we now have a more direct path preferred of TU.constructor( TV )


In the following combinations tested:

Code: Select all

TU_ctor_from_TV       Y  Y  Y  Y           
TU_ctor_from_string   Y  Y  Y  Y 
TU_let_from_TV        Y  -  -  -
TU_let_from_string    Y  -  -  -
TU_ctor_from_TU       Y  -  -  Y
TU_let_from_TU        Y  -  -  Y
TV_cast_to_string     Y  Y  -  -
TV_cast_to_TU         Y  Y  Y  Y

CHANGES:              A  A  A  B
Where A and B are the following changes:

Code: Select all

A - byval_as_TU_from_TV
  - call order before: TV_cast_to_TU + TU_ctor_from_TU
  - call order after : TU_ctor_from_TV

B - changes in A above, plus
  - equal_as_TU_from_TV, and
  - function_equal_from_TV_to_TU
  - call order before: TV_cast_to_TU + TU_ctor_from_TU + TU_let_from_TU
  - call order after: TU_ctor_from_TV + TU_let_from_TU    
EDIT:
- I can also do just the changes from A and not the changes of B.
- If we wanted to only change passing BYVAL UDT and not affect 'u = v' and 'function = v'
coderJeff
Site Admin
Posts: 4081
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

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

Post by coderJeff »

coderJeff wrote: Dec 29, 2022 13:49 EDIT:
- I can also do just the changes from A and not the changes of B.
- If we wanted to only change passing BYVAL UDT and not affect 'u = v' and 'function = v'
I decided to do this as it should give us some positive results, but induce the least number of changes for now. Probably better to make a small incremental change for this work.

Code: Select all

type _tv as tv

type tu
    dim as integer i
    declare constructor()
    declare constructor(byref v as _tv)
end type

type tv
    dim as integer i
    declare operator cast() as tu
end type

constructor tu()
	print "    constructor tu()"
end constructor

constructor tu(byref v as tv)
	print "    constructor tu(byref v as tv)"
end constructor

operator tv.cast() as tu
	print "    operator tv.cast() as tu"
	return tu()
end operator

sub s1(byval u as tu)
end sub

sub s2(byref u as tu)
end sub

dim x as tv
print "s1(byval tv)"
s1(x)
print "s2(byref tv)"
s2(x)
With the changes:

FreeBasic 1.09.0

Code: Select all

s1(byval tv)
    operator tv.cast() as tu
    constructor tu()
s2(byref tv)
    operator tv.cast() as tu
    constructor tu()
FreeBasic 1.10.0

Code: Select all

s1(byval tv)
    constructor tu(byref v as tv)
s2(byref tv)
    operator tv.cast() as tu
    constructor tu()
fxm
Moderator
Posts: 11557
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

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). Note: implicit copy-constructor (u type) sufficient
    - 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). Note: implicit copy-let operator (u type) sufficient
    - Fourthly finally a matched constructor (for u type from v type) and an explicit copy-let operator (u type). Note: explicit copy-let operator (u type) mandatory

Referring to just above:
- Change A ('Byval As u_type'): OK to swap the first and second priorities.
- Change B ('u = v' and 'Function = v'): OK to swap the third and forth priorities, because an explicit copy-let operator (u type) is mandatory for the forth priority whereas it is not the case for the third priority.
coderJeff
Site Admin
Posts: 4081
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

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

Post by coderJeff »

fxm wrote: Dec 29, 2022 15:26 Referring to just above:
- Change A ('Byval As u_type'): OK to swap the first and second priorities.
- Change B ('u = v' and 'Function = v'): OK to swap the third and forth priorities, because an explicit copy-let operator (u type) is mandatory for the forth priority whereas it is not the case for the third priority.
Thanks, fxm. That clears up a some confusion I had working on this. I am fairly comfortable with change A.

For change B, I notice now that I haven't really been paying attention to types passed BYREF. At the very least I will go back and add to the test-suite so we can track regressions. The change for 'B' is literally a one line change in fbc source, but I see now that it has affects on passing arguments BYREF.

What do you think? Passing BYREF currently may induce some CAST/Constructor calls. Does passing BYREF follow any of the 5 cases analyzed so far?

EDIT:
not sure if this is the complication or not, but it is probably one of the complications:
`Operator LET( [BYVAL|BYREF] arg as T )` is in of itself a procedure taking an argument. Therefore some part of LET's behaviour will be affected by how arguments are implicitly converted. Like when passed BYVAL or BYREF.
Probably also some similar kinds of interaction for CONSTRUCTORs too taking either BYVAL or BYREF parameters.
fxm
Moderator
Posts: 11557
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

In my second version of the test program, the Cast operators return by reference to hide the constructions due to these own operators, in order to better interpret the results.

I modified this second version to add the 'byref_as_TU_from_TV' case:

Code: Select all

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

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
#define byref_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_TU
#define TU_ctor_from_TV
#define TU_ctor_from_TX
#define TU_let_from_TU
#define TU_let_from_TV
#define TU_let_from_TX
#define TU_dtor
#define TV_cast_to_TU
#define TV_cast_to_TX

'' 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

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_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_TU
        Declare Operator Let(Byref u As TU)
    #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_TU
        Declare Operator Cast() Byref As TU
    #endif
    #ifdef TV_cast_to_TX
        Declare Operator Cast() Byref As TX
    #endif
End Type

Type TW Extends TU
End Type

Dim Shared As TX x0
Dim Shared As TU u0
Dim Shared As TV v
Dim Shared As TW w0

Constructor TU()
    If (@This <> @u0) And (@This <> @w0) 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_TU
    Operator TU.Let(Byref u As TU)
        Print "   Operator TU.Let(Byref As TU)"
    End Operator
#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_dtor
    Destructor TU()
    End destructor
#endif

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

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

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

#ifdef byref_as_TU_from_TV
    Sub s2(Byref 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 byref_as_TU_from_TV
        Print "'Byref As TU' (from TV):"
        s2(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

The results, for 'byval_as_TU_from_TV' and 'byref_as_TU_from_TV' only, are as follows:

Code: Select all

Priority 1

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

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

Code: Select all

Priority 2

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

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

Code: Select all

Priority 3

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

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

I think the 'byref_as_TU_from_TV' case should not be modified:
- The first priority must remain a cast only (no new object construction).
- Only the second and third priorities construct a new object (from the v instance) which will be then passed by reference.
fxm
Moderator
Posts: 11557
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

coderJeff wrote: Dec 29, 2022 15:50 EDIT:
not sure if this is the complication or not, but it is probably one of the complications:
`Operator LET( [BYVAL|BYREF] arg as T )` is in of itself a procedure taking an argument. Therefore some part of LET's behaviour will be affected by how arguments are implicitly converted. Like when passed BYVAL or BYREF.
Probably also some similar kinds of interaction for CONSTRUCTORs too taking either BYVAL or BYREF parameters.

About cases:
- dim_as_TU_from_TV
- byval_as_TU_from_TV
- byref_as_TU_from_TV
- equal_as_TU_from_TV
- function_equal_from_TV_to_TU
- return_from_TV_to_TU

I think the priority logic for choosing which constructors/operators to use must not take into account the passing/returning modes (byval or byref) of those constructors/operators themselves, but only their existences.
(it would be enormously complicating the logic with a lot of conflicts to solve, for probably not bringing much more in the end)
fxm
Moderator
Posts: 11557
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: Dec 29, 2022 15:26 Referring to just above:
- Change A ('Byval As u_type'): OK to swap the first and second priorities.
- Change B ('u = v' and 'Function = v'): OK to swap the third and forth priorities, because an explicit copy-let operator (u type) is mandatory for the forth priority whereas it is not the case for the third priority.
Last fbc build from SARG (with the 'fbc: passing byval constructor preference' change).

Thanks, and OK for the change A (with 'byref_as_TU_from_TV' case not modified).
Do you plan to apply the change B as well ?
coderJeff
Site Admin
Posts: 4081
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

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

Post by coderJeff »

fxm wrote: Dec 29, 2022 20:26 Thanks, and OK for the change A (with 'byref_as_TU_from_TV' case not modified).
Do you plan to apply the change B as well ?
I don't plan to add change B at this time. It was an accidental discovery that looked like it might be an improvement. But after our discussion here it doesn't seem correct to add. I would need the goal to be defined well before attempting another change, for example with 'function = v'.

For now, I think it prudent to work with what we have before going further.
fxm
Moderator
Posts: 11557
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

coderJeff wrote: Dec 29, 2022 21:30 For now, I think it prudent to work with what we have before going further.
OK.

I updated the 'Conversions using User Data Type constructors and operators' paragraph to Rev A:
- all priorities described below have been checked using my modified second version of the test program: viewtopic.php?p=296154#p296154,
- and with the last fbc build from SARG (with the 'fbc: passing byval constructor preference' change).
  • .....
Conversions using User Data Type constructors and operators - Rev A (added, removed)
  • 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 searches by priority:
    • - 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 searches by priority:
    • - Firstly a matched cast operator (for v type to u type).
      - Secondly a matched constructor (for u type from v type).

      - Firstly a matched constructor (for u type from v type).
      - Secondly a matched cast operator (for v type to u 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 reference-passing ('Byref As u_type') when passing a v type parameter, the compiler searches by priority:
    • - 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 an implicit reference-passing)

    For an implicit assignment ('u = v'), or an implicit return from function by assigning ('Function = v') with function returning u type, the compiler searches by priority:
    • - 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 searches by priority:
    • - 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

    Note:
    Only the member procedures directly impacted in the conversion process itself are cited above:
    - the copy-constructor (u type) and the copy-let operator (u type) are not cited when only their implicit definition is sufficient and not their explicit definition,
    - the default constructor (u type) is not cited whereas an implicit version, otherwise explicit version if another explicit constructor (u type) is defined, is always required in the 'Function = v' case, but not for the conversion process itself.
.....

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

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

Post by fxm »

coderJeff wrote: Dec 29, 2022 21:30 I don't plan to add change B at this time. It was an accidental discovery that looked like it might be an improvement. But after our discussion here it doesn't seem correct to add.
You are right.
It is indeed more logical for an assignment to leave in last priority the only combination that uses a constructor !
coderJeff
Site Admin
Posts: 4081
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

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

Post by coderJeff »

quite often, I find it worthwhile to go through old bugs and see if anything is different.

With our recent efforts,
#830 Byval placed before a passed variable for a Byval parameter induces an incomplete copy construction

now throws a compile error. So I will probably take a look at that for a bit.
fxm
Moderator
Posts: 11557
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

@Jeff,

In my second version of the test program, the shared variable 'w1' is unused, so I suppressed it.

Therefore, same thing to do in your 'tests/structs/udt-init-ops-2.bas' file:
.....
dim shared as TW w0 , w1
.....
If (@This <> @u0) And (@This <> @w0) AND (@This <> @w1) Then
.....
fxm
Moderator
Posts: 11557
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

@Jeff,

After running all my tests after the last commit below:
fbc: internal: symbFind*() API
- fix regression caused by commit e1068f1
- discussion: viewtopic.php?t=32015
- options were incorrectly merged when passed to symbFindClosestOvlProc()
and only FB_SYMBLOOKUPOPT_NO_CTOR should have been passed.
- by merging options from the caller, finding a matching overload was too
restrictive
- tests added

1)
The regression for the '<>' operator (see viewtopic.php?t=32015) is well fixed now.

2)
But I find now a small (second-order) change for the implicit copy-construction ('Byval As u_type') expression when passing a v type parameter (about priority order between the different conversions available):
- the priorities 2 and 3 are now swapped for 'Byval As u_type', but i think this is rather a small improvement because this order becomes symmetric with respect to the other 3 expressions where these two priorities are also consecutive:
  • .....
Conversions using User Data Type constructors and operators - Rev B (added, removed, highlighted)
  • 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 searches by priority:
    • - 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 searches by priority:
    • - Firstly a matched constructor (for u type from v type).
      - Secondly a matched cast operator (for v type to u type).
      - Thirdly finally a cast operator (for v type to special type (*)) and its matching conversion-constructor (for u type from special 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 reference-passing ('Byref As u_type') when passing a v type parameter, the compiler searches by priority:
    • - 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 an implicit reference-passing)

    For an implicit assignment ('u = v'), or an implicit return from function by assigning ('Function = v') with function returning u type, the compiler searches by priority:
    • - 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 searches by priority:
    • - 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

    Note:
    Only the member procedures directly impacted in the conversion process itself are cited above:
    - the copy-constructor (u type) and the copy-let operator (u type) are not cited when only their implicit definition is sufficient and not their explicit definition,
    - the default constructor (u type) is not cited whereas an implicit version, otherwise explicit version if another explicit constructor (u type) is defined, is always required in the 'Function = v' case, but not for the conversion process itself.
.....


My advice: do nothing.
Post Reply