Newsgroup: it.comp.lang.c++
Titolo: Problema con Member Template.

Ciao a tutti,
ho il semplice codice di esempio:
====================================================================
// provaCast.cpp : Defines the entry point for the console
application.
//
#include <iostream>
#include <string>
class A
{
public:
	A()
	{
		s = "CIAO!";
	}
	std::string print()
	{
		return s;
	}
private:
	std::string s;
};
class B
{
};
class C : public A, public B
{
};
class Wrapper
{
public:
	Wrapper()
	{
		b = new C();
	}
	template <class T> T* get()
	{
		return dynamic_cast<T*>(b);
	}
private:
	B *b;
};
int main(int argc, char* argv[])
{
	Wrapper w;
	std::cout << (w.get<A>())->print() << std::endl;
	return 0;
}
====================================================================
Praticamente ho una classe C che deriva da una classe B e A. Inoltre
la classe C viene wrappata, per qualche "oscuro" motivo con una classe
Wrapper, che inserisce il puntatore di C nella classe madre B.
Nel main creo un wrapper e chiedo il puntatore a C cercando di
castarlo a A automaticamente con il metodo get().
A questo punto il compilatore mi dice:
====================================================================
-------------------Configuration: provaCast - Win32
Debug--------------------
Compiling...
provaCast.cpp
d:\pdgprojects\provacast\provacast.cpp(54) : error C2275: 'A' :
illegal use of this type as an expression
        d:\pdgprojects\provacast\provacast.cpp(8) : see declaration of
'A'
d:\pdgprojects\provacast\provacast.cpp(54) : error C2059: syntax error
: ')'
Error executing cl.exe.
provaCast.exe - 2 error(s), 0 warning(s)
====================================================================
Dov'è che sbaglio? Grazie anticipatamente a tutti.
Saluti,
   Mirko.

Ciao a tutti,
ho il semplice codice di esempio:
===========================================================
// provaCast.cpp 
//
#include <iostream>
#include <string>


private:
	std::string s;
};
class B
{
};

};




	return 0;
}
===========================================================
Praticamente ho una classe C che deriva da una classe B e A. Inoltre
la classe C viene wrappata, per qualche "oscuro" motivo con una classe
Wrapper, che inserisce il puntatore di C nella classe madre B.
Nel main creo un wrapper e chiedo il puntatore a C cercando di
castarlo a A automaticamente con il metodo get().
A questo punto il compilatore mi dice:
===========================================================
Compiling...
provaCast.cpp
d:\pdgprojects\provacast\provacast.cpp(54) : error C2275: 'A' :
illegal use of this type as an expression
d:\pdgprojects\provacast\provacast.cpp(8) : see declaration of
'A'
d:\pdgprojects\provacast\provacast.cpp(54) : error C2059: syntax error
: ')'
Error executing cl.exe.
provaCast.exe - 2 error(s), 0 warning(s)
===========================================================
Dov'ıı che sbaglio? Grazie anticipatamente a tutti.
Saluti,
Mirko.
------------------------------------------------------------------------
Questo messaggio e` stato inviato da 
http://www.inwind.it

    Mirko.
Primo problema,
penso che alcuni compilatori hanno ancora problemi col member template (ho
provato col VC++ 6 service pack 5 e mi da un errore sulla std::cout della
main).
Secondo problema,
non puoi fare un dynamic_cast fra A e B non essendo queste parenti fra loro,
anche se hai fatto nel costruttore di Wrapper, l'allocazione dinamica b =
new C(); b e' sempre dichiarato come puntatore a B, per cui ti vieta di fare
un dynamic_cast.
Per cui la soluzione e' di dichiarare in Wrapper un membro puntatore a C *c;
e di usare un compilatore tipo il DevC++ che mi compila senza problemi il
tuo esempio corretto.
Eccoti il codice (da non compilare con VC++ 6 !):
#include <iostream>
#include <string>
class A
{
public:
 A() {s = "CIAO DA MAURUS";}
 std::string print(){return s;}
private:
 std::string s;
};
class B
{
};
class C : public A, public B
{
};
class Wrapper
{
public:
 Wrapper(){c = new C();}
 template <class T> T* get()
 {
  return dynamic_cast<T*>(c);
 }
private:
 C *c;
};
int main(int argc, char* argv[])
{
 Wrapper w;
 std::cout << (w.get<A>())->print() << std::endl;
 return 0;
}
Ciao
Maurus

"Mirko Cambi" ha scritto
: Ciao a tutti,
:
: ho il semplice codice di esempio:
:
: ====================================================================
:
: // provaCast.cpp : Defines the entry point for the console
: application.
: //
:
: #include <iostream>
: #include <string>
:
: class A
: {
: public:
: A()
: {
: s = "CIAO!";
: }
// conviene avere un distruttore virtuale
// soprattutto se devi derivare da A
  virtual ~A() {}
:
: std::string print()
: {
: return s;
: }
:
: private:
: std::string s;
: };
:
: class B
: {
// idem
  virtual ~B() {}
:
: };
:
: class C : public A, public B
: {
:
: };
:
: class Wrapper
: {
: public:
: Wrapper()
: {
: b = new C();
: }
  Wrapper() : b( new C ) {}
oppure
  Wrapper() : b(0) { b = new C; }
e
  ~Wrapper() { delete b; }
:
: template <class T> T* get()
: {
: return dynamic_cast<T*>(b);
: }
 questa funzione potrebbe dare pbs con qualche vecchio
 compilatore.
: private:
: B *b;
: };
:
: int main(int argc, char* argv[])
ciao
Massimo

 un dynamic_cast.
Sbagliato.  dynamic_cast e` perfettamente supportato fra puntatori a classi
non parenti fra loro: non solo lo standard lo prevede, ma persino VC++6 lo
supporta.  NULLA "vieta di fare un dynamic_cast", purche`, ovviamente, le
classi siano polimorfe.  Se il tipo di runtime ("piu` derivato")
dell'oggetto
cui punta l'argomento del dynamic_cast non deriva dalla classe richiesta, si
avra` semplicemente, appunto a runtime, un risultato di 0 da dynamic_cast.
Alex


Ciao Alex,
hai perfettamente ragione.
Ho preso un abbaglio dato dal fatto che il compilatore mi dava un messaggio
di errore, quando cercavo di fare il dynamic_cast senza aver dichiarato
virtual i distruttori delle classi.
L' errore era:
35 testtemplatemain.cpp
 cannot dynamic_cast `Wrapper::b' (of type `class B *') to type `class A *'
Ed io lo avevo interpretato erroneamente.
Se invece come giustamente dici, rendessi le classi polimorfe, giusto dando
l'attributo virtual ai loro distruttori, il dynamic_cast funziona pur non
essendo parenti A e B.
Codice riveduto e corretto :
#include <iostream>
#include <string>
class A
{
public:
 A() {s = "CIAO da Alex Martelli";}
 std::string print(){return s;}
 virtual ~A(){}
private:
 std::string s;
};
class B
{
public :
 virtual ~B(){}
};
class C : public A, public B
{
};
class Wrapper
{
public:
 Wrapper(){b = new C();}
 template <class T> T* get()
 {
  return dynamic_cast<T*>(b);
 }
private:
 B *b;
};
int main(int argc, char* argv[])
{
 Wrapper w;
 std::cout << (w.get<A>())->print() << std::endl;
 return 0;
}
Bentornato Alex,
Maurus

 Bentornato Alex,
Grazie!  Ma e` un transitorio... tiro il fiato dopo avere completato
il "Python Cookbook" per O'Reilly (con David Ascher) e prima di tornare
al "Python in a Nutshell" (sempre per O'Reilly, ma li` sono da solo --
l'ho interrotto qualche mese per lavorare al Cookbook).  Dato che la
mailing list di Boost (
www.boost.org
) si e` infiammata di interessanti
discussioni mi e` tornata una temporanea nostalgia del C++ e ho pensato
di dare un occhio qui, ma + prima che poi dovro` reimmergermi...:-).
Alex

 Alex
Prima che ti reimmergi, vorrei rubarti un po' del tuo tempo prezioso
per spiegarmi delle cosette:
1) Perche' mai un programmatore C++ dovrebbe usare il Pyton, ovvero
cosa potrei fare col Pyton che non posso fare o lo faccio in maggior tempo
col C++?
2) Di quali strumenti si ha bisogno per cominciare a lavorare col Pyton?
Ambiente di sviluppo, interprete ecc...a pagamento o free.
3) Dopo quanto tempo si incomincia a diventare produttivi magari seguendo il
tuo "libro di cucina"?
Grazie per le eventuali risposte.
Maurus

tuo "libro di cucina"?
leggendo il tutorial se già sai programmare dopo 2 giorni riesci a
fare cose che in C++ riesci a fare dopo mesi.
Comunque visto che 	qui sei OT ti consiglio di spostarti su
it.comp.lang dovre ti potremmo dare informazioni più ampie su Python.
Ricordati di usare il tag [PYTHON] o [CONFRONTO] se vuoi confrontare
più linguaggi.
-- 
Marco Barisione (ICQ 84277092)

 Grazie per le eventuali risposte.
Prego, e spero di non avere scocciato altri.  Faccio presente che la
discussione di Python avviene sul nuovo gruppo it.comp.lang (usare
www.mailgate.org
 se il proprio provider non lo supporta ancora) e che
su detto gruppo va apposto un [TAG] per chiarire di che linguaggio si
parla, ad esempio [Python] per parlare di Python, nel Subject.
Alex

Alex Martelli ha scritto : 
[mega ultra cut]
Volevo solo porti una domanda, ho sentito parlare molto bene di Python
e tu stesso ne hai fatto un'ottima presentazione, tuttavia è da un pò
che mi incuriosisce un altro liguaggio di scripting e cioè Ruby, che 
dicono unisca la semplicità di Python ad un migliore supporto per l'OO.
Tu cosa ne pensi?
-- 
  _  _ >>Now on Linux<<  _     || ICQ number.................Non lo uso
 | \| |___ _____ ___ ___|_|___ || Home-Page ................Non ce l'ho
 | .` | -_|     | -_|_ -| |_ -||| E-Mail................Non l'avrai mai
 |_|\_|___|_|_|_|___|___|_|___||| Un Nemesis che ha pochi e-contatti ;)

Ruby
E` giusto un pochettino OT  :-)
Prova su it.comp.lang (a me comunque non piace molto anche se
praticamente non lo conosco).


(quelli che dicono "un giorno" mentre io dico "una settimana")!
Non ti abbattere, ce la puoi fare. ROTFL.
Alex, durante le ferie, scrive programmi di analisi
bridgistica (!!!).
E' un pazzo scatenato :)
-- 
Andrea Laforgia - walkietalkie(at)
libero.it
"Meglio cieco che negro" (Stevie Wonder)

 praticamente non lo conosco).
Se Python non esistesse, Ruby sarebbe assai interessante.  Ma le
differenze fra Ruby e Python sono decisamente minori rispetto a
quelle fra uno qualsiasi dei due e praticamente qualsiasi altro
linguaggio (forse Smalltalk e` il meno lontano).  Python e` piu`
maturo e Ruby troppo influenzato dall'impronta di Perl (variabili
speciali con "nomi" come $/ $, $. e simili...) per cui non c'e` nessuna
particolare ragione di approfondire Ruby, esistendo Python:-).
Python si puo` integrare a meraviglia con il C++ (a ipotetico perfetto
standard ISO, ma in pratica i compilatori gcc e Microsoft sono poi
supportati anche se ISO C++ non lo supporta ancora nessuno:-)
grazie alla meravigliosa Boost (
www.boost.org
, sito caldamente
raccomandabile a qualsiasi programmatore C++).  Non credo Ruby
abbia nessun aggancio specifico C++, solo a livello C (Python ha
anche quello C, ma anche le possibilita` specifiche C++).  E cosi`
cerchiamo di tornare ontopic...:-)
Alex

 dicono unisca la semplicità di Python ad un migliore supporto per l'OO.
Vedi anche la mia replica a Marco sul thread, comunque, specificamente
sull'OO, ad esempio: Ruby ha eredita` singola, Python multipla.  Chi dice 
che la prima rappresenta "migliore supporto per l'OO" e` caldamente 
invitato ad andarsene su altri gruppi (Java, Smalltalk, C#, ...) che i 
patiti di C++ (o Eiffel, ecc) queste eresie preferiscono risparmiarsele:-).
In precedenti versioni di Python non si poteva ereditare da certi tipi
(come ad esempio int), come non si puo` farlo in C++, C#, Java, Eiffel.
Con l'attuale Python 2.2, puoi ereditare da int, ecc, come in Ruby o
Smalltalk (non che serva tantissimo, ma altri tipi come dict e list si`, e
comunque questo si puo` in effetti considerare "piu` OO" -- ma con
Python 2.2 lo fai quanto in Ruby).
Io cerco sempre di ritirare in argomento anche il C++ se no qui ci
linciano, sara` meglio muoversi su it.comp.lang, no...?!
Alex

Se Python non esistesse, Ruby sarebbe assai interessante.  
[cut]
Ok, grazie! chiudo qui altrimenti ci linciano :)


E` giusto un pochettino OT  :-)
Ehm in effetti, però visto che c'eravamo c'ho provato, cmq chiudo qui,
ne ho approfittato vista la presenza di un tale esperto ;)


Alex Martelli ha scritto : 

La mia era una semplice curiosità e volevo approfittare delle tue
conoscenze per avere un parere autorevole, non volevo certo aprire un
dibattito Ruby vs Python, e cmq certamente non qui :)
Grazie, cmq ora it.comp.lang quasi quasi lo sottoscrivo, visto che
vorrei imparare un linguaggio di scripting e sono appunto indeciso tra
Python e Ruby, conoscere altri pareri mi aiuterà.
