Domanda

Ho una classe con una funzione "Allega" che accetta un oggetto funzione e lo memorizza in una collezione. La classe stessa è templato sulla firma della funzione. Qualcosa di simile a questo:

template<class Signature>
class Event
{
public:

 void Attach(boost::function<Signature> signature)
 {
  MySignatures.push_back(signature);
 }

private:

 std::list<boost::function<Signature>> MySignatures;
};

Per dimostrare l'utilizzo, si consideri la seguente classe:


class Listening
{
public:

 int SomeFunction(int x, int y, int z); 
};

Per passare la funzione Listening in Event, avrei bisogno di scrivere:


 Event<int(int, int, int)> myEvent;
 Listening myListening;

 myEvent.Attach(boost::bind(boost::mem_fn(&Listening::SomeFunction), &myListening, _1, _2, _3));

Così, invece di farlo per ogni singolo caso, che può essere soggetto ad errori, scrivo un insieme di macro, come segue:


 #define EventArgument0(x, y)  boost::bind(boost::mem_fn(x), y)
 #define EventArgument1(x, y)  boost::bind(boost::mem_fn(x), y, _1)
 #define EventArgument2(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2)
 #define EventArgument3(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3)
 #define EventArgument4(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3, _4)

 etc.

e quindi posso scrivere:


 myEvent.Attach(EventArgument3(&Listening::SomeFunction, &myListening));

che è molto più facile da leggere (credo). Ora alla mia domanda: come posso invece scrivere:


 myEvent.Attach(EventArgument(&Listening::SomeFunction, &MyListening));

o meglio ancora:


 myEvent.Attach(&Listening::SomeFunction, &myListening);

, in modo tale che l'evento Fissare magicamente si legano in modo corretto con il numero appropriato di argomenti contenuta nel (in questo esempio, int(int, int, int))? Sono aperto a qualsiasi modello di magia meta-programmazione che avete in mente qui.

Grazie.

Modifica: si scopre non ho bisogno di boost::mem_fn qui, perché boost::bind equivale, quindi nel mio macro posso usare:

bind(&MyClass::Hello, myClass, _1, _2, _3);

, invece di:

bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3);

La questione rimane però: come passare &MyClass::Hello alla classe di evento e l'uso modello sovraccarico per gestire il _1, _2, _3, ecc implicito il prototipo di funzione utilizzata al modello della classe Event

È stato utile?

Soluzione

sovraccarico Attach per un diverso numero di parametri nella funzione membro:

template<typename R,typename T,typename U>
void Attach(R (T::*pmf)(),U* p))
{
    Attach(boost::bind(pmf,p));
}

template<typename R,typename T,typename U,typename A1>
void Attach(R (T::*pmf)(A1),U* p))
{
    Attach(boost::bind(pmf,p,_1));
}

template<typename R,typename T,typename U,typename A1,typename A2>
void Attach(R (T::*pmf)(A1,A2),U* p))
{
    Attach(boost::bind(pmf,p,_1,_2));
}

Se avete bisogno di gestire le funzioni di membro const troppo, allora avrete bisogno di una seconda serie di sovraccarichi.

Altri suggerimenti

Fare Attach() un modello ti permettono di fare ciò che si sta puntando. Il codice diventa disordinato, ma ti permette di chiamare nel modo desiderato.

template<typename A1>
void Attach(A1 a1);

template<typename A1, typename A2>
void Attach(A1 a1, A2 a2);

template<typename A1, typename A2, typename A3>
void Attach(A1 a1, A2 a2, A3 a3);

template<typename A1, typename A3, typename A4>
void Attach(A1 a1, A2 a2, A3 a3, A4 a4);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top