2011-07-08 5 views
5

¿Cómo creo una función lambda utilizando boost o stl para que coincida con el parámetro boost::function esperado por F en el tercer fragmento de código en main?¿Cómo creo una función lambda para que coincida con un parámetro boost :: function sin usar C++ 0x?

#include <iostream> 
#include <boost/function.hpp> 

void F(int a, boost::function<bool(int)> 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); 

    // How can I do it in place without C++0x 
    F(123, /* create a lambda here to match */); 
} 

No puedo usar C++ 0x y me gustaría evitar crear varias funciones separadas. Puedo usar algo diferente que boost::function si eso ayuda, mi prioridad es crear el lambda de manera sucinta.

+1

Me pregunto ... ¿cómo es que no puedes usar C++ 0x pero quieres usar 'std :: function' que es parte de C++ 0x? Por cierto, eche un vistazo a la biblioteca boost lambda, ya que podría ser lo que está buscando. –

+2

@David: boost :: function not std :: function –

Respuesta

7
#include <functional> // STL 
#include <boost/lambda/lambda.hpp> // Boost.Lambda 
#include <boost/spirit/include/phoenix_core.hpp>  // Boost.Pheonix 
#include <boost/spirit/include/phoenix_operator.hpp> // Boost.Pheonix also 

... 

// Use STL bind without lambdas 
F(0, std::bind2nd(std::equal_to<int>(), 0)); 
F(123, std::bind2nd(std::equal_to<int>(), 0)); 

// Use Boost.Lambda (boost::lambda::_1 is the variable) 
F(0, boost::lambda::_1 == 0); 
F(123, boost::lambda::_1 == 0); 

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

Es posible que desee añadir un poco de using namespace para simplificar el código.

Boost.Lambda es estrictamente para definir los funtores en línea con un C++ - como sintaxis, mientras que Boost.Phoenix es un lenguaje de programación funcional construido encima de C++ abusar (☺) su sintaxis y la capacidad de cálculo en tiempo de compilación. Boost.Phoenix es mucho más poderoso que Boost.Lambda, pero el primero también toma mucho más tiempo en compilarse.

+0

Además, a partir de Boost 1.47, Boost.Lambda está oficialmente en desuso en favor de Boost.Phoenix v3. Es decir, Boost.Lambda ahora es una biblioteca heredada, no destinado para el uso en el nuevo código. – ildjarn

-1

Respuesta corta: no.

C++ 0x Las lambdas se inventaron para hacer exactamente lo que usted desea. En realidad, no son más que una forma de hacer Increment en el siguiente ejemplo anónimo/en línea. Es el único forma de obtener una función anónima en cualquiera de los C++ estándar.

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

void foo (const std :: vector <int> & 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 
} 

Lo único mágico en lambdas es que su tipo no se puede escribir, pero el compilador puede unir el tipo oculto interno para std::function (o incluso un puntero de función C bajo algunas circunstancias).

Estoy publicando el código anterior porque creo que su pregunta podría no significar lo que cree que hace. Lambdas son definitivamente una cosa de C++ 0x pero en este ejemplo, Increment es un cierre. (Algunos dirían que solo se convierte en cierre si lo devuelves y la variable encuadernada escapa del contexto en el que estaba enlazado, eso es poco, pero es lo que, por ejemplo, hace Javascript).

¿Tienes preguntas sobre lambdas o cierres?

+0

¿Por qué se bajó este valor? El código es sólido. EDITAR: Excepto que el constructor 'Increment' debería tomar' int & 'not an' int'. –

+0

@Mike: Probablemente porque hay múltiples bibliotecas lambda para C++ 03. (No perdoné.) – ildjarn

+0

Creo que estamos en desacuerdo sobre lo que significa "lambda". Las "bibliotecas lambda" de C++ 03 pueden * verse * como lambdas, debido al trabajo inteligente y difícil de los autores, pero son * no * lambdas. No puedo evitar sentirme un poco hard-done-by :-( – spraff

Cuestiones relacionadas