1 / 16

Lambda Expressions

Lambda Expressions. Conceptually, unnamed function objects created “on the fly”. vector<int> v; auto it = find_if(v.cbegin(), v.cend(), [](int i){return i>0 && i<10;} ); deque<float> d; sort(d.begin(), d.end(), [](const float& f1, const float& f2) { return f1 < f2;} );.

arien
Download Presentation

Lambda Expressions

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lambda Expressions • Conceptually, unnamed function objects created “on the fly”. vector<int> v; auto it = find_if(v.cbegin(), v.cend(), [](int i){return i>0 && i<10;}); deque<float> d; sort(d.begin(), d.end(), [](const float& f1, const float& f2) { return f1 < f2;});

  2. Lambda Expressions • Lambda expressions – just a shorthand for creating and using function objects. • Such function objects are called closures.

  3. Capturing Local Variables • Local variables from the calling context can be “captured” int minVal, maxVal; .. auto it = find_if(v.begin(), v.end(), [minVal, maxVal](int i) {return i>minVal && i<maxVal;}); Without lambdas, you would need to create a function object and pass minVal and maxVal through its constructor.

  4. Capturing local variables • Captures can also be references. Different local variables can be captured in different ways: int minVal, maxVal; .. auto it = find_if(v.begin(), v.end(), [&minVal, &maxVal](int i) {return i>minVal && i<maxVal;}); auto it = find_if(v.begin(), v.end(), [minVal, &maxVal](int i) {return i>minVal && i<maxVal;});

  5. Capturing Local Variables • Capture mode defaults can be specified: auto it = find_if(v.begin(), v.end(), [=](int i) //defaults to by value {return i>minVal && i<maxVal;}); auto it = find_if(v.begin(), v.end(), [&](int i) //defaults to by ref {return i>minVal && i<maxVal;}); • With a default capture mode, captured variables need not be listed.

  6. Capturing Local Variables • Default overridable on per-variable basis: auto it = find_if(v.begin(), v.end(), [=, &maxVal](int i) {return i>minVal && i<maxVal;});

  7. Capturing Class Members • To access class members within a member function, capture this: class Widget { public: void doSomething(); private: list<int> il; int minVal;}; Void Widget::doSomething() { auto it = find_if(il.begin(), il.end(), [minVal](int i){return i >minVal;})} //error Void Widget::doSomething() { auto it = find_if(il.begin(), il.end(), [this](int i){return i >minVal;})}

  8. Capturing Class Members • A default capture mode also makes this available: class Widget { public: void doSomething(); private: list<int> il; int minVal;}; Void Widget::doSomething() { auto it = find_if(il.begin(), il.end(), [=](int i){return i >minVal;})} Void Widget::doSomething() { auto it = find_if(il.begin(), il.end(), [&](int i){return i >minVal;})}

  9. Lambda Return Types • Optional when: • Return type is void. • Lambda body is “return expr;” • Return type is that of “expr” • Otherwise must be specified via trailing return type syntax: vector<double> v; transform(v.begin(), v.end(), [](double d)->double { doSomethingElseHere(); return sqrt(abs(d));});

  10. Trailing Return Types • Must be used with lambdas (when a return type is given). • Often useful with decltype • Permitted for any function (with a leading auto):\ void f(int x); auto f(int x)->void; class Widget { public: void mf1(int x); auto mf2()const -> bool; }; • Non-lambda, non-decltype uses not expected to be common

  11. Lambdas without Parameter Lists • Lambdas with no parameters may omit the parameter list. • Such functions especially useful with threads. Void doSomeWork(); Void doMoreWork(); thread t1([](){doSomeWork(); doMoreWork();}); thread t2([] {doSomeWork(); doMoreWork();}); • Omitting the optional parentheses seems to be fairly common.

  12. Lambda Expression Complexity • Lambdas maybe arbitrarily complex: • Multiple statements, multiple returns. • Throw/catch exceptions. • Essentially anything allowed in a “normal” function. • Maintainability considerations suggest: • Short, clear, context-derived lambdas are best.

  13. Storing Closures • Closure types not specified, but two easy ways to store closures: 1. auto auto multipleOf5 =[](long x) {return x %5==0;}; vector<long> vl; vl.erase(remove_if(vl.begin(), vl.end(), multipleOf5), vl.end());

  14. Storing Closures • Closure types not specified, but two easy ways to store closures: 2. std::function std::function<bool(long)> multipleOf5 =[](long x){return x %5==0;}; vl.erase(remove_if(vl.begin(), vl.end(), multipleOf5), vl.end());

  15. Specifying Function Types • A function type is its declaration w/o any names: void f1(int x); //type is void(int) double f2(int x, string s); //type is double(int, string) • C++ uses this function type for std::function std::function<bool(long)> multipleOf5 = [](long x) {return x % 5 == 0;}; • Function types never use the trailing return type format.

  16. Lambda/Closure Summary • Lambda Expressions generate closures. • Calling state can be captured by value or by reference. • Return types, when specified, use trailing return type syntax. • Closure can be stored using auto or std::function. • Short, clear, context-derived lambdas are best.

More Related