Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with overloaded functions that have ambiguous parameters

Take this small example class (not my real code, but it exposes the problem):

Convert = class(TObject)
  public
    class function ToString(value: Double): String; overload;
    class function ToString(value: TDateTime): String; overload;
  end;

It compiles fine until you try to use the Double or TDateTime functions As In:

var
  d: Double;
begin
  d := 99.99;
  ShowMessage(Convert.ToString(d));

You will get this compile error: Ambiguous overloaded call to 'ToString'. The problem boils down to the fact that TDateTime is a type of Double

My Question: how do You deal with this type of problem?

EDIT - I am NOT looking for a solution for the example given

I have found 3 Solutions so far:

  • Rename one of the 2 functions
  • Add a "Dummy" parameter to one of the 2 functions
  • Change the parameters to Var types, this has the disadvantage that I can no longer call this function with constants

are there any other solutions out there?

like image 331
whosrdaddy Avatar asked Jan 05 '13 07:01

whosrdaddy


People also ask

How do you fix an ambiguous call to overloaded function?

There are two ways to resolve this ambiguity: Typecast char to float. Remove either one of the ambiguity generating functions float or double and add overloaded function with an int type parameter.

Can a call to an overloaded function be ambiguous options the?

Answer: If two or more functions have the same name and function signature, the call to an overloaded function can be unclear. Explanation: Function overloading ambiguity occurs when the compiler is unable to decide which of the overloaded functions should be invoked first.

What is ambiguity in function overloading?

When the compiler is unable to decide which function it should invoke first among the overloaded functions, this situation is known as function overloading ambiguity. The compiler does not run the program if it shows ambiguity error.

What are the restrictions on overloaded functions?

Restrictions on overloadingAny two functions in a set of overloaded functions must have different argument lists. Overloading functions that have argument lists of the same types, based on return type alone, is an error.


2 Answers

Overloaded methods can be very effective. However, as soon as there is a hint of ambiguity they become a liability. A good example of this are the new TStream overloads introduced in XE3. It's not hard to fall into a trap where the compiler chooses an overload that you weren't expecting. At least in your code the compiler stopped. In that sense you were lucky.

So my advice, in your situation, is to abandon overloads. Express the different input types in the method name. Yes it's a little more verbose, but you won't make any mistakes, and you code will compile!

like image 122
David Heffernan Avatar answered Oct 25 '22 19:10

David Heffernan


Your posted example compiles and executes fine in XE.

In a comment you give this example instead:

ShowMessage( Convert.ToString( 99.99 ));  // <- gives compiler error 2251

In this particular case the solution is to explicitly define the type( I thought):

ShowMessage( Convert.ToString( Double(99.99) )); // <- E2089, Invalid Typecast

Looking into the documentation:

This error message is issued for type casts not allowed by the rules. The following kinds of casts are allowed:

  • Ordinal or pointer type to another ordinal or pointer type
  • A character, string, array of character or pchar to a string
  • An ordinal, real, string or variant to a variant
  • A variant to an ordinal, real, string or variant
  • A variable reference to any type of the same size.

So, to explicitly tell the compiler to select the Double overloaded function:

ShowMessage( Convert.ToString( Double(Variant(99.99)))); // Ok

A bit convoluted perhaps. But for the other overloaded function it is simpler:

ShowMessage( Convert.ToString( EncodeDate(2013,1,5));

Update


To make this a generic solution working for all classes, consider adding class functions to resolve your ambiguous types.

Convert = Class(TObject)
  ...
  class function AsDouble( value: Double) : Double; inline; static;
  class function AsTDateTime( value: TDateTime) : TDateTime; inline; static;
end;

class function Convert.AsDouble(value: Double): Double;
begin
  Result := Value;
end;
class function Convert.AsDateTime(value: TDateTime): TDateTime;
begin
  Result := Value;
end;

Now you can call your overloaded class function with constants:

ShowMessage( Convert.ToString( Convert.AsDouble(99.99)));   
like image 33
LU RD Avatar answered Oct 25 '22 18:10

LU RD