web-dev-qa-db-fra.com

Passer des fonctions Lambda C ++

J'ai cherché partout cela, et je ne semble pas être en mesure de trouver une réponse directe. Certaines sources disent que ce n'est pas possible, mais cela ne fait que poser plus de questions pour moi, que j'expliquerai plus loin.

Voici donc la situation. Supposons que j'ai une classe de conteneur personnalisée avec une fonction de sélection comme ci-dessous (ce n'est qu'un exemple):

template <typename T>
class Container {
public:
    // ...

    Container<T> select(bool (*condition)(const T&)) const;

    // ...
};

Comme vous pouvez le voir, la fonction select prend un pointeur sur une fonction condition. Il s'agit d'une fonction qui définit les éléments à sélectionner. Ainsi, un exemple d'utilisation de ceci serait quelque chose de similaire à:

bool zero_selector(const int& element) {
    return (element == 0); // Selects all elements that are zero
}

Maintenant, si j'ai un conteneur rempli, disons s = { 1, 1, 0, 0, 1, 0, 1, 0 }, Je pourrais sélectionner un sous-ensemble de ceux-ci qui ne contiendrait que des zéros en utilisant:

t = s.select(&zero_selector); // t = { 0, 0, 0, 0 }

Comme vous pouvez le voir, c'est un peu maladroit. Les fonctions lambda rendraient cela beaucoup plus élégant, alors je pourrais l'utiliser (je ne suis pas sûr que ce soit la bonne syntaxe), par exemple:

t = s.select([&] (int x) -> bool { return (x == 0); });

Ma question est, est-ce possible? Dans l'affirmative, quel devrait être mon prototype de fonction pour que Container::select() accepte un lambda comme l'un de ses paramètres?

Si ce n'est pas possible, alors comment quelque chose comme std::for_each Est-il implémenté qui peut utiliser une expression lambda comme l'un de ses arguments? Toutes les ressources qui expliqueraient clairement cela seraient très appréciées. Tout ce que j'ai trouvé ne donne que des exemples de fonctions lambda et l'utilisation de std::function<> Pour les passer en paramètres, mais rien n'explique comment std::for_each Fonctionne avec les fonctions lambda.

Je voudrais noter que ce code n'est pas compilé/testé tel quel. C'est uniquement à des fins de démonstration. J'ai essayé de mettre en œuvre les mêmes principes dans le projet réel et cela ne fonctionne pas.

33
Zeenobit

Vous devez déclarer votre lambda sans état (c'est-à-dire avec une spécification de capture vide [](int x)-> bool {...}) pour qu'il soit convertible en pointeur de fonction.

17
MSN

Il n'est pas nécessaire d'ajouter le réflexe [&]-Capturer. Votre lambda n'en a pas besoin:

[] (int x) -> bool { return (x == 0); }

Les lambdas sans capture sont convertibles en le pointeur de fonction correspondant, donc cela devrait fonctionner hors de la boîte.

Cela dit, vous devez probablement déclarer la fonction select pour accepter std::function, dans lequel tous les lambdas sont convertibles, capturant ou non:

Container<T> select(std::function<bool(const T&)> predicate) const;
41
Kerrek SB