2015-01-06 16 views
25

sto Catturare un'unique_ptr in un'espressione lambda in questo modo:Cattura e spostare un unique_ptr in un'espressione C++ 14 lambda

auto str = make_unique<string>("my string"); 
auto lambda = [ capturedStr = std::move(str) ] { 
    cout << *capturedStr.get() << endl; 
}; 
lambda(); 

funziona benissimo fino a quando cerco di passare ad un altro capturedStr unique_ptr. Per esempio, il seguente non funziona:

auto str = make_unique<string>("my string"); 
auto lambda = [ capturedStr = std::move(str) ] { 
    cout << *capturedStr.get() << endl; 
    auto str2 = std::move(capturedStr); // <--- Not working, why? 
}; 
lambda(); 

Ecco l'output del compilatore:

.../test/main.cpp:11:14: error: call to implicitly-deleted copy 
constructor of 'std::__1::unique_ptr<std::__1::basic_string<char>, 
std::__1::default_delete<std::__1::basic_string<char> > >' 
     auto str2 = std::move(capturedStr); 
      ^ ~~~~~~~~~~~~~~~~~~~~~~ ../include/c++/v1/memory:2510:31: note: copy constructor is implicitly 
deleted because 'unique_ptr<std::__1::basic_string<char>, 
std::__1::default_delete<std::__1::basic_string<char> > >' has a 
user-declared move constructor 
    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT 
          ^1 error generated. 

Perché non è possibile spostare capturedStr?

+11

L'operatore '' di Lambdas() 'è' const' a meno che non sia dichiarato 'mutable', e non è possibile spostarsi da un oggetto' const'. –

+1

Grazie @ T.C., Puoi scrivere una risposta, la accetterò – MartinMoizard

risposta

45

Il operator() di un lambda è const per impostazione predefinita e non è possibile spostarsi da un oggetto const.

Dichiararlo mutable se si desidera modificare le variabili acquisite.

auto lambda = [ capturedStr = std::move(str) ]() mutable { 
//            ^^^^^^^^^^ 
    cout << *capturedStr.get() << endl; 
    auto str2 = std::move(capturedStr); 
}; 
+1

Pensavo che non avresti postato :) +1 – sehe

6
auto lambda = [ capturedStr = std::move(str) ] { 
    cout << *capturedStr.get() << endl; 
    auto str2 = std::move(capturedStr); // <--- Not working, why? 
}; 

per dare più dettaglio il compilatore sta diventando di questa trasformazione:

class NameUpToCompiler 
{ 
    unique_ptr<string> capturedStr; // initialized from move assignment in lambda capture expression 

    void operator()() const 
    { 
     cout << *capturedStr.get() << endl; 
     auto str2 = std::move(capturedStr); // move will alter member 'captureStr' but can't because of const member function. 
    } 
} 

L'uso di mutabile sul lambda rimuoverà il const dalla funzione membro dell'operatore() quindi a che permette ai membri di essere modificati

Problemi correlati