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:
codice:
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:
codice:
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> );