Upgrade to Pro — share decks privately, control downloads, hide ads and more …

C++11 Lambda

Matt
November 16, 2013

C++11 Lambda

Matt

November 16, 2013
Tweet

More Decks by Matt

Other Decks in Programming

Transcript

  1. Outline • Lambda syntax • Lambda in STL algorithms •

    Lambda as callback • Lambda in concurrency • Lambda as scope guard
  2. Greetings void greetings() { cout << "Hello!"; } int main()

    { greetings(); } -------------Output------------ Hello!
  3. First Lambda int main() { auto greetings = [] {

    cout << "Hello Lambda!"; }; greetings(); } -------------Output------------ Hello Lambda! lambda syntax starting with [ ]
  4. // Create a lambda and call it immediately. int main()

    { [] { cout << "Hello Lambda!"; } (); } -------------Output------------ Hello Lambda!
  5. int main() { auto func = [] ( string strName

    ) { cout << "Hello " << strName << endl; }; func( "Taco" ); } -------------Output------------ Hello Taco! Pass parameter to a lambda
  6. int main() { auto func = [] ( float f1,

    float f2 ) { return f1 + f2; }; cout << func( 2.5, 7.5 ); } -------------Output------------ 10 Lambda can return something.
  7. int main() { auto func = [] ( float f1,

    float f2 ) -> float { return f1 + f2; }; cout << func( 2.5, 7.5 ); } -------------Output------------ 10 Specify return type.
  8. int main() { string strName = "Matthew"; auto func =

    [strName] { cout << "Hello " << strName; }; func(); } -------------Output------------ Hello Matthew Capture variable "strName".
  9. int main() { string strName = "Matthew"; auto func =

    [=] { cout << "Hello " << strName; }; func(); } -------------Output------------ Hello Matthew Auto capture all variables by copy.
  10. int main() { string strName = "Matthew"; auto func =

    [=] { strName = "Terence"; // Ooops, compiler error. cout << "Hello " << strName; }; func(); } -------------Output------------
  11. int main() { string strName = "Matthew"; auto func =

    [&] { strName = "Terence"; // OK! cout << "Hello " << strName; }; func(); } -------------Output------------ Hello Matthew Auto capture all variables by reference.
  12. [] Capture nothing [&] Capture any referenced variable by reference

    [=] Capture any referenced variable by making a copy [=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference [bar] Capture bar by making a copy; don't copy anything else [this] Capture the this pointer of the enclosing class [x, &y, z ] Capture x, z by making a copy; capture y by reference; don't copy anything else
  13. void plus10( int& i ) { i = i +

    2; } int main() { vector<int> v { 1, 2, 3, 4, 5 }; for_each( v.begin(), v.end(), plus10 ); // print v } -------------Output------------ 11 12 13 14 15 <<< The Old Way
  14. void plusN( int& i ) { i = i +

    n; } int main() { vector<int> v { 1, 2, 3, 4, 5 }; cin >> n; for_each( v.begin(), v.end(), plusN ); // print v } -------------Output------------ <= How to get n ??
  15. int main() { vector<int> v { 1, 2, 3, 4,

    5 }; cin >> n; auto plusN = [n] ( int &i ) { i = i + n; }; for_each( v.begin(), v.end(), plusN ); // print v } -------------Output------------ n is 4 5 6 7 8 9 std::for_each() in lambda
  16. int main() { vector<int> v { 1, 2, 3, 4,

    5 }; cin >> n; for_each( v.begin(), v.end(), [n] ( int &i ) { i = i + n; } ); // print v } -------------Output------------ n is 4 5 6 7 8 9 <<< inline Lambda
  17. int main() { vector<int> v { 1, 2, 3, 4,

    5 }; cin >> n; for_each( v.begin(), v.end(), [n] ( int &i ) { i = i + n; } ); // print v } -------------Output------------ <<< inline Lambda
  18. std::find_if vector<string> v { "Apple", "Banana", "Cat", "Doom" }; char

    firstLetter = 'C'; auto pos = find_if( v.begin(), v.end(), [=](string str) { return str[0] == firstLetter; }); cout << *pos; -------------Output------------ Cat
  19. std::transform vector<int> v { 1, 2, 3, 4, 5 };

    vector<int> v2; transform( v.begin(), v.end(), // source v2.begin(), // destination [](int i) { return i * i * i; // to the power of 3 }); for_each( v2.begin(), v2.end, [] (int &i) {cout << i << " "} ); -------------Output------------
  20. Lambda syntax [ capture ] ( params ) mutable exception

    attribute -> ret { body } [ capture ] ( params ) -> ret { body } [ capture ] ( params ) { body } [ capture ] { body }
  21. Type of a Lambda • Anonymous function object • Unique

    for each lambda. • Using std::function to wrap lambda, ex: std::function< bool(int) > func = [] ( int i ) -> bool { return i % 2; }; func( 4 ); #include<functional>
  22. class CVideoExporter { public: std::function< void() > onWorkCompleted; std::function< void()

    > onWorkCanceled; std::function< void(RL::Result) > onWorkFailed; std::function< void(float) > onProgressChanged; Result start(); Result cancel(); ... };
  23. CVideoExporter* e = new CVideoExporter; CVideoExportDialog* d = new CVideoExportDialog;

    e.onWorkCompleted = [=] { d.ShowMesseage( "Video Exporting Success." ); }; e.onWorkCanceled = [=] { d.closeDialog(); }; e.onWorkFailed = [=] ( RL::Result result ) { d.ShowMessage( errorMessage( result ) ); }; e.onProgressChanged = [=] ( float fProgress ) { d.setProgress( fProgress ); }; e.start();
  24. Lambda in Qt5 signal/slot void Doc::saveDocument() { QFileDialog* dlg =

    new QFileDialog(); dlg->open(); QObject::connect(dlg, &QDialog::finished, [dlg, this](int result) { if (result) { QFile file(dlg->selectedFiles().first()); // ... } dlg->deleteLater(); }); }
  25. std::future long long n = 313221123313213213; std::future<bool> ft = std::async(

    [=] { return IsPrime( n ); } ); ...perform foreground task. bool bIsPrime = ft.get(); // get result later. #include<future>
  26. template<class InputIterator> int parallel_sum( InputIterator beg, InputIterator end ) {

    typename InputIterator::difference_type len = end - beg; if ( len < 1000 ) return std::accumulate( beg, end, 0 ); InputIterator mid = beg + len / 2; auto handle = std::async( std::launch::async, [&] { parallel_sum( mid, end ); } ); int sum = parallel_sum( beg, mid ); return sum + handle.get(); } int main() { std::vector<int> v(10000, 1); std::cout << "The sum is " << parallel_sum( v.begin(), v.end() ) << '\n'; }
  27. Scope Guard void foo() { HANDLE h = CreateFile(...); IXXXObject*

    = CreateXXX(..); ON_SCOPE_EXIT ( CloseHandle( h ); SAFE_RELEASE( IXXXObject ); ) ... // use the file }
  28. ON_SCOPE_EXIT #define ON_SCOPE_EXIT(callback) \ ScopeGuard onExit( [&] { callback }

    ); void foo() { HANDLE h = CreateFile(...); ScopeGuard onExit ( [&] { CloseHandle(h); } ); ... // use the file }
  29. ScopeGuard class ScopeGuard { public: explicit ScopeGuard( std::function<void()> onExitScope )

    : m_onExitScope( onExitScope ) { } ~ScopeGuard() { m_onExitScope(); } private: std::function<void()> m_onExitScope; };