C++11 lambdas de Pointeur de Fonction
Je commence à développer des applications à l'aide de C++11 lambdas, et la nécessité de convertir certains types de pointeurs de fonction. Cela fonctionne parfaitement dans GCC 4.6.0:
void (* test)() = []()
{
puts("Test!");
};
test();
Mon problème est quand j'ai besoin d'utiliser la fonction ou de la méthode des variables locales au sein de la lambda:
const char * text = "test!";
void (* test)() = [&]()
{
puts(text);
};
test();
G++ 4.6.0 donne la fonte de code d'erreur:
main.cpp: In function 'void init(int)':
main.cpp:10:2: error: cannot convert 'main(int argc, char ** argv)::<lambda()>' to 'void (*)()' in initialization
Si l'utilisation auto, cela fonctionne bien:
const char * text = "Test!";
auto test = [&]()
{
puts(text);
};
test();
Ma question est: comment puis-je créer un type pour un lambda [&]? Dans mon cas, je ne peux pas utiliser la STL std::function (parce que mon programme n'utilise pas de C++ RTTI et les EXCEPTIONS à l'exécution), et Il est simple de mise en œuvre de la fonction pour résoudre ce problème?
Vous ne pouvez pas convertir une capture lambda à un pointeur de fonction. Expliquez ce que vous essayez de faire.
Vous avez expliqué la (mal) une tentative de solution, tout en décrivant ce que vous en réel problème. S'il vous plaît dites-nous ce que vous problème réel est
J'ai fait quelques corrections à ma réponse après avoir regardé une mise en œuvre de
std::function
. Vous devriez probablement prendre un coup d'oeil.
OriginalL'auteur Raphael Basso | 2012-06-12
Vous devez vous connecter pour publier un commentaire.
Alors vous pouvez avoir besoin d'écrire votre propre équivalent à
std::function
.L'habitude de la mise en œuvre de type effacement de
std::function
n'a pas besoin de RTTI pour la plupart de ses fonctionnalités; il fonctionne par le biais virtuel régulier des appels de fonction. Afin d'écrire votre propre version, c'est faisable.En effet, les seules choses en
std::function
que besoin RTTI sont lestarget_type
ettarget
fonctions, qui ne sont pas les fonctions les plus utiles dans le monde. Vous pourriez être en mesure de l'utiliser justestd::function
sans appel de ces fonctions, en supposant que l'application que vous utilisez n'a pas besoin de RTTI pour ses affaires..Généralement, lorsque vous désactivez la gestion des exceptions, le programme de simplement s'arrête et les erreurs lors de la rencontre d'un
throw
déclaration. Et puisque la plupart des exceptions qu'unstd::function
serait émettent ne sont pas le genre de chose que vous seriez en mesure de récupérer à partir de (l'appel d'un videfunction
, à court de mémoire, etc), vous pouvez probablement utiliser simplementstd::function
.OriginalL'auteur Nicol Bolas
Seulement lambdas avec pas de capture peut être converti en un pointeur de fonction. C'est une extension de lambdas que pour ce cas particulier [*]. En général, les lambdas sont des objets de fonction, et vous ne pouvez pas convertir un objet de fonction à une fonction.
L'alternative pour les lambdas qui ont un état (capture) est d'utiliser
std::function
plutôt qu'un simple pointeur de fonction.[*]: Si le lambda qui détient de l'état pourraient être convertis à un pointeur de fonction, où l'état pourrait-il être maintenu? (Notez qu'il peut y avoir plusieurs instances d'un particulier lambda, chacun avec son propre état qui doit être maintenu séparément)
const int c; [c](int i)->int{return i*c;}
il ferait beaucoup de sens...Elle dépend, d'envisager
std::function<int(int)> f(int x) { const int c = x; return [c](int i){return i*c;} };
. Le foncteur retourné parf
dépend de l'argument et a donc de l'état. Seulement si la capture a été une constante de l'expression, il pourrait être pris en compte dans une plaine de la fonction.Hm. Je suis d'accord, en partie. Il peut encore être retiré, mais la solution peut être coûteux, comme le programme aurait besoin de copier le code de la fonction lambda à chaque fois avec la modification de la valeur de c dans le code de la fonction. (ou si pas de copier l'intégralité du code de la fonction, il doit faire planifié sauts, où les sauts peuvent ralentir les choses.)
Je ne pense pas que cela peut même être fait, considèrent que l'argument de la fonction peut être une valeur d'exécution (lire à partir de la saisie de l'utilisateur par exemple) et vous ne pouvez pas créer des fonctions en fonction des valeurs de l'exécution. Vous pouvez imaginer le stockage de la valeur de côté, mais de s'assurer que les différents lambdas ne pas obtenir leurs valeurs tabassé lors d'une nouvelle lambda est créé, ce qui nécessiterait la mémoire dynamique dont l'utilisation serait intraitable pour le compilateur...
Essayé sur les deux VS2013 et xcode6. Lambda sans la saisie peut être converti pointeur de fonction, merci de le faire remarquer.
OriginalL'auteur David Rodríguez - dribeas
Comme il a été mentionné, seuls les lambdas qui captent rien ne peut être converti à des pointeurs de fonction.
Si vous ne souhaitez pas utiliser ou écrire quelque chose comme std::function, puis une autre alternative est de passer en paramètre les choses d'une autre façon. Vous pouvez même créer une structure pour les tenir.
Une autre alternative est d'utiliser global/static/thread_local/constexpr variables qui ne nécessitent pas la prise de vue.
OriginalL'auteur bames53
Vous pouvez utiliser
std::function
, il n'a pas besoin de "runtime". Sinon, regardez ici pour une esquisse de la façon de mettre en œuvre desstd::function
vous-même.OriginalL'auteur jpalecek