5 votes

Comment puis-je créer une fonction lambda pour correspondre à un paramètre boost::function sans utiliser C++0x?

Comment créer une fonction lambda en utilisant boost ou la STL pour correspondre au paramètre boost::function attendu par F dans le troisième extrait de code de main ?

#include 
#include 

void F(int a, boost::function f) {
    std::cout << "a = " << a << " f(a) = " << f(a) << std::endl;
}

bool G(int x) {
    return x == 0;
}

int main(int arg, char** argv) {
    // C++0x
    F(123, [](int i) { return i==0; } );

    // Using seperate function
    F(0, &G);

    // Comment puis-je le faire en place sans C++0x
    F(123, /* créer une lambda ici pour correspondre */);
}

Je ne peux pas utiliser C++0x et je préfère éviter de créer plusieurs fonctions séparées. Je peux utiliser autre chose que boost::function si cela aide, ma priorité est de créer la lambda de manière succincte.

7voto

KennyTM Points 232647
#include     // STL
#include    // Boost.Lambda
#include      // Boost.Phoenix
#include  // Boost.Phoenix also

...

// Utilisez la liaison STL sans lambdas
F(0, std::bind2nd(std::equal_to(), 0));
F(123, std::bind2nd(std::equal_to(), 0));

// Utilisez Boost.Lambda (boost::lambda::_1 est la variable)
F(0, boost::lambda::_1 == 0);
F(123, boost::lambda::_1 == 0);

// Utilisez Boost.Phoenix
F(0, boost::phoenix::arg_names::arg1 == 0);
F(123, boost::phoenix::arg_names::arg1 == 0);

Vous voudrez peut-être ajouter quelques using namespace pour simplifier le code.

Boost.Lambda est strictement destiné à définir des foncteurs en ligne avec une syntaxe similaire à C++, tandis que Boost.Phoenix est un langage de programmation fonctionnelle construit sur C++ en abusant (☺) de sa syntaxe et de sa capacité de calcul au moment de la compilation. Boost.Phoenix est beaucoup plus puissant que Boost.Lambda, mais ce dernier prend également beaucoup plus de temps à compiler.

-1voto

spraff Points 10492

Réponse courte : non.

Les lambdas C++0x ont été inventés pour faire exactement ce que vous voulez. Ils ne sont en fait rien de plus qu'un moyen de rendre Increment dans l'exemple ci-dessous anonyme/en ligne. C'est le seul moyen d'obtenir une fonction anonyme dans l'un des C++ standards.

struct Increment {
    int & arg;
    Increment (int a) : arg (a) {}
    void operator () (int & i)
        {arg += i;}
};

void foo (const std :: vector  & buffer, int x)
{
    std :: for_each (
        buffer .begin (), buffer .end (),
        Increment (x)); // C++98

    std :: for_each (
        buffer .begin (), buffer .end (),
        [&x] (int & i) {x += i;}); // C++0x
}

La seule chose magique des lambdas est que leur type ne peut pas être écrit mais le compilateur peut lier le type interne caché à std::function (ou même à un pointeur de fonction C dans certaines circonstances).

Je poste le code ci-dessus car je pense que votre question pourrait ne pas signifier ce que vous croyez. Les lambdas sont définitivement une chose C++0x mais dans cet exemple, Increment est une fermeture. (Certains diraient que cela ne devient une fermeture que si vous la renvoyez et que la variable liée échappe au contexte dans lequel elle était liée - c'est du pinaillage mais c'est ce que fait, par exemple, Javascript).

Votre question concerne-t-elle les lambdas ou les fermetures?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X