¿Cómo declarar una función que acepta una lambda?

4 minutos de lectura

Leí en Internet muchos tutoriales que explicaban cómo usar lambdas con la biblioteca estándar (como std::find), y todos fueron muy interesantes, pero no pude encontrar ninguno que explicara cómo puedo usar una lambda para mis propias funciones.

Por ejemplo:

int main()
{
    int test = 5;
    LambdaTest([&](int a) { test += a; });

    return EXIT_SUCCESS;
}

como debo declarar LambdaTest? ¿Cuál es el tipo de su primer argumento? Y luego, ¿cómo puedo llamar a la función anónima pasándole, por ejemplo, “10” como argumento?

avatar de usuario
sepp2k

Dado que probablemente también desee aceptar punteros de función y objetos de función además de lambdas, probablemente querrá usar plantillas para aceptar cualquier argumento con un operator(). Esto es lo que hacen las funciones estándar como find. Se vería así:

template<typename Func>
void LambdaTest(Func f) {
    f(10);
}

Tenga en cuenta que esta definición no utiliza ninguna característica de c++0x, por lo que es completamente compatible con versiones anteriores. Solo la llamada a la función mediante expresiones lambda es específica de c++0x.

  • En caso de errores, los mensajes de error serán difíciles de entender.

    – liori

    30 de mayo de 2010 a las 12:40

  • Depende si es lo mejor. Este usa una plantilla, y el otro no. Esto significa que la función ya no puede ser virtual y no se puede definir por separado en el archivo cpp. std::function también es perfectamente capaz de tomar tipos de clase de objeto de función, aunque es un poco más lento cuando se llama. Pero esa diferencia es insignificante para la mayoría de las aplicaciones 🙂

    – Johannes Schaub – litb

    30 de mayo de 2010 a las 12:41


  • “mejor” está en el ojo del espectador 🙂 esta respuesta usa un functor lo cual es bueno, pero en realidad no responde la pregunta original (y lo que me llevó aquí) que era “¿cómo uso una lambda para mis propias funciones?”. Además, las plantillas tienen su propio conjunto de problemas, que la respuesta con std::function no.

    – Marco Massenzio

    17 de abril de 2017 a las 3:30

  • @Marco Esta respuesta no requiere que uses funciones, te permite usar lo que quieras, incluidas las lambdas.

    – sepp2k

    17 de abril de 2017 a las 10:09

Si no desea crear una plantilla para todo, puede hacer lo siguiente:

#include<functional> 

void LambdaTest (const std::function <void (int)>& f)
{
    ...
}

  • Esta sintaxis en realidad me permite guardar la variable de función para llamarla más tarde, ¿verdad? Por ejemplo, quería implementar una función que permitiera ejecutar consultas de base de datos asíncronas, donde la lambda actúa como una devolución de llamada. (Por supuesto que no podría acceder a los cierres por referencia)

    – Tomás Bonini

    30 de mayo de 2010 a las 12:52

  • ¿No es más idiomático pasar funciones por valor?

    – fredo desbordamiento

    30 de mayo de 2010 a las 12:53

  • @Andreas Bonini: Sí, si guarda en std::function (no es una referencia), usted hace una copia de f. Sin embargo, no estoy seguro de cómo lambda/closures manejan las referencias cuando el objeto al que se hace referencia queda fuera del alcance, probablemente UB. @FredOverflow: Tengo entendido que std::function no es un objeto trivial, especialmente cuando se envuelven lambdas. Probablemente sea mejor hacer referencia a él para evitar copias innecesarias.

    usuario319799

    30 de mayo de 2010 a las 13:01


  • Si su lambda captura la pila por valor, entonces sí, la lambda puede sobrevivir a esas variables y continuará guardando copias de ellas. Si captura por referencia tendrás un problema.

    – Kate Gregorio

    30 de mayo de 2010 a las 13:41

  • Tendremos que copiarlo dentro de la función, por lo que no tiene sentido copiarlo a medida que se pasa en

    – Casebash

    2 de mayo de 2011 a las 4:57

Me gustaría contribuir con este ejemplo simple pero que se explica por sí mismo. Muestra cómo pasar “cosas invocables” (funciones, objetos de función y lambdas) a una función oa un objeto.

// g++ -std=c++11 thisFile.cpp

#include <iostream>
#include <thread>

using namespace std;

// -----------------------------------------------------------------
class Box {
public:
  function<void(string)> theFunction; 
  bool funValid;

  Box () : funValid (false) { }

  void setFun (function<void(string)> f) {
    theFunction = f;
    funValid = true;
  }

  void callIt () {
    if ( ! funValid ) return;
    theFunction (" hello from Box ");
  }
}; // class

// -----------------------------------------------------------------
class FunClass {
public:
  string msg;
  FunClass (string m) :  msg (m) { }
  void operator() (string s) {
    cout << msg <<  s << endl; 
  }
};

// -----------------------------------------------------------------
void f (string s) {
  cout << s << endl;
} // ()

// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
  pf( "call_it: hello");
} // ()

// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
  pf( "call_it1: hello");
} // ()

// -----------------------------------------------------------------
int main() {

  int a = 1234;

  FunClass fc ( " christmas ");

  f("hello");

  call_it ( f );

  call_it1 ( f );

  // conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );

  call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );

  Box ca;

  ca.callIt ();

  ca.setFun (f);

  ca.callIt ();

  ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );

  ca.callIt ();

  ca.setFun (fc);

  ca.callIt ();

} // ()

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad