Newsgroup: it.comp.lang.delphi
Titolo: Sono quasi impazzito. E voi come ve la caverete?

Chiedo scusa a tutti anticipatamente.
Sto per formularvi un questio che mi ha tenuto incollato per circa 1 ora
prima di arrivare ad una
"soluzione plausibile".
Data la seguente funzione (testata e "funzionante"; scusate il gioco di
parole :) ):
function RTTIElencaInsieme(Info:PTypeInfo;Insieme:TIntegerSet):string;
var
    i                       : integer;
    ptd                     : PTypeData;
begin
    Result:='';
    for i := 0 to SizeOf(Integer) * 8 - 1 do
        if i in Insieme then
        begin
            if Result <> '' then
                Result := Result + ',';
            ptd:=GetTypeData(Info);
          Result := Result + GetEnumName(ptd^.CompType^, I);
        end;
end;
Considerando una unit avente definiti i segg. tipi:
  TTMResultCode = (
                   cRC_OK,
                   cRC_NonCodificato,
                   cRC_KernelList_NonIstanziata,
                   cRC_KernelList_Vuota,
                   cRC_KernelList_IDUnita_Vuoto,
                   cRC_KernelList_IntervalloTemporale_Errato,
                   cRC_KernelList_IDUnita_Duplicato,
                   cRC_KernelList_IDUnita_Inesistente,
                   cRC_KernelList_Thread_NonAggiunto,
                   cRC_KernelList_Thread_NonIstanziato,
                   cRC_KernelList_Thread_ImpossibileModificareStato,
                   cRC_KernelList_InfoThread_NonIstanziato,
                   cRC_KernelList_Plugin_NonDefinito,
                   cRC_KernelThread_ListaDump_NonIstanziata,
                   cRC_UnitaElaborativa_Inizializzazione_Ok,
                   cRC_UnitaElaborativa_Inizializzazione_Fallita,
                   cRC_UnitaElaborativa_Inizializzazione_MancaPlugin,
cRC_UnitaElaborativa_Inizializzazione_Plugin_DescriviUnita_Mancante,
cRC_UnitaElaborativa_Inizializzazione_Plugin_DescriviUnita_Fallita,
                   cRC_END_PAD
                  );
  TTMResultCodes = set of TTMResultCode;
  TProva = (
                    clGnocco,
                    clPizza,
                    clGatto
                  );
    TProve = set of TProva;
Posto che in un'altra unit abbiate un codice del tipo:
procedure TForm1.Button1Click(Sender: TObject);
var
    classe  : TTMResultCodes;
    classe2 : TProve;
begin
(A)
ShowMessage(RTTIElencaInsieme(TypeInfo(TProve),TIntegerSet(Classe2)));
(B)
ShowMessage(RTTIElencaInsieme(TypeInfo(TTMResultCodes),TIntegerSet(Classe)))
;
end;
Chi mi sa spiegare perchè la riga marcata con (A) genera un errore di
"Invalid TypeCast" mentre, quella
marcata con (B), funziona perfettamente???
Io, come già detto, credo di esserci arrivato e penso sia anche "logica"
come risposta.
Tuttavia, ho bisogno di un vostro sforzo per capire se sono sull'orlo della
follia, oppure sono
troppo ignorante per non aver considerato alcune cosette :) (Lo so, sono
criptico, scusate)
Nel "P.S." aggiungo la soluzione a cui sono arrivato.
Saluti,
L'Enigmista...ehm...Carmine
P.S.:
Probabilmente si tratta di una questione di ottimizzazione, messa in pratica
dal compilatore Delphi.
In effetti, il Tipo TProve ci sta abbondandemente ad essere codificato con
un solo byte e, quindi,
genera l'"Invalid TypeCast" quando ho usato TIntegerSet.
Sull'altro fronte, invece, abbiamo TTMResultCodes che ha bisogno di più di
un byte per
poter essere descritto come tipo. In questo caso, sarebbe assicurata la
"compatibilità" con TIntegerSet.
Se è così che funzionano le cose, mi domando: "Cosa accadrebbe se, per
descrivere il tipo occorresse
qualcosa di più grande di TIntegerSet? Si ripresenterebbe dinuovo l'"Invalid
TypeCast"?"
Se ho detto min.iate chiedo venia. Sarà intossicazione da cibi natalizi. :)

 ha scritto nel
messaggio news:9mFP9.61020$Ou4.1...@twister2.libero.it...

La spiegazione te la sei data da solo :)
Prova con questo codice e vedrai che tutto funziona:
uses TypInfo;
type

cRC_UnitaElaborativa_Inizializzazione_Plugin_DescriviUnita_Mancante,
cRC_UnitaElaborativa_Inizializzazione_Plugin_DescriviUnita_Fallita,
                   cRC_END_PAD
                  );


  TMaxSet = set of 0..32 * 8 - 1;
  PMaxSet=^TMaxSet;
function RTTIElencaInsieme(Info:PTypeInfo; Insieme:PMaxSet;
Size:longint):string;
var
    i                       : integer;
    ptd                     : PTypeData;
begin
    Result:='';
    for i := 0 to Size * 8 - 1 do
        if i in Insieme^ then
        begin
            if Result <> '' then
                Result := Result + ',';
            ptd:=GetTypeData(Info);
          Result := Result + GetEnumName(ptd^.CompType^, I);
        end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
    classe  : TTMResultCodes;
    classe2 : TProve;
begin
//(A)
classe:=[                   cRC_OK,
                   cRC_NonCodificato,
                   cRC_KernelList_NonIstanziata,
                   cRC_KernelList_Vuota,
                   cRC_KernelList_IDUnita_Vuoto,
                   cRC_KernelList_IntervalloTemporale_Errato,
                   cRC_KernelList_IDUnita_Duplicato,
                   cRC_KernelList_IDUnita_Inesistente,
                   cRC_KernelList_Thread_NonAggiunto,
                   cRC_KernelList_Thread_NonIstanziato,
                   cRC_KernelList_Thread_ImpossibileModificareStato,
                   cRC_KernelList_InfoThread_NonIstanziato,
                   cRC_KernelList_Plugin_NonDefinito,
                   cRC_KernelThread_ListaDump_NonIstanziata,
                   cRC_UnitaElaborativa_Inizializzazione_Ok,
                   cRC_UnitaElaborativa_Inizializzazione_Fallita,
                   cRC_UnitaElaborativa_Inizializzazione_MancaPlugin,
cRC_UnitaElaborativa_Inizializzazione_Plugin_DescriviUnita_Mancante,
cRC_UnitaElaborativa_Inizializzazione_Plugin_DescriviUnita_Fallita,
                   cRC_END_PAD
   ];
Classe2:=[clGnocco,clPizza,clGatto];
ShowMessage(RTTIElencaInsieme(TypeInfo(TProve),Addr(Classe2),SizeOf(Classe2)
));
//(B)
ShowMessage(RTTIElencaInsieme(TypeInfo(TTMResultCodes),Addr(Classe),SizeOf(C
lasse)))
;
end;
Ciao Giorgio


Nel post precedente ho dichiarato TMaxSet come set di un array di 256 valori
che corrisponde al massimo amesso del compilatore per i tipi set, quindi non
può mai succedere di passargli un set più grande.
Ciao
Giorgio

 end;
Grazie 1000 per la risposta :)
Allora, io ho risolto diversamente ed in maniera molto meno elegante :)
function RTTIElencaInsieme(Info:PTypeInfo;Insieme:TInsieme):string;
al posto di:
function RTTIElencaInsieme(Info:PTypeInfo;Insieme:TIntegerSet):string;
dove TInsieme = set of byte;
Perň ho dovuto dichiarare tutti gli insiemi come TInsieme e, all'atto di
comporre l'insieme, ho
dovuto forzare tutti i valori con byte(...).
Es:
type
    TInsieme = set of byte;
var
    classe : TInsieme;
begin
    classe := [byte(cRC_OK)];
    ...
    ...
end;
Ovviamente, č una gra rottura di scatole dover mettere byte(...) quindi,
rimetto mano al codice ed utilizzo
la versione con i puntatori :)
Grazie ancora per l'interessamento.
Saluti,
Carmine


Praticamente come avevi accennato tu, il compilatore a seconda dell'elenco
dei valori del set alloca memoria in modo diverso, se l'elenco dei valori è
minore o uguale a 8 allocherà un byte, se sono sono tra 9 e 16 allocherà 2
byte e via dicendo, percui se tu dichiari la funzione con un set che occupa
4 byte non puoi passare un set che ne occupa di meno altrimenti i byte
restanti da dove se li tira fuori???
Viceversa se dichiari nella funzione un set con 1byte soltanto, quando passi
un set con + di un byte (e questo si può fare con il typecast credo) perdi
tutti i valori oltre l'ottavo e quindi la funzione non funzionerebbe bene.
Il metodo che ho usato io consiste nel passargli un puntatore al set e
dicendogli anche quanto è grande in modo che non si incasini quando
controlla tutti i valori per creare la stringa tramite la funzione iniziale
scritta da te.
Spero di essermi spiegato bene, ciao!

> Spero di essermi spiegato bene, ciao!
Decisamente bene :)
Grazie ancora