|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
[c++] puntatori a template
ammettiamo di avere un template semplicissimo
Codice:
template <typename T>
class dato
{
T v;
public:
dato(T v) : v(v) {};
T get() { return v; }
T set(T newv) { return v = newv: }
};
typedef dato<int> datoint;
typedef dato<long> datolong;
però non si può fare un vector di un template si può però fare una cosa di questo tipo: Codice:
class datobase
{
public:
datobase() {};
virtual ~datobase();
}
template <typename T>
class dato : public datobase
{
T v;
public:
dato(T v) : v(v) {};
T get() { return v; }
T set(T newv) { return v = newv: }
};
Codice:
vector<datobase*> vdati; idee? |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
la domanda si può riformulare in un altro modo:
come è possibile definire un'interfaccia alla classe base che però non abbia un tipo di ritorno fisso? (vedi la funzione get...) |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
Re: [c++] puntatori a template
Quote:
intendevo dire che non si può fare un vettore di template non ancora definiti |
|
|
|
|
|
|
#4 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Se ho capito bene la tua domanda non e' difficile fare quello che chiedi. Ad esempio:
Codice:
template <class T>
void foo()
{
vector< dato<T>*> set;
/* etc... */
}
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
non voglio un vettore all'interno della classe, non ci sarebbe problema altrimenti, come hai fatto giustamente notare tu
voglio un vettore che contenga puntatori alla classe template, però non dello stesso tipo questo si fa utilizzando la classe base il problema è definire un'interfaccia che mi permetta di lavorare coi tipi defiiniti dal template e questo penso non sia possibile.. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
forse,e dico forse con i "traits"
http://www.cantrip.org/traits.html o forse ancora (se ho capito quello che vuoi) con l"any" della boost: http://www.boost.org/libs/any/index.html |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
ottimi link entrambi, grazie mille
le any sembrerebbero la soluzione, devo fare qualche test per capire esattamente cosa comportano ma già il fatto che una volta definito il tipo non effettua conversioni implicite mi piace ^^ |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
ah,no,forse ho capito che vuoi.
Si fa con un pointer wrapper. Cerca "Mumit STL newbie guide". Vedi se va bene questo: Codice:
Templated pointer wrapper that takes a pointer to the base class
The following example shows 2 classes derived from Base, derived1 and derived2 and a templated wrapper Wrapper<T>. The wrapper class assumes that the base class provides a virtual clone facility and does the memory management.
Note: After the new'd Base derivative is passed to the wrapper, it owns it and deletes it in the destructor.
--------------------------------------------------------------------------------
#include <stl.h>
#include <string.h>
#include <iostream.h>
//
// abstract base class
//
class Base {
public:
const char* typename() const { return typename_; }
virtual Base* clone() const = 0;
virtual void identify(ostream& os) const = 0;
virtual ~Base();
public:
static int count;
protected:
Base(const char* typename);
Base(const Base& base);
private:
char* typename_;
};
Base::Base(const char* typename) {
const char* tname = (typename) ? typename : "unknown";
strcpy(typename_ = new char[strlen(tname) 1], tname);
count;
}
Base::Base(const Base& base) {
strcpy(
typename_ = new char[strlen(base.typename_) 1], base.typename_
);
count;
}
Base::~Base() {
delete[] typename_;
--count;
}
//
// First derived class.
//
class Derived1 : public Base {
public:
Derived1(int data) : Base("derived1"), data_(data) { }
Derived1(const Derived1& d) : Base("derived1"), data_(d.data()) { }
virtual ~Derived1() { }
virtual Base* clone() const { return new Derived1(*this); }
virtual void identify(ostream& os) const;
int data() const { return data_; }
private:
int data_;
};
virtual void Derived1::identify(ostream& os) const {
os << "(" << typename() << " " << data() << ")";
}
//
// Second derived class.
//
class Derived2 : public Base {
public:
Derived2(int data) : Base("derived2"), data_(data) { }
Derived2(const Derived2& d) : Base("derived2"), data_(d.data()) { }
virtual ~Derived2() { }
virtual Base* clone() const { return new Derived2(*this); }
virtual void identify(ostream& os) const;
int data() const { return data_; }
private:
int data_;
};
virtual void Derived2::identify(ostream& os) const {
os << "(" << typename() << " " << data() << ")";
}
//
// now define a templated pointer wrapper. The class must support the
// clone() method.
//
template <class T>
class PtrWrapper {
public:
PtrWrapper(T* t_ptr = 0) : t_ptr_(t_ptr) { }
PtrWrapper(const PtrWrapper<T>& w) {
t_ptr_ = w() ? w()->clone() : 0;
}
~PtrWrapper() { delete t_ptr_; }
const T* operator()() const { return t_ptr_; }
T* operator()() { return t_ptr_; }
PtrWrapper<T>& operator= (const PtrWrapper<T>& w) {
delete t_ptr_;
t_ptr_ = w()->clone();
return *this;
}
private:
T* t_ptr_;
};
template <class T>
bool operator== (const PtrWrapper<T>& w1, const PtrWrapper<T>& w2) {
return false;
}
template <class T>
bool operator< (const PtrWrapper<T>& w1, const PtrWrapper<T>& w2) {
return false;
}
//
// end of class defs.
//
// define static members.
int Base::count = 0;
int main(int, char*[]) {
list<PtrWrapper<Base> > list1;
list1.push_back(PtrWrapper<Base> (new Derived1(101)));
list1.push_back(PtrWrapper<Base> (new Derived2(201)));
list1.push_back(PtrWrapper<Base> (new Derived2(202)));
list1.push_back(PtrWrapper<Base> (new Derived1(102)));
list1.push_back(PtrWrapper<Base> (new Derived2(203)));
list<PtrWrapper<Base> >::const_iterator it = list1.begin();
for(; it != list1.end(); it) {
const PtrWrapper<Base>& w = *it;
w()->identify(cerr);
cerr << " ";
}
cerr << endl << endl;
return 0;
}
--------------------------------------------------------------------------------
And here's the output:
--------------------------------------------------------------------------------
(derived1 101) (derived2 201) (derived2 202) (derived1 102) (derived2 203)
Ultima modifica di verloc : 15-02-2004 alle 10:23. |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
è praticamente quello che ho fatto io
il problema è che in quell'esempio l'interfaccia non fornisce metodi che ritornano tipi T |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
e infatti...
Cmq,se vuoi un contenitore che contenga tipi di dato diversi allora "any" dovrebbe fare al caso tuo. Dovresti prima di utilizzarlo, tornare indietro e riflettere se l'impostazione logica del tuo problema sia ottimamente risolto da un contenitore di quel genere oppure richieda una diversa soluzione;più efficiente o più pulita. Dico così,a caso |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
no, neanche le any fanno al caso mio...
a me serve un "qualcosa" che sia una interfaccia comune a tipi diversi però questo qualcosa, una volta deciso di che tipo è, NON deve accettare tipi diversi inoltre è per me pressochè fondamentale il poter contenere questo "qualcosa", di qualsiasi tipo sia, all'interno di un singolo container (un vector, un map, etc...) Ultima modifica di ri : 15-02-2004 alle 10:42. |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Bel problema...in pratica ti servirebbe un vettore di oggetti non specializzati che possa contenere oggetti di qualsiasi tipo... Mica una cosa da nulla...
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
beh quando mi rivolgo al forum è perchè ho cose stuzzicanti da proporre
|
|
|
|
|
|
#14 | |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Quote:
Si, puoi farlo, ad esempio il tipo di ritorno puo' essere a sua volta una classe base; in alternativa fai fare tutto il lavoro alle classi nel vettore e non ritorni mai oggetti. Ma non penso che sia quello che ti serve, visto che poi a runtime devi sempre andare a fare dei dynamic_cast e controllare che hai il tipo che ti serve. Mi sembra che ti serva il vettore come "buffer temporaneo" per metterci gli oggetti e pescarteli dopo... a questo punto non ti conviene tenerti un contenitore per ogni tipo ? |
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
no il vettore mi serve come descrittore di una struttura dati generica composta da tipi di dato diverse (es, una tabella di un db, con N campi con un max di N tipi diversi per campo), che una volta definita rimane fissa
non voglio fare N vettori per gli N tipi di dato perchè non è detto che i tipi rimangano sempre N... |
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
/\/\@®¢Ø: hai la signature troppo lunga... Può essere al max 3 righe a 1024x768... |
|
|
|
|
|
|
#17 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#18 | |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Quote:
Io sono a 1024x768 e Konqueror me le fa stare su tre righe Vabbe', dammi un attimo di tempo che le modifico |
|
|
|
|
|
|
#19 | |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Quote:
Prima dici che una volta definita rimane fissa, poi dici che non e' detto che rimangano sempre gli stessi... Non puoi farmi un esempio concreto (magari non legale, ma che renda l'idea) ? |
|
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Feb 2003
Città: fra casa e lavoro
Messaggi: 1061
|
i tipi possono non rimanere gli stessi nella "vita" del sorgente.... fra 3 mesi potrebbe esserci bisogno di inserire un nuovo tipo "unsigned long double salto mortale carpiato avvitato" e non vorrei dover andare a toccare il codice
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 15:22.



















