PDA

Visualizza la versione completa : [c++ stl]estrazione tipi da container


giuseppe500
25-08-2010, 12:03
ciao.
Ho una semplice gerarchia in cui le classi CtipoA e CtipoB derivano da Ctipobase.
Ho un vector di tipo Ctipobase contenente un insieme dei due tipi , ad es 3 CtipoA e 5 Ctipob.
E' possibile estrarre dal container stl , solo i tipi CtipoA o solo i Ctipob ?
Pensavo di utilizzare un dynamic_cast e un for_each , è un metodo possibile?
o esistono metodi migliori?
grazie.

p_marco
25-08-2010, 12:35
Sinceramente anch' io sono piuttosto ignorante in materia.
Forse non è il metodo migliore; ti suggerisco di inserire una funzione virtuale su ogni classe in modo da poterle distinguere.

giuseppe500
25-08-2010, 14:31
neanche usando i template si puo' utilizzare ad es la funzione copy per inserire in un secondo container tutti i tipi CTipoA o CTipoB a seconda del tipo scelto?
non conosco bene i template , quindi scusate se ho detto un eresia

giuseppe500
25-08-2010, 16:10
La domanda sul copy era una possibile soluzione , spiego meglio il problema:
ho un vector con tipo = classe base e ho una sequenza di classi di tipo tipo1 , tipo2, tipo3 ecc.. che derivano dalla classe base.
Alla fine adesso faccio un sort con un function object dove implemento l'operatore di confronto e mi trovo tutti gli oggetti ordinati in modo corretto .
Vorrei poter eseguire il sort solo su un tipo o su due tipi , quello che mi è venuto in mente in due ore è :
E' possibile templatizzare un function object ? in modo che ad es scrivendo:


sort(EntitiesToSort.begin(), EntitiesToSort.end(), CmpSortEntities<type>);

mi faccia il sort solo nelle entità di tipo uguale al tipo passato alla CmpSOrtEntities?
ad es modificando i parametri del function object?
che so:


class template <typename T>
class CmpSortEntitiesù
template <typename T>
bool operator()(T* pEnt1, T* pEnt2)

grazie, scusate se sono insistente e un po confusionario(sono partito da una domanda e ne ho fatte altre 2), giuro dopo questa non chiedo piu'.


ciao,

shodan
25-08-2010, 19:42
Originariamente inviato da giuseppe500
E' possibile templatizzare un function object ?

Si, ma ottieni solo di non scrivere due functor diversi.
Il punto è che le informazioni sul tipo derivato vengono perse quando tale tipo viene affidato a un puntatore a classe base e per riottenerle ci vuole un cast esplicito.
Generalmente si usano due tecniche per riottenerle in modo sicuro:
dynamic_cast
User RTTI (occhio che la chiamo così solo perché non saprei come altro definirla).

Il primo modo è sicuro, ma lento (specie se hai molti oggetti), il secondo è da verificare.

Il secondo modo, in pratica, consiste nell'aggiungere una funzione virtuale che restituisce un valore univoco (di solito un valore di una enum), definito dall'utente. Se tale valore coincide con quello che ti aspetti per quel tipo, si va di static_cast (non cast stile C).
Però se sbagli a passare i tipi, succede un disastro.

Il primo metodo assomiglia a qualcosa come:


template <typename DerivedType, typename BaseType>
struct CmpSortEntities {
bool operator(BaseType* a, BaseType* b) {
DerivedType* ta = dynamic_cast<DerivedType*>(a);
DerivedType* tb = dynamic_cast<DerivedType*>(b);
if (a == 0) return false;
if (b == 0) return false;
return ( *a < *b);
}
};

sort(EntitiesToSort.begin(), EntitiesToSort.end(), CmpSortEntities<DerivedClass,BaseClass> );


Il secondo a qualcosa come:


enum TypeList {
Base = 0, // la classe base
Tipo1,
Tipo2,
Tipo3,
...
TipoN
};

template <int RTTIVal, typename DerivedType, typename BaseType>
struct CmpSortEntities {
bool operator(BaseType* a, BaseType* b) {
if (a->get_info_type() != RTTIVal) return false;
if (b->get_info_type() != RTTIVal) return false;
// I tipi sono corretti.

DerivedType* ta = static_cast<DerivedType*>(a);
DerivedType* tb = static_cast<DerivedType*>(b);
if (a == 0) return false;
if (b == 0) return false;
return ( *a < *b);
}
};

sort(EntitiesToSort.begin(), EntitiesToSort.end(), CmpSortEntities<TypeList::Tipo2, Tipo2,BaseClass> );

Loading