Newsgroup: it.comp.lang.c++
Titolo: Errore strano (VC++ 6.0)

Ho un problema curioso con il Visual C++ 6.0, non riesco a compilare il
seguente codice.
L'obiettivo e' gestire una lista di connessioni di rete attive, e tra le
altre funzioni ci sono queste:
class network
{
private:
 mainsock *mainsocket;
 list<clientsock *> socklist;
 list<clientsock *>::iterator it1;
 list<clientsock *>::iterator it2;
 void input_one(clientsock *);
 void inputall(void);
};
void network::input_one(clientsock *s)
{
 if(!s->readinput())
  s->closeflag = true;
 return;
}
void network::inputall(void)
{
 it1 = socklist.begin();
 it2 = socklist.end();
 for_each(it1,it2,input_one);
 return;
}
Come si vede, vorrei utilizzare l'algoritmo for_each per applicare la
funzione input_one() a tutti i membri della lista socklist (puntatori a
oggetti di tipo clientsock).
Ma quando tento di compilare, ottengo questo errore:
d:\mud\network.cpp(36) : error C2664: 'for_each' : cannot convert parameter
3 from 'void (class clientsock *)' to 'void (__thiscall *)(class clientsock
*)'
        None of the functions with this name in scope match the target type
Che cavolo vuol dire ?!?
Massimo

  for_each(it1,it2,input_one);
La funzione input_one() non dovrebbe essere un membro di una classe
(almeno credo). Sicuramente funziona se è una funzione non membro oppure
un oggetto funzione.
EMG

  for_each(it1,it2,input_one);
for each č cosě definita:
template<class In, class Op> Op for_each(In first, In last, Op f)
{
    while(first != last) f(*first++);
    return f;
}
Il problema č che input_one č una funzione membro, quindi per essere
chiamata
ha bisogno di sapere *su* che oggetto deve essere chiamata:
network obj;
clientsock* s;
obj.input_one(s);
Poichč (nel tuo caso) input_one non accede a this, puoi
tranquillamente (anzi, č piů coerente) dichiararla come static
e risolvere cosě il problema.
Manlio Perillo

 ha scritto nel messaggio
news:39FD37D1...@flashnet.it...

Avevo pensato a qualcosa di simile (quel __thiscall lasciava pensare a un
problema di questo tipo), ma mi pare assurdo...
Però non voglio funzioni globali... e se la dichiaro static ?
Massimo

 e risolvere così il problema.
...allora avevo indovinato :-)
Appena rimetto mano sul compilatore provo, thanks.
Massimo



Mi sembra, però, che for_each ammetta come terzo argomento soltanto
un'instnza di una classe funzionale, nel qual caso puoi adottare una
soluzione del genere:
 struct input_one_caller
 {
	network*  bound;
	input_one_caller(network* n) : bound(n) { }
	void operator()( clientsock* s ) { bound->input_one(s); } 	
 };
E in network::input_all():
 for_each( it1, it2, input_one_caller(this) );
 
Salvo refusi, dovrebbe andare.
Max

  for_each( it1, it2, input_one_caller(this) );
esistono gia' costrutti per fare questo, date un occhio ai function
adapter, bind e mem_fun.
Ciao,
Nicola

 un'instnza di una classe funzionale,
No.
Il terzo argomento è un template.
Quindi se fai, ad esempio
    int f(int k) { return ++k; }
    int array[10];
    for_each(array, array + 10, f);
il terzo parametro template è un puntatore:
int (*)(int);
Infatti se hai un puntatore a funzione int (*pf)(int)
facendo pf(val) chiami la funzione.
Manlio Perillo

 adapter, bind e mem_fun.
Giusto, ma lě per lě non avevo voglia di trovare la giusta combinazione di
bind* e mem_func*. Eccola qua:
 for_each(it1,it2,std::bind1st(std::mem_fun1(&network::input_one),this));
Max

 adapter, bind e mem_fun.
Il problema è che il C++ é TROPPO vasto. :-)
EMG

 Perň non voglio funzioni globali... e se la dichiaro static ?
Si, funziona lo stesso.
EMG


Mi sembra che mem_fun1 non sia Standard.
Meglio usare mem_fun.
Manlio Perillo

 Meglio usare mem_fun.
In effetti lo Stroustrup non lo menziona nella tavola del Capitolo 18.
Perň l'ho trovato sia nel draft sia nella documentazione di Dinkumware. Se
non fosse standard sarebbe una strana mancanza, visto che mem_fun1_t č
senz'altro standard.
Max


Non è una mancanza.
Il fatto è che (dal codice del KAI C++):
 template <class S, class T>
 inline mem_fun_t<S, T> mem_fun(S (T::*f)())
 {
     return mem_fun_t<S, T>(f);
 }
 template <class S, class T, class A>
 inline mem_fun1_t <S, T, A> mem_fun(S (T::*f)(A))
 {
     return mem_fun1_t<S, T, A>(f);
 }
 template <class S, class T, class A>
 inline mem_fun1_t <S, T, A> mem_fun1(S (T::*f)(A))
 {
     return mem_fun1_t<S, T, A>(f);
 }
Come si vede mem_fun1_t è usato da mem_fun (per il quale
sono previste due funzioni scelte tramite overloading
-- poi ci sono anche le versioni const -- ).
Quindi mem_fun1 è inutile.
Manlio Perillo


Giusto, ho detto una sciocchezza (non tenevo conto del possibile
overloading di mem_fun).
Tuttavia nè la libreria del gcc nè quella del VC++ mettono a disposizione
quell'overload.
Max

Piu' esattamente mem_fun e' una funzione template ausiliaria che ritorna
l'oggetto funzionale appropriato in base ai parametri, in modo da non
doverlo scrivere esplicitamente.
Ciao,
Nicola


Strano, nella libreria del DJGPP 2.95.2 è presente.
Forse usi una vecchia versione.
Manlio Perillo