Newsgroup: it.comp.lang.c++
Titolo: Template a run-time

Ciao,
ho una classe "collection<T>" derivata dalla "object". Devo permettere che
gli utenti utilizzino questa classe collection con qualsiasi tipo, un po
come le classi STL. Tutti gli oggetti creati vanno in un vettore di
"object".
Alla terminazione del programma devo chiamare un metodo di tutti gli oggetti
creati dagli utenti, ma come posso sapere a run-time che tipo di oggetto è ?
Ossia un oggetto "collection< ? >".
Non posso fare un generico ((collection<int>*) obj)->display() perchè non so
se l'oggetto è un collection di int, di string, o altro.
Conoscete una soluzione ???


wrote:

In generale l'istanzazione di un template richiede che il parametro
soddisfi certi vincoli, tipicamente deve fornire un certo metodo.
Insomma il tuo template deve costringere chi lo istanzia a fornire
certe funzioni. Vedi ad esempio la definizione della template function
max:
template <typename T>
T max(T sx, T dx) {
  return (sx>dx)? sx: dx;
}
Nota come sia necessario che operator > sia definito
su T
Paolo
-----------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------


Che centra ? Io posso utilizzare la funzione "Max" con un int o una string,
ma come posso determinare a run-time il tipo T ?? La risposta potrebbe
essere il typeid(T) ed in questo caso potrebbe andare bene...
Ma se io ho una classe A<T> con due istanze:
A<int>  intero;
A<string>  stringa;
e questi oggetti li metto in un array generico, poi come faccio dall'array a
risalire a che tipi sono, ossia A<int> il primo e A<string> il secondo ???
Mi serve perchc poi dovrei fare una display del tipo e chiaramente varia in
base al tipo.
Ciao, Lvca.



risalire a che tipi sono, ossia A<int> il primo e A<string> il secondo ???
A<T> deve utilizzare il polimorfismo (quello della OOP o quello della
programmazione generica). Il polimorfismo della oop pero` va bene solo
con le classi.
Comunque nel tuo caso potresti  usare l'rtti... ci sono altre soluzioni
ma sono un po' artificiose (almeno quelle che mi vengono in mente).



mmmmh, non so se ho capito bene quello che ti serve comunque potresti
definire la collection come una collezione di oggetti di una classe
Object_1, derivata dalla object, all'interno della quale hai definito una
variabile (una stringa, un UINT, un int....), che al momento
dell'inserimento da parte dell'utente, ti identifichi il tipo di oggetto
inserito. Cosě alla terminazione del programma, magari con uno switch,
richiami il metodo giusto per ogni tipo diverso di oggetto, a seconda del
valore della variabile di controllo.
Altrimenti c'č un metodo ancora piů efficiente utilizzando i puntatori, ma
non so se ho capito bene la domanda....
Fammi sapere


La soluzione che uso è MOLTO artificiosa e consiste nel creare delle
meta-classi.
Poi nel costruttore della classe colection<T> uso il RTTI con
typeid(T).name() e mi vado a cercare nelle mie meta-classi la classe
utilizzata...
Poi dall'arrai faccio un generico collection<int> per scorrere la lista
degli oggetti della collezione. Questa che uso funziona, ma volevo sapere se
ne esistono altre che sfruttino il linguaggio C++ !!!
A quali soluzioni ti riferivi ?
Grazie, ciao Lvca.

}
Si, ma come dichiari l'oggetto coll ???
Ciao, Lvca.

 Conoscete una soluzione ???
se la tua collection fosse istanziabile solo per tipi derivati da una classe
base con metodo virtuale display() non sarebbe un problema (basterebbe chiamare
il metodo display per ogni elemento della collezione, senza preoccuparsi del tipo)
se invece non vuoi porre questo vincolo sul tipo degli oggetti da "collezionare"
puoi fare qualcosa del genere (vado un po' a memoria, non ho provato a compilarlo)
template <class T>
ostream & operator  << (ostream &s,const collection<T> &c)
{
    collection<T>::const_iterator it;
    for( it = c.begin(); it != c.end(); it++ )
	s << *it << std::endl;
    return s;	   
}
ovviamente devi implementare l'operatore << per i tipi non primitivi che vuoi collezionare.
In generale ti occorre un metodo per poter visualizzare ogni oggetto indipendentemente dal
suo tipo (quindi, se non vuoi usare gli stream, puoi scrivere una free function display()
per ogni tipo che ti interessa)
*Fabio*
-- 
Our little systems have their day;
They have their day and cease to be;
They are but broken lights of thee.
		-- Tennyson

:

Momento. Tu vuoi chiamare una funzione *su* l'oggetto contenuto o un metodo 
*di* esso?
Nel secondo caso, collection di <int> sono escluse, in quanto i tipi primitivi 
non hanno ovviamente metodi. 
Quindi suppongo tu voglia chiamare un'unica funzione che agisca nello stesso 
modo su collection di tipi diversi. Una funzione template fa al caso tuo, ad 
esempio:
template <class T>
void miafunzione(set<T> &coll) {
	for(set<T>::iterator i=coll.begin();i!=coll.end();i++)
		cout << *i << endl;
}
void main(void) {
 set<int> a;
 set<float> b;
 a.insert(1);
 b.insert(0.5);
 miafunzione(a);
 miafunzione(b);
}
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun/

:
Oh, naturalmente la funzione puo' fare qualcosa come
template <class T>
void miafunzione(set<T> &coll) {
	string type = typeid(T).name();
	if (type == "int") {
		cout << "int";
	} else if (type == "float") { ... }


A quali soluzioni ti riferivi ?
Al momento mi viene in mente che si potrebbe
passare al template un ulteriore parametro, appunto
un puntatore alla funzione. Cio` pero` ti obbliga
a fissare nel template la signature della funzione
(ma penso sia un limite accettabile).
Una possibile signature per la funzione potrebbe essere
void Func(T&)
