///////////////////////////////////////////////////////////////////// // Lambdas.cpp - demonstrate lambda capture // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2015 // ///////////////////////////////////////////////////////////////////// /* * When compiled a lambda definition is translated into a functor * with operator() defining the code of the lambda. Any referenced * data from the local scope becomes member data of the functor and * gets passed around with the lambda. * * Lambdas are defined like this: * 1. [=] (arguments) * { code to execute may include names of local data as well as arguments }; * The [=] means that local data, like i below, are captured by value. * 2. [&] (arguments) * { code to execute may include names of local data as well as arguments }; * The [&] means that local data is captured by reference so must be in * scope when the lambda executes. * 3. [localVar1, &localVar2] (arguments) * { code to execute includes localVar1 by value and localVar2 by reference } */ #include #include #include //----< create a lambda and bind to a std::function >---------------- /* * Lambda copies captured values, e.g., [=] */ std::function CreateLambda1(int i) { // this std function converts an integer to a string std::function f = [=]() { std::ostringstream convert; convert << i; // lambda captures value of i return convert.str(); }; return f; } //----< create a lambda and bind to a std::function >---------------- /* * Lambda copies captured values, e.g., [] */ std::function CreateLambda2() { // this std function converts an integer to a string std::function f = [](int i) { std::ostringstream convert; convert << i; // lambda captures value of i return convert.str(); }; return f; } //----< create a lambda and bind to a std::function >---------------- /* * Lambda captures a reference to i and the value of j, e.g., [&i, j] */ std::function CreateLambda3(int& i) { // this std function converts integers to a string int j = 40; std::function f = [&i, j]() { std::ostringstream convert; convert << i + j; // lambda captures reference to return convert.str(); // external i - would be an error }; // if i was passed by value to return f; // CreateLambda3(int i) } //----< create a lambda and bind to a std::function >---------------- /* * Lambda captures a reference to i that will become invalid when * returning from invocation and a copy of j which will be valid, * e.g., [&i, j] */ std::function CreateLambda4() { // this std function converts integers to a string int i = 2; int j = 40; std::function f = [&i, j]() { std::ostringstream convert; convert << i + j; // error here - will return invalid reference return convert.str(); // to temporary value of i along with valid }; // copy of j, e.g., [&i, j] return f; } //----< demonstration of lambda operation >-------------------------- int main() { std::cout << "\n Demonstrating Lambda Capture"; std::cout << "\n =============================="; std::function f = CreateLambda1(42); std::cout << "\n The meaning of life is \"" << f() << "\""; std::function g = CreateLambda2(); std::cout << "\n The meaning of life is still \"" << g(42) << "\""; int i = 2; std::function h = CreateLambda3(i); std::cout << "\n Again, the meaning of life is still \"" << h() << "\""; std::function error = CreateLambda4(); std::cout << "\n the meaning of life is not \"" << error() << "\""; std::cout << "\n\n So long, Douglas Adams, and thanks for all the fish!\n\n"; }