examples - C++ 11 ¿Cambiar `auto` Lambda a un Lambda diferente?
lambda examples c++ (5)
Digamos que tengo la siguiente variable que contiene un lambda:
auto a = [] { return true; };
Y quiero a
regreso false
tarde. ¿Podría hacer algo en la línea de esto?
a = [] { return false; };
Esta sintaxis me da los siguientes errores:
binary ''='' : no operator found which takes a right-hand operand of type
''main::<lambda_a7185966f92d197a64e4878ceff8af4a>'' (or there is no acceptable conversion)
IntelliSense: no operator "=" matches these operands
operand types are: lambda []bool ()->bool = lambda []bool ()->bool
¿Hay alguna manera de lograr algo como esto? Me gustaría cambiar la variable auto
a una lambda diferente. Soy un principiante, por lo que puede que me falte algo de conocimiento sobre auto
o lambdas. Gracias.
Cada expresión lambda crea un nuevo tipo único, por lo que el tipo de su primer lambda es diferente del tipo de su segundo ( example ). Además, el operador de asignación de copias de un lambda se define como eliminado ( example ), por lo que no puede hacer esto por partida doble. Para un efecto similar, puede tener a
be std::function
aunque le costará algo de rendimiento
std::function<bool()> a = [] { return true; };
a = [] { return false; };
Cada lambda tiene un tipo diferente, por lo que no puede cambiarlo. Podría usar una std::function para mantener un objeto llamable arbitrario, que se puede cambiar a voluntad.
std::function <bool ()> a = [] { return true; };
a = [] { return false; };
Desde C++17
puede hacer que se deduzca el parámetro std::function
template gracias a la deducción de argumentos de la plantilla de clase . Incluso funciona con la captura de lambdas:
int a = 24;
std::function f = [&a] (int p) { return p + a; };
f = [&a] (int p) { return p - a; };
f = [] (int p) { return p; };
Esto es útil con firmas más complejas y aún más con tipos de devolución deducidos.
Podemos usar la llamada retrospectiva para convertir lambda a std :: function:
template<typename T>
struct memfun_type
{
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>
{
using type = std::function<Ret(Args...)>;
};
template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
{ // Function from lambda !
return func;
}
Después de eso podremos hacerlo (ya que ''a'' es std :: function type now):
auto a = FFL([] { return false; });
a = FFL([] { return true; });
Un Lambda se puede convertir en un puntero de función utilizando el operador unario +
manera:
+[]{return true;}
siempre que el grupo de captura esté vacío y no tenga argumentos auto
. 1
Si hace esto, puede asignar diferentes lambdas a la misma variable siempre que las lambdas tengan la misma firma.
En tu caso,
auto a = +[]{return true;};
a = +[]{return false;};
compilaría y actuaría como usted espera. 2 Puede usar los punteros de función de la misma manera que espera usar un lambda, ya que ambos actuarán como functors .
1. En C ++ 14, puede declarar lambdas con auto
como tipo de argumento, como [](auto t){}
. Estas son lambdas genéricas , y tienen un operator()
plantilla operator()
. Dado que un puntero de función no puede representar una función con plantilla, el truco +
no funcionará con lambdas genéricas.
2. Técnicamente, no necesita el segundo operador +
en la tarea. La lambda se convertiría al tipo de puntero de función en la asignación. Aunque me gusta la consistencia.