Newsgroup: it.comp.lang.c++
Titolo: dinamic_cast in template

Ciao a tutti.
Ho una domanda (credo) sui template (premettendo ovviamente che li sto 
studiando giusto ora)
Ho due classi in stretta relazione
class B;
 
class A {
	[...]
	virtual void fun ( B* stuff ) = 0;
	[...]
}
Ora.. quando si usa questa classe A,  la si usa sempre derivando anche 
l'altra "a"...
class derivedB, public B { [...] };
class DerivedA, public A {
	[...]
	void fun ( B* stuff )
	{
	    derivedB* mystuff = dynamic_cast<derivedB*>(stuff);
	    if ( mystuff )
	    {
			/* .... */
	    }
	}
	[...]
}
Insomma: chi deriva la A, sa che nella sua fun arriverà sempre e solo un 
puntatore alla sua derivedB. 
Sto cercando di capire se c'è un modo, utilizzando un template, di 
evitare che si debba scrivere sempre quel dinamic cast (e forse anche di 
derivare)
Non ho avuto molto successo...
Si può?


Sarebbe meglio approfondire, per sapere perché le due classi sono
strettamente legate.
Una soluzione che ti potrebbe essere utile potrebbe essere:
 //- SovietCast.cpp - START
class A
{
public:
	template <typename B>
		void fun(B* stuff){
			if(stuff){
				stuff->pack();
				size_t sz( stuff->howMuch );
			}
		}
};
class Good{
public:
	Good():howMuch(23){}
	void pack(){int i = 42;}
	size_t howMuch;
};
class Bad{
};
int main()
{
	Good good;
	Bad bad;
	A a;
	// Tutto OK: la classe Good definisce la funzione stuff e
	// il dato membro pack
	a.fun(&good);
	// Non compila.
        a.fun(&bad);
	// Errori di compilazione
	//SovietCast.cpp(13): error C2039: "howMuch": non è un membro di
"Bad"
	//SovietCast.cpp(12): error C2039: "pack": non è un membro di "Bad"
	return 0;
}
//- SovietCast.cpp - END
In questo caso la funzione A::fun accetta puntatori di qualunque tipo,
a patto
che definiscano una funzione pack()  e un dato membro howMuch.
Il controllo  viene fatto dal compilatore.
Nel caso del dynamic_cast il controllo viene fatto a runtime e nel
caso
in cui il puntatore non sia convertibile, dynamic_cast ritorna un
puntatore
nullo.
Ciao Ugo

 
Ciao!
grazie mille.
oggi mi metto a provare il codice (i template ancora nn li digerisco 
immediatamente.. mi ci vuole un minimo di tempo).
Le classi sono strettamente legate per questo motivo: la classe base A 
con le funzioni virtuali è una classe che fa da interfaccia a dei plugins.
Nella mia app, io carico con dlopen una serie di .so (.dll). Tutti questi 
plugins hanno ereditato A e vengono interpellati dalla mia app 
restituendo dei puntatori a B.
Questi puntatori a B sono in realtà dei puntatori a classi derivate da B. 
Infatti B contiene dei campi conosciuti alla mia app, ma i vari plugin 
hanno necessità di aggiungere le loro robe private (quindi derivando B e 
aggiungendo). E quando la mia app RI-passa uno dei vai B_derived* ad uno 
dei vari plugin, chiamando per esempio la funzione 	
	fun( B* stuff )
qui sopra, il plugin in questione ha la certezza che gli verrà passato un 
qualcosa che lui stesso ha creato.
Ecco.
Spero di essermi spiegato.
In ogni caso... Grazie mille 
Ora provo
Mario.

 };
ok.. mi sa che non è quel cercavo... 
intanto che chiedo al mio amico stroustrup...
ecco uno pseudopezzo del mio codice.
//base_plugin.h
class B { 
    int membro 
};
class A {
   virtual B* fun ( B* stuff = 0 ) = 0;
}
//plugin.cpp
#include <base_plugin.h>
class Bplug : public B {
    int altromembro;
}
class plugin : public A {
    B* fun_x ( B* stuff ) { 
        Bplug* b = dynamic_cast<Bplug*>(stuff);
 
        if(b) b->altromembro++;
        else b = new Bplug();
        return b;
    };
}
extern "C" A* create() { return new plugin(); }
//main.cpp
#include "base_plugin.h"
main ()
{
   /*dlopen vari*/
   A* a = dlopenedPointer->create();
   B* b = a->fun();
   B* b = a->fun(b);
   B* b = a->fun(b);
   B* b = a->fun(b);
   B* b = a->fun(b);
   B* b = a->fun(b);
   exit(0);
}
main.cpp e base_plugin.h vengono compilati assieme.
plugin.cpp viene compilato separatamente.
Ecco.
Mario

     B* fun_x ( B* stuff ) {
chi ha aggiunto quel _x ??
errore di copia-inolla ci fu.


Ma perche' usi la dynamic_cast?
nel codice che hai postato stai facendo un "upcast"!
usa la static_cast e hai fatto :-)

#include <iostream>
class ModuloParam
{
public:
	ModuloParam(){}
	~ModuloParam(){}
	virtual void miaFunzione(void) = 0;
};
template <typename T>
class ModuloBase {
public:
       /*Puugin common class*/
	ModuloBase(){}
	~ModuloBase(){}
	virtual T* fun ( T* pDMP = 0)=0;
};
class DerivatoModuloParam : public ModuloParam
{
public:
	DerivatoModuloParam(){}
	~DerivatoModuloParam(){}
	void miaFunzione(void)
	{
		std::cout << "DerivatoModuloParam"  << std::endl;
	}
};
class DerivatoModuloBase : public ModuloBase<DerivatoModuloParam> {
public:
	DerivatoModuloBase(){}
	~DerivatoModuloBase(){}
	DerivatoModuloParam* fun ( DerivatoModuloParam* pDMP = 0)
    {
		DerivatoModuloParam* dmp = new DerivatoModuloParam();
		return dmp;
    }
};
int main(int argc, char* argv[])
{
	std::cout << "INIZIO" << std::endl;
	ModuloBase<DerivatoModuloParam>* a = new DerivatoModuloBase(); //A* a
= dlopenedPointer->create();
	ModuloParam* b = a->fun();
	b->miaFunzione();
	std::cout << "FINE"  << std::endl;
	return 0;
}
cercando di fare con i template ecco come si potrebbe iniziare...
il problema, come vedi, e' che in questo caso devi conoscere il tipo
della DerivatoModuloParam che nel tuo caso non e' possibile, essendo
plugin.
Cercando di togliere quella riga (cioe' la conoscenza delle classi
derivate) ti ritroverai nella condizione precedente con la
static_cast,
almeno io non sono riuscito a farlo senza :-)

 usa la static_cast e hai fatto :-)
Veramente quello qua sopra e' un *down* cast ed il dynamic_cast e'
necessario.
Ciao,
Nicola


downcast - a cast from a base class to one of its derived classes.
OPS
hai ragione ma si puo' comunque usare la static_cast xche' B non e'
una polymorphic class.
o no?


Se B non fosse polimorfica non si potrebbe usare il dynamic_cast(). I
casi in cui e' possibile sostituire un dynamic_cast con uno
static_cast senza pericolo sono talmente pochi che non vale la pena
correre il rischio.
Ciao,
Nicola


In effetti i template non sono adatti per risolvere il tuo problema.
Ho dato un'occhiata ai libri che ho in casa e ce n'è uno che fa al
caso tuo: "Imperfect C++" di Matthew Wilson.  Il tuo problema è
trattato nel capitolo 8 "Objects across borders".
Prova a farti un giro sul suo sito 
http://www.synesis.com.au/index.html.Ci
sono dei link alle librerie che ha scritto e di cui tratta nel suo
libro. Può essere che ci sia una soluzione pronta per l'uso.
Ciao Ugo