Newsgroup: it.comp.lang.c++
Titolo: [OT?] funzione membro classe template non inline con VC6

Ciao a tutti,
il seguente pezzo di codice il mio compilatore non lo prende segnando 
l'errore che vedete nelle ultime righe (che sinceramente non capisco)
Come si può intuire il mio compilatore è una vera m... con i template 
(VC6), però devo usare quello, quindi non vale rispondere cambia 
compilatore :) (ho provato il VC8 e lo compila senza problemi).
Se definisco la funzione B::foobar inline, invece compila, ma mi farebbe 
più comodo definirla non inline.
Qualcuno conosce qualche workaround?
template <class S>
struct A
{
	typedef S S;
};
template <class T>
struct B
{
	void foo(int a);
	void foobar(typename T::S* pS);
};
template <class T>
void B<T>::foo(int a)
{
}
template <class T>
void B<T>::foobar(typename T::S* pS)
{
} //error C2244: 'B<T>::foobar' : unable to resolve function overload
B< A <int> > bb;

 Qualcuno conosce qualche workaround?
Il tuo ottimismo e' encomiabile. Purtroppo pero' il tuo messaggio
contiene gia' tutte le risposte ;-)
Ciao,
Nicola

 
E invece.... (rullo di tamburi)
... ho trovato un workaround che nel mio caso può funzionare.
Lo posto caso mai interessasse a qualcuno:
(ho aggiunto typedef T::S S; in B e ho cambiato il tipo dell'argomento 
di foobar da T::S* a S*)
template <class S>
struct A
{
	typedef S S;
};
template <class T>
struct B
{
	typedef T::S S;
	void foo(int a);
	void foobar(typename S* pS);
};
template <class T>
void B<T>::foobar(typename S* pS)
{
}
template <class T>
void B<T>::foo(int a)
{
}
B< A <int> > bb;

 l'errore che vedete nelle ultime righe (che sinceramente non capisco)
Stranamente sia BCC55 che VC++ Toolkit 2003 me lo compilano senza errori 
mentre gcc 4.1.0 mi dice:
test.cc:4: error: declaration of 'typedef S A<S>::S'
test.cc:1: error:  shadows template parm 'class S'
test.cc:4: error: declaration of 'typedef S A<S>::S'
test.cc:1: error: changes meaning of 'S' from 'class S'
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 

     void foobar(typename S* pS);
credo di non capire, non mi sembra che questa dichiarazione 
indichi che foobar sia una funzione template anche del parametro 
S, ma solo di T ...
per il poco che mi sembra di capire di ciò che vuoi fare, avrei 
dichiarato foobar così :
template <class T>
struct B
{
     typedef T::S S;
     void foo(int a);
     template <typename S> void foobar(S * pS);
};
poi per la definizione non so improvvisarla a braccio. Tenterei 
così (sicuramente sbagliando)
template <class T, typename S> void B<T> :: foobar (S * pS)
{...};
probably la sintassi non è corretta, ma spero di aver reso 
l'idea. Invece nel tuo esempio non capisco bene come si evinca 
che foobar è un template del parametro S
ciao
Soviet_mario


>     typedef T::S S;
era qui la dipendenza di S dall'unico parametro template T
Per cui indirettamente anche S è templatizzato.
Tuttavia mi pare un codice un po' esile nella misura in cui 
potresti chiamare la struct B con argomento una classe che non 
supporta il membro statico S. OK avresti errore in compile time, 
ma mi chiedo se il messaggio sarebbe espressivo.
Detto in altre parole è uno di quei casi che già avevo 
incontrato in cui sarebbe preziosissima la possibilità di usare 
restrizioni sulla genericità degli argomenti template, nel caso 
specifico bisognerebbe dire che class T non è un ente generico, 
ma deve essere limitato alle sole classi
"struct A<pincopallino>"
Infatti poi quando istanzi scrivi
B <A <int>> bb;
ma nessuno ti avrebbe impedito, vedendo la sola dichiarazione di 
B, di pensare di scrivere
B <ClassWrong> ccc;
B <double> ddd;
ottenendo ovviamente insulti relativamente alla riga
 >> struct B
 >> {
 >>     typedef T::S S;
perchè ClassWrong e double non possiedono un typedef chiamato S.
Sarei curioso di provare quanto chiari e utili siano i messaggi 
di errore in tal caso.
Delle restrizioni ne sento proprio la mancanza, in effetti.
ciao
soviet


 void B<T>::foobar(typename S* pS)
                    ^
...e non qui. Se cambi cosa succede? Te lo suggerisco perche' cosi'
com'e' a mio avviso non e' C++ valido, anche se VC++6 la pensa
altrimenti.
Ciao,
Nicola

 
Hai sicuramente ragione.
Inizialmente io typename non lo avevo neppure messo, poi ho visto che 
VC8 mi dava una warning consigliando di metterlo. Così misi typename in 
quel punto, VC8 smise di lamentarsi ma VC6 rimaneva col suo vecchio errore.
Poi ho trovato il trucco del typedef e l'ho provato solo con VC6 che lo 
accetta (per me alla fine dei conti è sufficiente). Ora ho provato con 
VC8 che si lamenta ma mettendo typename dove dici tu va tutto a posto.
Grazie.
GM

 messaggio sarebbe espressivo.
...
L'esempio che ho postato è un esempio minimale che serviva solo per 
riprodurre il problema.
Ovviamente nel caso "vero" c'è qualcosa in più attorno...
Comunque nel mio caso io SO che la classe che passo come argomento di 
template definisce un tipo che si chiama S.
Non sto scrivendo una libreria che deve essere generica, mi basta essere 
generico per i 4 tipi che a me interessano (senza dover riscrivere 4 
classi praticamente identiche).
Per uanto riguarda l'espressività dei messaggi di errore...
... ti confermo che VC6 fa schifo .
VC8 è sicuramente migliore (forse fin troppo "prolisso" ma di solito 
riesco a capire quasi subito dove sta il problema).
Altri compilatori non li conosco abbastanza per esprimere giudizi.