2009-08-06 3 views
2

Tenir compte:"" opérateur pour les types génériques contraintes

TTest <T : class, constructor> = class 
public 
    function CreateMyObject : T; 
end; 
function TTest<T>.CreateMyObject : T; 
var 
    Obj : TObject; 
begin 
    Obj := T.Create; 
    Result := (Obj as T); 
end; 

Pourquoi est-ce pas possible? Le compilateur génère un message d'erreur "Opérateur non applicable à ce type" pour l'opérateur en tant qu'opérateur. T est contraint à être un type de classe, donc cela devrait fonctionner, n'est-ce pas?

Merci pour l'aide.

+0

Est-ce que le résultat: = T (Obj) fonctionne? –

+0

Non. Ce serait un transtypage invalide. – jpfollenius

Répondre

2

je suis tombé sur le même problème et résolu en ajoutant une méthode pointeur copie de bas niveau à la classe comme une solution de contournement:

TTest <T : class, constructor> = class 
    private 
    function _ToGeneric(AItem: TObject): T; inline; //inline, so it's a little faster 
    public 
    function CreateMyObject : T; 
    end; 

    function TTest<T>.CreateMyObject : T; 
    var 
    Obj : TObject; 
    begin 
    Obj := T.Create; 
    Result := _ToGeneric(Obj); 
    end; 

    function TTest<T>._ToGeneric(AItem: TObject): T; 
    begin 
    System.Move(AItem,Result,SizeOf(AItem)) 
    end; 
+0

+1 Cela semble fonctionner! Belle solution de contournement. J'espère que ça va se réparer bientôt. – jpfollenius

0

Je ne sais pas pourquoi cela ne fonctionne pas. Je suppose qu'il y a encore quelques bizarreries/bugs dans l'implémentation des génériques.

Mais le code suivant fonctionne:

// Class definition 
function CreateMyObject<T : class, constructor> : T; 


// Class implementation 
function TForm1.CreateMyObject<T>: T; 
var 
    Obj : T; 
begin 
    Obj := T.Create; 
end; 
+0

Oui, cela fonctionne mais malheureusement je ne peux créer qu'un TObject, puisque j'utilise TClass.Create pour créer l'objet. C'est pour une classe d'usine (voir mes autres questions récentes) – jpfollenius

+0

Pourquoi n'utilisez-vous pas un ancêtre commun avec un constructeur virtuel? Yo peut créer une classe de type et l'utiliser (et pas TClass)? –

+0

Pouvez-vous s'il vous plaît expliquer plus en détail? Si je comprends bien cela n'aide pas car je veux que la valeur de retour soit de type T et non de type TCommonAncestor. – jpfollenius

1

C'est a known issue avec le compilateur Delphi. Veuillez voter pour cela si vous souhaitez le voir corrigé. En attendant, vous pouvez travailler autour d'elle en disant

Result := (Obj as TClass(T)); 
+0

Salut Mason! Merci pour l'indice. Malheureusement, votre solution de contournement ne compile pas pour moi ("'(' attendu ')' trouvé ') – jpfollenius

+0

Ack! Si cela ne fonctionne pas pour votre version, alors la réponse de MvdH pourrait être la seule façon de le faire. –