The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,483 other followers

Delphi and generics: some examples of “E2015: Operator not applicable to this operand type”

Posted by jpluimers on 2019/12/24

I don’t have enough time right now to elaborate on the code, so below is a an example of where I bumped into the very non-descriptive [WayBack/Archive.is] E2015: Operator not applicable to this operand type when using generics in Delphi.

Most have to do with comparing types (one of which is similar to comparing interfaces where you need to have a GUID in order to get an as comparison working, see Source: Delphi – Using FastMM4 part 2: TDataModule descendants exposing interfaces, or the introduction of a TInterfacedDataModule).

Like most post-Delphi 2007 language features in Delphi, generics still have rough edges. I doubt this will change anytime soon and I am not alone in this.

The documentation never got update to cover situations involving generics ([Archive.is] E2015 Operator not applicable to this operand type (Delphi) – RAD Studio), so basically this to show some examples you might bump into as well.

Note the code below usually is an indication of code-smell, as was the more elaborate situation I had to use it in. A long term solution for that code was to introduce more polymorphism.

A shorter term solution involves either the use of local variables or type-casting (for the latter, see [WayBack] delphi – Cannot compile constrained generic method – Stack Overflow)

–jeroen

program E2015WithGenerics;
uses
System.SysUtils;
{$APPTYPE CONSOLE}
{$R *.res}
type
TMyAncestor = class
end;
TMyClass = class(TMyAncestor)
strict protected
function GetClassInstance<T: class>: T;
function GetTMyAncestorInstance<T: TMyAncestor>: T;
// function GetTMyClassInstance<T: TMyClass>: T; // [dcc32 Error] E2086 Type 'TMyClass' is not yet completely defined
end;
function TMyClass.GetClassInstance<T>: T;
var
lClassType: TClass;
begin
lClassType := T;
if lClassType = TMyClass then
begin
Result := T(Self)
end
else if T = TMyClass then
begin
Result := T(Self)
end
// else if lClassType is TMyClass then // [dcc32 Error] E2015 Operator not applicable to this operand type
// begin
// Result := T(Self)
// end
// else if T is TMyClass then // [dcc32 Error] E2015 Operator not applicable to this operand type
// begin
// Result := T(Self)
// end
else if lClassType.InheritsFrom(TMyClass) then
begin
Result := T(Self)
end
else if T.InheritsFrom(TMyClass) then
begin
Result := T(Self)
end
else
begin
raise ENotSupportedException.CreateFmt('GetClassInstance fails for class %s', [lClassType.ClassName]);
end;
end;
function TMyClass.GetTMyAncestorInstance<T>: T;
var
lClassType: TClass;
begin
lClassType := T;
if lClassType = TMyClass then
begin
Result := T(Self)
end
// else if T = TMyClass then // [dcc32 Error] E2015 Operator not applicable to this operand type
// begin
// Result := T(Self)
// end
// else if lClassType is TMyClass then // [dcc32 Error] E2015 Operator not applicable to this operand type
// begin
// Result := T(Self)
// end
// else if T is TMyClass then // [dcc32 Error] E2015 Operator not applicable to this operand type
// begin
// Result := T(Self)
// end
else if lClassType.InheritsFrom(TMyClass) then
begin
Result := T(Self)
end
else if T.InheritsFrom(TMyClass) then
begin
Result := T(Self)
end
else
begin
raise ENotSupportedException.CreateFmt('GetTMyAncestorInstance fails for class %s', [lClassType.ClassName]);
end;
end;
//function TMyClass.GetTMyClassInstance<T>: T;
//begin
////…
//end;
begin
end.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: