type
TForm72 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TTestForm = class(TForm)
public
constructor CreateTest(AOwner: TComponent); virtual;
end;
TTestForm1 = class(TTestForm)
public
constructor CreateTest(AOwner: TComponent); override;
end;
TTest<T: TTestForm, constructor> = class(TObject)
public
class procedure Test;
end;
var
Form72: TForm72;
implementation
{$R *.dfm}
procedure TForm72.FormCreate(Sender: TObject);
begin
TTest<TTestForm1>.Test;
end;
{ TTest<T> }
class procedure TTest<T>.Test;
var
F: T;
begin
F := T.CreateTest(Application);
Form72.Caption := F.Name;
end;
{ TTestForm }
constructor TTestForm.CreateTest(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
{ TTestForm1 }
constructor TTestForm1.CreateTest(AOwner: TComponent);
begin
inherited;
Caption := 'Bang';
end;
end.
This code compiled in XE2, but fail with “[dcc32 Error] Unit71.pas(55): E2010 Incompatible types: ‘T’ and ‘procedure, untyped pointer or untyped parameter'” in XE3. What I did wrong, or compiler did wrong?
In fact this code highlights a compiler bug in XE2. In XE2, the code compiles when it should not. Remove the
constructorconstraint and the compilation fails withBut the
constructorconstraint merely states that the class has a parameterless constructor. The documentation states:The fact that the presence or otherwise of the
constructorconstraint influences this code indicates that the XE2 compiler has a fault.In XE3 the code correctly fails to compile. The only way to call a constructor with the syntax
T.Createis if you are using aconstructorconstraint and are calling a parameterless constructor. That is not the case here and so XE3 correctly reports a compilation error.You need some casting to make it compile.
This is a well-known trick to get around some of the quirks of the Delphi generics implementation’s handling of constructors. Although it looks messy, I believe that this code is what the language designers intended us to use. In my opinion, the change in behaviour is due to a bug fix and XE3 is behaving as designed.