Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How compatible are static class methods and regular routine pointers?

It seems to me that static class methods and regular routine pointers are compatible from a practical viewpoint but the compiler doesn't know this. Example:

type
  TFunc = function(i: Integer): string;

  TMyClass = class
  public
    class function StaticMethod(i: Integer): string; static;
  end;

class function TMyClass.StaticMethod(i: Integer): string;
begin
  Result := '>' + IntToStr(i) + '<';
end;

function GlobalFunc(i: Integer): string;
begin
  Result := '{' + IntToStr(i) + '}';
end;

procedure CallIt(func: TFunc);
begin
  Writeln(func(42));
end;

begin
  CallIt(TMyClass.StaticMethod); //       1a: doesn't compile
  CallIt(GlobalFunc); //                  1b: compiles

  CallIt(@TMyClass.StaticMethod); //      2a: compiles iff $TYPEDADDRESS OFF
  CallIt(@GlobalFunc); //                 2b: compiles iff $TYPEDADDRESS OFF

  CallIt(Addr(TMyClass.StaticMethod)); // 3a: compiles
  CallIt(Addr(GlobalFunc)); //            3b: compiles

  Readln;
end.

As noted in the comments, 3a and 3b both compile (where compiles includes works at runtime in this simple example). 2a and 2b both compile if and only if $TYPEDADDRESS is OFF. But 1a/1b are different: 1b always compiles while 1a never compiles. Is this distinction by design? Is using 3a save or have I overlooked any pitfalls?

like image 701
Uli Gerhardt Avatar asked Aug 25 '26 18:08

Uli Gerhardt


1 Answers

There is no difference on binary level between static class function and ordinary function with the same arguments&result type - they are binary compatible, so your example is OK. Of course they are different types for the compiler, so you need Addr() or @ to compile your example.

Addr() is equivalent to the @ operator except that it is unaffected by the $T compiler directive.If you switch type check on your example will not compile:

{$T+}
begin
  CallIt(@TMyClass.StaticMethod);
  Readln;
end.

[Pascal Error] Project10.dpr(28): E2010 Incompatible types: 'TFunc' and 'Pointer'

like image 147
kludg Avatar answered Aug 27 '26 17:08

kludg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!