UDT with Constructors and Cast - Ambigious Call

General FreeBASIC programming questions.
Post Reply
stephanbrunker
Posts: 62
Joined: Nov 02, 2013 14:57

UDT with Constructors and Cast - Ambigious Call

Post by stephanbrunker »

Hello,

I'm trying to write an UDT with a numeric member, which can be constructed from all FB datatypes and can be casted to all datatypes. But in this constellation, the compiler returns the error "Ambigious call to overloaded function" (datatype).constructor() in Return z (from any of the operators). In the smallest version possible, the code looks like:

Code: Select all

type murks
    s as integer
    Declare Constructor()
	Declare Constructor (ByRef a As Byte)
	Declare Constructor (ByRef a As Integer)
    declare operator cast() as byte      
end type

Constructor murks()
    This.s = 0
end Constructor

constructor murks(byref a as byte)
    this.s = a
End constructor

constructor murks(byref a as integer)
    this.s = a
End constructor

Operator + (ByRef x As murks, byref y as murks) As murks
    dim as murks z
    z.s = x.s + y.s
    Return z
End Operator

Operator murks.Cast() as byte
    Return Cast(byte,this.s)
End Operator
If you remove the Cast() or one of the Constructors, then the error evaporates, but then I couldn't assign or cast this datatype. And also, if the UDT member is a string instead of a numeric variable (that was the case in the Bigint UDT where all constructors and casts are defined). Am I missing something?

Regards,
Stephan

PS: If this issue is solved, the 128-bit datatype for 64-bit looks pretty good. The muliplication alone is 70x faster than the bigint implemenation.
RockTheSchock
Posts: 252
Joined: Mar 12, 2006 16:25

Re: UDT with Constructors and Cast - Ambigious Call

Post by RockTheSchock »

Maybe like this:

Code: Select all

Operator + (ByRef x As murks, byref y as murks) ByRef As murks
  Static z As murks
  z.s = x.s + y.s
  Return z
End Operator
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

Normally, RETURN (a copy) calls the copy constructor.
As no explicit copy constructor exists, and before do a shallow copy of fields, the compiler tries to do a conversion by using the constructors and cast operators explicitly defined.

For your full version (with many constructors and many cast operators), there will inevitably be ambiguity.
So I advise you to define a copy constructor:

Code: Select all

type murks
    s as integer
    Declare Constructor()
    Declare Constructor (Byref m As murks)
    Declare Constructor (ByRef a As Byte)
    Declare Constructor (ByRef a As Integer)
    declare operator cast() as byte      
end type

Constructor murks()
    This.s = 0
end Constructor

Constructor murks(Byref m As murks)
  This.s = m.s
End Constructor

constructor murks(byref a as byte)
    this.s = a
End constructor

constructor murks(byref a as integer)
    this.s = a
End constructor

Operator + (ByRef x As murks, byref y as murks) As murks
    dim as murks z
    z.s = x.s + y.s
    Return z
End Operator

Operator murks.Cast() as byte
    Return Cast(byte,this.s)
End Operator
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

dkl,

In the above shortened example of stephanbrunker (precisely with one cast operator and two constructors), I don't understand why there is ambiguity.
I expected that the compiler would execute this following conversion (which is not ambiguous):
''Return z
Return murks(Cast(byte, z))

The fact that compiler does not make this conversion not obvious, I could understand, but why this specific error message on the ambiguity!
Last edited by fxm on Jul 16, 2015 11:34, edited 1 time in total.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT with Constructors and Cast - Ambigious Call

Post by dodicat »

if you say operator=z, instead of return z it seems OK.
Although I admit, I am unsure of the exact mode of operation of RETURN in an operator.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

OPERATOR= (or FUNCTION=) calls the default constructor at the beginning of the operator code, then the let operator at OPERATOR=z.
As there is no explicit let operator, the compiler does a shallow copy of fields.

If you have to put some other special fields where a shallow copy is insufficient, then I advise you to also define a let operator. This let operator could be also called by the copy constructor:

Code: Select all

type murks
    s as integer
    Declare Constructor()
    Declare Operator Let (Byref m As murks)
    Declare Constructor (Byref m As murks)
    Declare Constructor (ByRef a As Byte)
    Declare Constructor (ByRef a As Integer)
    declare operator cast() as byte      
end type

Constructor murks()
    This.s = 0
end Constructor

Operator murks.Let(Byref m As murks)
  This.s = m.s
End Operator

Constructor murks(Byref m As murks)
  This = m
End Constructor

constructor murks(byref a as byte)
    this.s = a
End constructor

constructor murks(byref a as integer)
    this.s = a
End constructor

Operator + (ByRef x As murks, byref y as murks) As murks
    dim as murks z
    z.s = x.s + y.s
    Operator = z
End Operator

Operator murks.Cast() as byte
    Return Cast(byte,this.s)
End Operator
stephanbrunker
Posts: 62
Joined: Nov 02, 2013 14:57

Re: UDT with Constructors and Cast - Ambigious Call

Post by stephanbrunker »

Thank you so far. I intended to define a LET operator anyway (and did it in the extended example), but the Copy Constructor is new for me. Anything else I have to know?

As far as I know, I can't access the Cast Operator with the syntax Cast(Ulonglongint, "[any other format]") ?

Regards,
Stephan
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

stephanbrunker wrote:As far as I know, I can't access the Cast Operator with the syntax Cast(Ulonglongint, "[any other format]") ?
I suppose you think to Ulongint!
Can you provide a short example of the cast operator not working?
stephanbrunker
Posts: 62
Joined: Nov 02, 2013 14:57

Re: UDT with Constructors and Cast - Ambigious Call

Post by stephanbrunker »

The question is, if I have a datatype with all the Constructors and the Cast () as ... defined, can I access a function Cast([mydatatype],[any other]) ? Normally, if i have a "=" operation, with my datatype first, then the matching constructor is called and everything works fine. You can overload all operators for your datatype, except BitValue, BitSet and BitReset, because they are macros - says the manual:

Code: Select all

#DEFINE BITSET(x,y) ((x) OR (CAST(TYPEOF(x), 1) SHL (y)))
OR is defined, SHL is defined, but I can't get that working. The Error is "Type mismatch, before ')' in 'bitset(a,1)' - and I presume it is based on the CAST.

I've two datatypes in mind: The Bigint (based on Richards work) and a Ulonglongint / Longlongint as 128-bit datatype for 64-bit systems. The first one is already stable, the second one I'm writing at the moment. And of course, you can get them if you want to distribute them with FB.

Is the CAST with two arguments a separate function? And can be overloaded? For example, if I want in the bigint case:

Code: Select all

dim a as bigint = Cast(bigint,2)^1024
I get the same type mismatch error.
As workaround I've defined a function CBig() and overloaded, so in that case Cbig(2)^1024 works, but the alternate spelling doesn't.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

With CAST, you can never convert a predefined type (like numerics) to an user defined type (UDT), even by overloading the cast operator in the UDT.
Overloading the cast operator in the UDT allows to only convert an UDT instance to an another type (predefined or other UDT).

If you want to convert a predefined type (like numerics) to an user defined type (UDT), you must defined a matching constructor in the UDT.

Example of possible syntaxes with your above murks Type:

Code: Select all

Dim As murks x = murks(5)
Dim As Integer y = 3

#define sumInt(x, y) Cast(Typeof(y), x) + y
Print sumInt(x, y)

#define sumMurks(x, y) Type<murks>(y) + x  '' or #define sumMurks(x, y) murks(y) + x
Print Cast(Byte, sumMurks(y, x))
Last edited by fxm on Jul 16, 2015 6:07, edited 4 times in total.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

stephanbrunker wrote:Is the CAST with two arguments a separate function? And can be overloaded? For example, if I want in the bigint case:

Code: Select all

dim a as bigint = Cast(bigint,2)^1024
I get the same type mismatch error.
If the bigint Type has a matching constructor plus a '^' overload operator, you can code:
dim a as bigint = bigint(2)^1024 '' or dim a as bigint = Type<bigint>(2)^1024
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT with Constructors and Cast - Ambigious Call

Post by fxm »

fxm wrote:Example of possible syntaxes with your above murks Type:

Code: Select all

Dim As murks x = murks(5)
Dim As Integer y = 3

#define sumInt(x, y) Cast(Typeof(y), x) + y
Print sumInt(x, y)

#define sumMurks(x, y) Type<murks>(y) + x  '' or #define sumMurks(x, y) murks(y) + x
Print Cast(Byte, sumMurks(y, x))
Even better, by using a "dynamic" temporary type (always with your above murks Type):

Code: Select all

Dim As murks m = murks(8)
Dim As Integer i = 5

#define sumOnTypeY(X, Y) Type<Typeof(Y)>(X) + Y
Print sumOnTypeY(m, i)
Print Cast(Byte, sumOnTypeY(i, m))
Post Reply