Wodzu
Wodzu

Reputation: 6979

Converting value of type <T> into Variant, is it possible?

here is a snippet showing what I am trying to achieve:

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
var
  TmpValue: Variant;
begin
  TmpValue := Variant(Value); //Invalid typecast
  Result := VarType(TmpValue);
end;

I know that above apporach with typecast is naive but I hope you get the idea. I would like to replace it with some conversion mechanism.

TMyObject will be always of simple type like Integer, String, Single, Double.

The purpose of such conversion is that function VarType gives me integer constant for each simple type which I can store somewhere else.

I would like to know if such conversion is possible?

Thanks for your time.

Upvotes: 6

Views: 4242

Answers (4)

gabr
gabr

Reputation: 26830

It's trivially solvable in Delphis with enhanced RTTI (2010 and newer). Too bad you're limited to 2009 :(

function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Result := VarType(TValue.From<T>(Value).AsVariant);
end;

This works only for simple types but that was a constraint specified in the question.

Upvotes: 7

Wodzu
Wodzu

Reputation: 6979

Thanks guys for your answers:

As @RRUZ have shown it is possible (I mean not strict assigment but extracting the type of data). I was working on my own while waiting for any answer and have found a more generic solution.

So I am positing it here:

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Result := GetTypeData(TypeInfo(T)).varType;
end;

Once again thanks!

Upvotes: 1

RRUZ
RRUZ

Reputation: 136391

You can use the RTTI to get this info, just check the value of the TTypeInfo.Kind property:

Check this sample code

{$APPTYPE CONSOLE}

uses
  TypInfo,
  Variants,
  Generics.Collections,
  SysUtils;

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Case PTypeInfo(TypeInfo(T))^.Kind of
    tkInteger : Result:=varInteger;
    tkFloat   : Result:=varDouble;
    tkString  : Result:=varString;
    tkUString : Result:=varUString;
    //add more types here
  End;
end;

Var
  LObj : TMyObject<Integer>;
begin
  try
     Writeln(VarTypeAsText(TMyObject<Integer>.Create.GetVarType(5)));
     Writeln(VarTypeAsText(TMyObject<String>.Create.GetVarType('Test')));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

this will return

Integer
UnicodeString

Upvotes: 6

David Heffernan
David Heffernan

Reputation: 612954

I can't see how it could be possible to do this with generics. The compiler needs to know that an instance of type T can be assigned to a Variant for any possible T. There's no way for you to tell that compiler that is possible.

If this were templates as in C++ then it would be trivial.

Upvotes: 1

Related Questions