2010-12-10 35 views
3

Je suis à ce moment vraiment ennuyeux dans le développement de ma bibliothèque, où je veux construire une classe basée sur un identificateur de message Windows et les arguments WPARAM et LPARAM. Le prototype de ces fonctions est trivial:Y a-t-il un avantage/inconvénient à utiliser des délégués de fonctions sur lambdas dans une collection?

boost::shared_ptr<EventArgs>(const UINT& _id, const WPARAM& _w, const LPARAM& _l); 

Pour chaque message windows, je vais avoir une fonction de cette nature.

Maintenant, ce que je fais actuellement utilise la bibliothèque FastDelegate pour faire mes délégués. Ceux-ci sont stockés dans une carte thusly:

typedef fastdelegate::FastDelegate3<const UINT&, const WPARAM&, const LPARAM&, boost::shared_ptr<EventArgs> > delegate_type; 
typedef std::map<int, delegate_type> CreatorMap; 

Et quand un message de fenêtres doit avoir une EventArg classe dérivée de créé, il est un cas simple de regarder le délégué approprié, invoquer et retourner l'instance nouvellement créée joliment contenu dans un shared_ptr.

boost::shared_ptr<EventArgs> make(const UINT& _id, const WPARAM& _w, const LPARAM& _l) const 
{ 
    MsgMap::const_iterator cit(m_Map.find(_id)); 
    assert(cit != m_Map.end()); 
    boost::shared_ptr<EventArgs> ret(cit->second(_w, _l)); 
    return ret; 
}; // eo make 

Tout fonctionne correctement. Mais alors je pensais, plutôt que d'avoir tous ces délégués autour, pourquoi ne pas profiter de lambdas en C++ 0x? Alors, je prototypé rapidement les éléments suivants:

typedef std::map<int, std::function<boost::shared_ptr<EventArgs>(const WPARAM&, const LPARAM&)> > MapType; 
typedef MapType::iterator mit; 

MapType map; 
map[WM_WHATEVER] = [](const WPARAM& _w, const LPARAM& _l) { /* create appropriate eventargs class given parameters */ }; 
map[WM_ANOTHER] = ....; 
// and so on 

Encore une fois, il est facile de rechercher et invoquer:

mit m = map.find(WM_PAINT); 
boost::shared_ptr<EventArgs> e(m->second(_wParam, _lParam)); 
// dispatch e 

Y at-il un avantage à utiliser lambdas de cette façon? Je sais que les frais de recherche du bon délégué/lambda seront les mêmes (car les deux types de cartes sont saisis avec un int), mais j'ai l'intention d'envoyer mes messages de la wndProc dans ma sympathique façon conviviale C++ aussi efficacement que possible. Mon instinct est que lambdas sera plus rapide, mais malheureusement je manque d'expérience dans la compréhension des optimisations du compilateur pour faire un jugement sur ce point, d'où ma question ici :) Oh, et en accord avec le sujet de la question, y at-il un gotchas/quelque chose que je n'ai pas pensé?

Répondre

2

Je vois deux différences réelles ici:

Le premier est la façon dont vous stockez le rappel: Soit le délégué rapide ou std :: fonction. Ce dernier est basé sur boost :: function, et les délégués rapides ont été spécialement conçus pour surpasser ceux-ci. Cependant, std :: function est conforme à la norme, alors que les délégués rapides ne le sont pas.

L'autre différence est la façon dont vous configurez votre code, et je vois un net avantage pour lambdas ici. Vous pouvez écrire le code exact exactement là où cela importe, vous n'avez pas besoin de définir une fonction distincte qui ne sert qu'à un objectif de niche. Si vous voulez de la vitesse brute - les délégués rapides gagnent probablement (mais vous devriez benchmark, si c'est un argument), mais si vous voulez la lisibilité et la conformité standard, allez avec std :: function et lambdas.

+0

merci pour votre réponse et vous avez raison. 'fastdelegate' (que j'ai déjà utilisé) est, en effet, très bon en termes de performances. Mais encore une fois, comme vous l'avez souligné, en utilisant lambdas, je peux créer une carte-initialisation très lisible avec des fonctions anonymes qui, comme vous le signalez également, servent un seul but. Et comme vous le dites, je ne sais pas à ce stade si la performance va être un problème! –