Newsgroup: it.comp.lang.c++
Titolo: puntatori a funzioni membro

Ciao a tutti,
vorrei scrivere una libreria sufficentemente generica per implementare
il meccanismo di callback tra gli oggetti, dove una classe Server
registra il puntatore ad una funzione membro della classe Client, che
potra' richiamare in seguito...
Il codice che segue e' un primo tentativo di realizzare questo
meccanismo, tuttavia non e' sufficente, perche' la classe template
Server deve essere istanziata specificando quale sara' la classe
Client, mentre io vorrei che al Server possa essere collegato un
qualsiasi membro di una qualsiasi classe a patto, naturalmente che
rispetti la firma della funzione.
Qualcuno ha un'idea da suggerire?
	Grazie Stefano
#include <iostream>
#include <string>
#include <functional>
using namespace std;
// event identifica una funzione membro della classe T che riceve come
argomento A e restituisce R
template<class R,class T,class A>
class event
{
	typedef mem_fun1_t<R,T,A> funct;
public:
	event():m_handler(NULL),connected(false){}
	~event(){}
	void connect(T& t,funct& ev){m_t=t;m_handler=ev;connected=true;}
	R emit_event(const A& arg){ R ret; if(connected) return
m_handler(&m_t,arg); else return ret;}
	bool isConnected(){ return connected; }
private:
	bool connected;
	funct m_handler;
	T m_t;
};
template<class T> // T rappresenta la classe che contiene la funzione
membro da chiamare
class button
{
public:
	button(){}
	~button(){}
	//on_click registra	una fuzione membro della classe T, che accetta
una string, e restituisce bool
	event<bool,T,string> on_click; 
	bool click(string s)
	{
		if(on_click.isConnected())
			return on_click.emit_event(s); //	richiamo l'evento se connesso
		else return false;
	}
};
class handler
{
public:
	handler(){}
	~handler(){}
	bool print(string s){cout<<"handler::print -> "<<s<<endl;return
true;}
};
int main()
{
	button<handler> but; //	la classe button viene istanziata con la
classe che gestira' l'evento
	handler h1;
	//la funzione membro "print" dell'istanza h1 di handler viene
registrata per la gestione dell'evento
	but.on_click.connect(h1,mem_fun1(&handler::print));	
	but.click("pippo"); //	genero l'evento --> richiamera'
h1.print("pippo");
	return 0;
}

 rispetti la firma della funzione.
Ti servirebbero i delegate (C#) o le closure (BCB/Delphi).
Il C++ non possiede quei costrutti, ma con un po' di fantasia è possibile
emularli. Ci sono state un paio di discussioni su questo newsgroup, e sono
state elaborate alcune soluzioni, più o meno conformi allo standard e più
o meno efficienti.
http://groups.google.com/groups?selm=3BB2EA9D.A7437071%40divalsim.it
http://groups.google.com/groups?selm=jC9i8.49080%24Ns4.2067286%40news2.tin.it
Max

 potra' richiamare in seguito...
se riesci in qualche modo a procurarti "Modern C++ Design" di 
Alexandrescu ti consiglio vivamente di leggere il capitolo 5 
("Generalized Functors") che tratta proprio di quello che chiedi. 
Altrimenti ti puoi accontentare di studiare il sorgente della libreria a 
corredo del libro: la libreria si chiama Loki e la trovi alla home page 
dell'autore (una ricerca su google con "Andrei Alexandrescu home page" 
dovrebbe aiutarti).
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it