Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array typed parameter not accepted when overloading function

In Delphi, I can do this:

Type
  TFourCC = Array[0..3] of AnsiChar;

Function Func(Param : TFourCC) : Boolean;
begin
  { ... }
end;

Func('ABCD'); // I can pass this as literal text without problems

Now, I want to make this parameter optional.

Function Func(Param : TFourCC = 'ABCD') : Boolean;
begin
  { ... }
end;

Now, the compiler throws me an error: E2268 Parameters of this type cannot have default values

Ok, so I was thinking overloading the function should do the trick then...

Function Func : Boolean; overload;
begin
  { ... }
end;

Function Func(Param : TFourCC) : Boolean; overload;
begin
  { ... }
end;

Func('ABCD'); // This line that worked in first example now gives an error

Unfortunately, Delphi doesn't like this either. Where it first accepted the parameter as a TFourCC typed variable, it now gives me E2250 There is no overloaded version of 'Func' that can be called with these arguments.

I beg to disagree with what this error tells me, the same thing worked when it wasn't overloaded.

Can someone explain me the logic behind this, and possibly a solution? I'd like to keep the TFourCC as it is (not a string type), it keeps the handling of reading and writing much easier. I rather avoid assigning it to a variable first before passing it, because the function will be used alot..

like image 959
Pantalaimon Avatar asked Sep 13 '20 18:09

Pantalaimon


People also ask

Can a function accept an array as a parameter?

A whole array cannot be passed as an argument to a function in C++. You can, however, pass a pointer to an array without an index by specifying the array's name.

Which data type Cannot be overloaded?

2) Member function declarations with the same name and the name parameter-type-list cannot be overloaded if any of them is a static member function declaration.

What are the restrictions on overloading function?

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.

Why we Cannot overload function on the basis of return type?

The return type of a function has no effect on function overloading, therefore the same function signature with different return type will not be overloaded. Example: if there are two functions: int sum() and float sum(), these two will generate a compile-time error as function overloading is not possible here.


1 Answers

Unfortunately, this is how the type system currently works.

But the good news is that you can do magic with records and operator overloading. For instance, with

type
  TFourCC = record
  strict private
    function GetChar(Index: Integer): AnsiChar;
    procedure SetChar(Index: Integer; const Value: AnsiChar);
  public
    class operator Implicit(AValue: AnsiString): TFourCC;
    class operator Implicit(AValue: TFourCC): AnsiString;
    class operator Equal(a, b: TFourCC): Boolean;
    class operator NotEqual(a, b: TFourCC): Boolean;
    property Chars[Index: Integer]: AnsiChar read GetChar write SetChar; default;
  case Boolean of
    False: (AnsiChars: array[0..3] of AnsiChar);
    True: (Data: Cardinal)
  end;

implementation

{ TFourCC }

class operator TFourCC.Implicit(AValue: AnsiString): TFourCC;
begin
  if Length(AValue) <> 4 then
    raise Exception.Create('Not a valid TFourCC string.');
  Result.Data := PCardinal(@AValue[1])^;
end;

class operator TFourCC.Implicit(AValue: TFourCC): AnsiString;
begin
  SetLength(Result, 4);
  PCardinal(@Result[1])^ := AValue.Data;
end;

class operator TFourCC.Equal(a, b: TFourCC): Boolean;
begin
  Result := a.Data = b.Data;
end;

class operator TFourCC.NotEqual(a, b: TFourCC): Boolean;
begin
  Result := a.Data <> b.Data;
end;

function TFourCC.GetChar(Index: Integer): AnsiChar;
begin
  Result := AnsiChars[Index];
end;

procedure TFourCC.SetChar(Index: Integer; const Value: AnsiChar);
begin
  AnsiChars[Index] := Value;
end;

you get all these benefits:

procedure TForm1.FormCreate(Sender: TObject);
var
  x: TFourCC;
begin
  x := 'FINE';                     // implicit conversion from string
  ShowMessage(x);                  // implicit conversion to string
  x[0] := 'D';                     // can access parts for writing (without explicit member)
  ShowMessage(x);
  ShowMessage(x[0]);               // can access parts for reading (without explicit member)
  ShowMessage(x.Data.ToString);    // can access underlying storage as a 32-bit integer
end;

And, you can now do

procedure f(A: TFourCC); overload;
begin
  ShowMessage(A);
end;

procedure f; overload;
begin
  ShowMessage('ABCD');
end;

Unfortunately, I am very much in a hurry right now, so I cannot double-check the correctness or comment further right now!

like image 126
Andreas Rejbrand Avatar answered Nov 14 '22 22:11

Andreas Rejbrand