Capture de mouvement dans Lambdas
Question :
Comment implémenter la capture de mouvement, également connues sous le nom de références rvalue, en C 11 lambdas ? Par exemple :
std::unique_ptr<int> myPointer(new int); std::function<void(void)> example = [std::move(myPointer)] { *myPointer = 4; };
Réponse :
Capture Lambda généralisée en C 14
En C 14, lambda généralisée la capture permet la capture de mouvements. Ce code est désormais valide :
using namespace std; auto u = make_unique<some_type>(some, parameters); go.run([u = move(u)] { do_something_with(u); });
Pour déplacer des objets d'un lambda vers une autre fonction, rendez le lambda mutable :
go.run([u = move(u)] mutable { do_something_with(std::move(u)); });
Solution de contournement pour Move Capture en C 11
Une fonction d'assistance, make_rref, peut faciliter la capture de mouvements. Son implémentation est la suivante :
#include <cassert> #include <memory> #include <utility> template <typename T> struct rref_impl { rref_impl() = delete; rref_impl(T&& x) : x{std::move(x)} {} rref_impl(rref_impl& other) : x{std::move(other.x)}, isCopied{true} { assert(other.isCopied == false); } rref_impl(rref_impl&& other) : x{std::move(other.x)}, isCopied{std::move(other.isCopied)} { } rref_impl& operator=(rref_impl other) = delete; T& operator&&() { return std::move(x); } private: T x; bool isCopied = false; }; template<typename T> rref_impl<T> make_rref(T&& x) { return rref_impl<T>{std::move(x)}; }
Un cas de test pour make_rref :
int main() { std::unique_ptr<int> p{new int(0)}; auto rref = make_rref(std::move(p)); auto lambda = [rref]() mutable -> std::unique_ptr<int> { return rref.move(); }; assert(lambda()); assert(!lambda()); }
Émulation de la capture Lambda généralisée en C 11
Un autre une solution de contournement est fournie par la fonction capture() :
#include <cassert> #include <memory> int main() { std::unique_ptr<int> p{new int(0)}; auto lambda = capture(std::move(p), [](std::unique_ptr<int>& p) { return std::move(p); }); assert(lambda()); assert(!lambda()); }
la capture est implémentée comme suit :
#include <utility> template <typename T, typename F> class capture_impl { T x; F f; public: capture_impl(T&& x, F&& f) : x{std::forward<T>(x)}, f{std::forward<F>(f)} {} template <typename ...Ts> auto operator()(Ts&& ...args) -> decltype(f(x, std::forward<Ts>(args)...)) { return f(x, std::forward<Ts>(args)...); } template <typename ...Ts> auto operator()(Ts&& ...args) const -> decltype(f(x, std::forward<Ts>(args)...)) { return f(x, std::forward<Ts>(args)...); } }; template <typename T, typename F> capture_impl<T, F> capture(T&& x, F&& f) { return capture_impl<T, F>( std::forward<T>(x), std::forward<F>(f)); }
Cette solution empêche la copie du lambda si le type capturé n'est pas copiable, évitant ainsi les erreurs d'exécution.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!