¿Qué hace realmente el código cuando paso una lambda mutable como referencia constante?
¿Por qué el compilador no genera un error? ¿Es esta una operación indefinida?
¿Por qué f1 y f2 son diferentes, f1 usa std::function<void()> y f2 usa auto ?
Encontré una pregunta similar pero todavía no entiendo completamente
Una const std::function envuelve un operador no const() / mutable lambda
#include <iostream> #include <functional> void call(std::function<void()> const & cb) { cb(); cb(); } int main() { std::function<void()> f1 = [a = 0] () mutable { std::cout << ++a << std::endl; }; call(f1); // prints 1 2 call(f1); // prints 3 4 auto f2 = [a = 0] () mutable { std::cout << ++a << std::endl; }; call(f2); // prints 1 2 call(f2); // prints 1 2 }En el primer caso, ambas llamadas de call(f1) usan la misma instancia de std::function<void()> .
En el segundo caso call(f2); La conversión implícita de lambda a std::function<void()> se activa y se crea el objeto temporal respectivo. Entonces, la segunda llamada usa una nueva copia del objeto temporal.
Intente transformar este código en cppinsights para ver esto con más detalles.
int main() { class __lambda_10_32 { public: inline /*constexpr */ void operator()() { std::cout.operator<<(++a).operator<<(std::endl); } private: int a; public: // inline /*constexpr */ __lambda_10_32(const __lambda_10_32 &) noexcept = default; // inline /*constexpr */ __lambda_10_32(__lambda_10_32 &&) noexcept = default; __lambda_10_32(const int & _a) : a{_a} {} }; std::function<void ()> f1 = std::function<void ()>(__lambda_10_32{0}); call(f1); call(f1); class __lambda_16_15 { public: inline /*constexpr */ void operator()() { std::cout.operator<<(++a).operator<<(std::endl); } private: int a; public: // inline /*constexpr */ __lambda_16_15(const __lambda_16_15 &) noexcept = default; // inline /*constexpr */ __lambda_16_15(__lambda_16_15 &&) noexcept = default; __lambda_16_15(const int & _a) : a{_a} {} }; __lambda_16_15 f2 = __lambda_16_15{0}; call(std::function<void ()>(__lambda_16_15(f2))); call(std::function<void ()>(__lambda_16_15(f2))); return 0; }