Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
963 views
in Technique[技术] by (71.8m points)

delphi - Use of Supports() function with generic interface type

I just tried my first use of generics in Delphi 2009 and am perplexed on how to use a generic type as the input to the Supports function used to see if an object implements a given interface. I've created a small sample illustrating the problem.

Given the following types and utility function:

IMyInterface = interface
['{60F37191-5B95-45BC-8C14-76633826889E}']
end;

TMyObject = class(TInterfacedObject, IMyInterface)
end;

class function TFunctions.GetInterface<T>(myObject: TObject): T;
var
  specificInterface: T;
begin
  // This would compile, but looses the generic capability
  //Supports(myObject, IMyInterface, specificInterface);

  // This results in compile errors
  Supports(myObject, T, specificInterface);

  result := specificInterface;
end;

and the following code snippet:

class procedure TFunctions.Test;
var
  myObject: TMyObject;
  myInterface: IMyInterface;
begin
  myObject := TMyObject.Create;

  myInterface := GetInterface<IMyInterface>(myObject);
end;

I would expect no problems but I get the following compile time errors:

[DCC Error] GenericExample.pas(37): E2029 '(' expected but ',' found [DCC Error] GenericExample.pas(37): E2014 Statement expected, but expression of type 'T' found

I'm not sure what the compiler is expecting me to do with the T when used as the actual argument to the function.

I've searched around quite a bit and haven't been able to crack this one. A part of me suspects that if I could understand how an interface name gets converted to the IID: TGUID type during compilation, when using a concrete interface name, I could make some headway, but that has evaded me also.

Any help is much appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There is no guarantee that T has a GUID associated with it, and there is no means in the language to write a constraint on the type parameter to make that guarantee.

The interface name is converted into a GUID by the compiler looking up the name in the symbol table, getting the compiler's data structure representing the interface, and checking the corresponding field for the GUID. But generics are not like C++ templates; they need to be compiled and type-checked and known to work for any valid type parameter, and that means constraining the type parameter in its declaration.

You can get the GUID using RTTI (first checking that T does indeed represent an interface) with something like GetTypeData(TypeInfo(T))^.Guid and pass the GUID to Supports that way.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...