Question

J'ai une classe avec une fonction « Joindre » qui accepte un objet de fonction et la stocke dans une collection. La classe elle-même est templated sur la signature de la fonction. Quelque chose comme ceci:

template<class Signature>
class Event
{
public:

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

private:

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

Pour démontrer l'utilisation, pensez à la classe suivante:


class Listening
{
public:

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

Pour passer la fonction sur Listening dans Event, il me faudrait écrire:


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

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

Ainsi, au lieu de le faire pour chaque cas qui peut être sujette à l'erreur, j'écris un ensemble de macros, comme suit:


 #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.

et puis je peux écrire:


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

ce qui est beaucoup plus facile à lire (je pense). Maintenant, à ma question: comment puis-je écrire à la place:


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

ou mieux encore:


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

, de sorte que l'événement attach sera correctement par magie se lier avec le nombre approprié d'arguments figurant dans (dans cet exemple, int(int, int, int))? Je suis ouvert à toute la magie méta-programmation modèle que vous avez à l'esprit ici.

Merci.

Edit: il se trouve que je ne ai pas besoin boost::mem_fn ici, parce que boost::bind est équivalent, dans ma macro je peux utiliser:

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

, au lieu de:

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

La question reste cependant: comment passer &MyClass::Hello au modèle classe d'événement et utiliser la surcharge pour gérer la _1, _2, _3, etc. sous-entendus par le prototype de fonction utilisée à le modèle de la classe Event

Était-ce utile?

La solution

Attach surcharge pour des nombres différents de paramètres de la fonction de membre:

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));
}

Si vous avez besoin pour gérer les fonctions membres de const aussi vous aurez besoin d'un deuxième jeu de surcharges.

Autres conseils

Faire Attach() un modèle vous permettra de faire ce que vous visez pour. Le code devient malpropre mais nous allons vous l'appelez comme vous le souhaitez.

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top