Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: OleVariant and Generics

Consider the following code extract:

type
  MyIntf = interface
    procedure Work(param: OleVariant);
  end;

  MyClass<T> = class
    procedure MyWork(param: T);
  end;

var
  intf: MyIntf;

procedure MyClass<T>.MyWork(param: T);
begin
  //compiler error: E2010 Incompatible types: 'OleVariant' and 'T'
  intf.Work(param);
end;

This fails to compile with the error message as indicated above. How could I call the Work function from my generic class?

like image 525
TmTron Avatar asked Feb 27 '13 13:02

TmTron


1 Answers

Your code fails to compile because the compiler cannot guarantee at compile time of the generic class that there is a possible conversion to all conceivable T.

When faced with

intf.Work(param);

in the generic method the compiler needs to know how to convert param to OleVariant. And it cannot do so. This is one of the limitations of generics in comparison with templates.


The easiest solution for you is to do the conversion at runtime with help from TValue from the Rtti unit.

procedure MyClass<T>.MyWork(param: T);
begin
  intf.Work(TValue.From<T>(param).AsVariant);
end;

And here's a sample test program to demonstrate that TValue does the job:

program SO15113162;
{$APPTYPE CONSOLE}

uses
  Rtti;

procedure Work(param: OleVariant);
begin
  Writeln(param);
end;

type
  MyClass<T> = class
    class procedure MyWork(param: T);
  end;

class procedure MyClass<T>.MyWork(param: T);
begin
  Work(TValue.From<T>(param).AsVariant);
end;

begin
  MyClass<Double>.MyWork(2.4);
  MyClass<string>.MyWork('hello');
  MyClass<Integer>.MyWork(-666);
  Readln;
end.

Output

2.4
hello
-666
like image 86
David Heffernan Avatar answered Oct 12 '22 23:10

David Heffernan