S R T B H P N

Lambdas.cpp, Code folder

Illustrates lambdas and the several ways they capture local state.

Lambdas.cpp

/////////////////////////////////////////////////////////////////////
// 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 <functional>
#include <iostream>
#include <sstream>

//----< create a lambda and bind to a std::function >----------------
/*
 * Lambda copies captured values, e.g., [=]
 */
std::function<std::string()> CreateLambda1(int i)
{
  // this std function converts an integer to a string
  std::function<std::string()> 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<std::string(int)> CreateLambda2()
{
  // this std function converts an integer to a string
  std::function<std::string(int)> 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<std::string()> CreateLambda3(int& i)
{
  // this std function converts integers to a string
  int j = 40;
  std::function<std::string()> 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<std::string()> CreateLambda4()
{
  // this std function converts integers to a string
  int i = 2;
  int j = 40;
  std::function<std::string()> 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<std::string()> f = CreateLambda1(42);
  std::cout << "\n  The meaning of life is \"" << f() << "\"";

  std::function<std::string(int)> g = CreateLambda2();
  std::cout << "\n  The meaning of life is still \"" << g(42) << "\"";

  int i = 2;
  std::function<std::string()> h = CreateLambda3(i);
  std::cout << "\n  Again, the meaning of life is still \"" << h() << "\"";

  std::function<std::string()> 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";
}

Lambdas.txt

  Demonstrating Lambda Capture
 ==============================
  The meaning of life is "42"
  The meaning of life is still "42"
  Again, the meaning of life is still "42"
  the meaning of life is not "-858993420"
  So long, Douglas Adams, and thanks for all the fish!

Press any key to continue . . .