7
votes

Comment mettre en cache un lambda en C ++ 0x?

J'essaie de travailler avec Lambda en C ++ après avoir utilisé beaucoup de choses en C #. J'ai actuellement un tuple Boost (c'est la version vraiment simplifiée).

tuplearray[i] = FooTuple([](string bar, int rc, bool eom) -> {return shared_ptr<Foo>(new Foo(bar, rc, eom));});


0 commentaires

3 Réponses :


7
votes

L'opérateur -> définit le type de retour de la Lambda, dans le cas d'aucun type de retour, il peut être omis. De plus, si cela peut être déduit par le compilateur, vous pouvez omettre le type de retour. Comme Terry a dit, vous ne pouvez pas attribuer une Lambda à un pointeur de fonction (GCC permet de conversion de cette conversion), mais vous pouvez utiliser STD :: Fonction.

Ce code fonctionne sur GCC et VC10 (Supprimer TR1 / de l'Inclus pour VC ): xxx


14 commentaires

Ne fonctionnera pas - une expression Lambda n'est pas un pointeur de fonction. C'est (conceptuellement) une classe de fonctions anonymes.


D'après ce que j'ai lu, le compilateur devrait pouvoir le comprendre et me laissera savoir si cela ne peut pas. Je vais y jeter un coup d'oeil. Merci.


@Terry Hmm c'est impair, car ce code compile et fonctionne sur GCC en ce moment.


@Steve, cela pourrait simplement être des implémentations à la traîne de la norme, c'est toujours un avantage de saignement même si la norme a été ratifiée.


@JOSHPERRY - Je peux vérifier que cela ne fonctionne pas sur le compilateur Intel. Eh bien, je suppose que Lambda est comme l'ouest sauvage en ce moment.


VC10 n'a pas encore de tuple, alors je ne peux donc pas le tester exactement comme écrit, mais je fais un exemple similaire essayant d'attribuer une Lambda à un pointeur de fonction, il ne compile pas (impossible de convertir de l'espace de noms anonymes :: à fonctionCointype). Peut-être que tuple ou GCC fait quelque chose de spécial, idk.


En fait, il a un tuple, et ce même code fonctionne bien sur VC10, je viens de l'essayer.


Vous me confondez quand vous dites "Même code". Votre code d'origine ne compile pas sur VC10, pour la raison pour laquelle j'ai dit ci-dessus (ne peut pas convertir Lambda en pointeur de fonction). J'avais tort à propos de Tuple ne pas être en VC10, cependant. Votre version mise à jour (utilisant STD :: Fonction) compile. Je ne suis pas un avocat de langue, mais je pense que VC est correct ici pour ne pas effectuer cette conversion.


Terry, tu as raison. GCC a en fait un opérateur de conversion qui ne fait pas partie du brouillon standard. Donc, mon premier code de code ne doit pas compiler sur un compilateur conformaire des normes.


"L'opérateur -> définit le type de retour de la Lambda, dans le cas d'aucun type de retour, il peut être omis" - il peut également être omis lorsque le type de retour peut être déduit; "Dans votre cas, vous devez définir le type de retour comme partagé_ptr " - il ne le fait pas, car le corps de son lambda est une seule déclaration déclaration , qui est précisément le contexte dans lequel retour le type peut être déduit.


@JOSHPERRY - Merci pour tout le temps et les efforts que vous avez mis dans cette réponse.


Merci Pavel, pour une raison quelconque, l'inférence ne travaillait pas pour moi au début, mais avec mon dernier code, cela fonctionne, je vais donc mettre à jour la réponse. Steve, avez-vous eu le travail sur le compilateur Intel?


Oui, tout fonctionne comme prévu avec votre dernier exemple. Sa plus rapide qu'un pointeur de fonction aussi!


C ++ 0X a la conversion en pointeur de fonction pour non-capture de Lambdas maintenant, voir §5.1.2 / 6 dans la FCD.



1
votes

Vous devriez pouvoir stocker une Lambda dans une fonction STD :: Fonction. Dans votre exemple, essayez de le stocker dans un

std :: Fonction (STD :: String, int, Bool)>

N'oubliez pas d'auto (bien que vous ne puissiez pas créer un tableau d'auto, etc.).


5 commentaires

Avez-vous de la chance de savoir l'en-tête de STD :: Fonction? Google ne m'ade pas ...


Aussi, qu'entendez-vous par auto?


std :: fonction est dans auto est une autre fonctionnalité C ++ 0x


Bah, son échec sur une erreur de boost folle sur l'instanciation du modèle. Merci


Je ne sais pas sur tout le monde, mais je devais désactiver certaines des fonctionnalités C ++ 0X de Boost (il y a #defines pour les activer / les désactiver).



3
votes

de Blog Visual C ++

J'ai mentionné de stocker Lambdas dans TR1 :: Fonctions. Mais tu ne devrais pas faire que si c'est nécessaire, comme TR1 :: La fonction a des frais généraux. Si vous voulez réutiliser une lambda ou simplement Voulez-vous donner un nom, vous pouvez utiliser Auto.


6 commentaires

auto n'est d'aucune aide ici, car il ne peut pas être utilisé comme paramètre de type pour un conteneur comme vecteur .


C'est vrai, je voulais juste mentionner les frais généraux.


Sur le compilateur Intel, la Lambda avec fonction est toujours plus rapide que la mise en cache d'un pointeur de fonction. Environ 3 à 5% de mes tests. Merci pour le conseil.


@PAVEL: Vous pouvez utiliser Auto pour nommer un Lambda, puis déclencheur sur ce nom pour obtenir le type d'objet Lambda. Ce dernier peut être utilisé comme paramètre de type de modèle.


@sellibitze: à ce moment-là, vous pouvez aussi bien définir T id pare_type (t) , puis l'écrire comme déclenle ([[] ([] () ...)) . Sans doute, pour tout l'effort, il est plus facile d'écrire un foncteur :)


@Pavel: Quel serait le point de faire ça? Ce type sera inutile car lorsque vous écrivez la même expression de la Lambda pendant une seconde fois, cela aura un type différent, car ils ont des types uniques.