0% found this document useful (0 votes)
23 views29 pages

Module 53

Uploaded by

deva.jntuk.cse
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views29 pages

Module 53

Uploaded by

deva.jntuk.cse
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Module M53

L
Partha Pratim
Das
Programming in Modern C++

E
Objectives &
Outlines
Module M53: C++11 and beyond: General Features: Part 8: Lambda in C++/2

T
λ in C++:
Recap

P
std::function
Examples

Generic λ Partha Pratim Das

N
Recursive λ in
C++
Practice Examples
Department of Computer Science and Engineering
Generic Recursive λ Indian Institute of Technology, Kharagpur
Practice Examples
ppd@[Link]
Generalized λ
Captures

Module Summary
All url’s in this module have been accessed in September, 2021 and found to be functional

Programming in Modern C++ Partha Pratim Das M53.1


Module Recap

Module M53

• Understood λ expressions (unnamed function objects) in C++ with

L
Partha Pratim
Das
◦ Closure Objects

E
Objectives &
Outlines ◦ Parameters
◦ Capture

T
λ in C++:
Recap

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive λ
Practice Examples

Generalized λ
Captures

Module Summary

Programming in Modern C++ Partha Pratim Das M53.2


Module Objectives

Module M53

• To learn different techniques for writing and using λ expressions in C++

L
Partha Pratim
Das
• To understand std::function for specifying function prototypes

E
Objectives &
Outlines • To understand generic λ support in C++14

T
λ in C++:
Recap • To learn how to implement recursive λ expressions in C++11 and C++14

P
std::function
Examples
• To be exposed to several practice examples
Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive λ
Practice Examples

Generalized λ
Captures

Module Summary

Programming in Modern C++ Partha Pratim Das M53.3


Module Outline

Module M53

λ in C++: Recap

L
Partha Pratim 1
Das

E
Objectives &
Outlines
2 std::function
Examples

T
λ in C++:
Recap

P
std::function
Examples
3 Generic λ in C++14
Generic λ

N
Recursive λ in
4 Recursive λ in C++
C++
Practice Examples
Practice Examples
Generic Recursive λ Generic Recursive λ
Practice Examples
Practice Examples
Generalized λ
Captures

Module Summary
5 Generalized λ Captures

6 Module Summary

Programming in Modern C++ Partha Pratim Das M53.4


λ in C++: Recap

Module M53

L
Partha Pratim
Das

E
Objectives &
Outlines

T
λ in C++:
Recap

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive
Practice Examples
λ
λ in C++: Recap
Generalized λ
Captures Source:
Module Summary • Module 52: C++11 and beyond: General Features: Part 7: Lambda in C++/1

Programming in Modern C++ Partha Pratim Das M53.5


λ in C++: Recap (Module 52)

Module M53 • A λ expression is an unnamed function for specifying lightweight functions in C++
• Compiler generates a functor-like class for a λ which at run-time instantiates a Closure Object

L
Partha Pratim
Das
• A λ expression can have zero or more value and / or reference parameters used in its body

E
Objectives & Free variables in the body a λ expression must be captured by value or by reference
Outlines
• Here is a complete example

T
λ in C++:
Recap class A { std::vector<int> values; int m_;
public: A(int mod) : m_(mod) { }

P
std::function
Examples A& put(int v) { values.push_back(v); return *this; }
Generic λ int extras() { int count = 0;

N
Recursive λ in std::for_each([Link](), [Link](), // iterate over values to apply lambda
C++
[=, &count] // capture default by value, capture count by reference
Practice Examples
Generic Recursive λ
(int v) { count += v % m_; }); // v is a param, this captured implicitly
Practice Examples // by value & m_ used as this->m_ to accumulate
Generalized λ return count;
Captures }
Module Summary };
int main() { A g(4); // g.m_ = 4
[Link](3).put(7).put(8); // [Link] = { 3, 7, 8 }
std::cout << "extras: " << [Link](); // extras: 6: 3%4 + 7%4 + 8%4 = 3+3+0 = 6
}
Programming in Modern C++ Partha Pratim Das M53.6
std::function

Module M53

L
Partha Pratim
Das

E
Objectives &
Outlines

T
λ in C++:
Recap

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive
Practice Examples
λ
std::function
Generalized λ
Captures Source:
Module Summary • std::function, [Link]
• Usage and Syntax of std::function, [Link]
• std::function, [Link]
• std::function::function, [Link]

Programming in Modern C++ Partha Pratim Das M53.7


std::function

Module M53
• std::function is defined in <functional>

L
Partha Pratim template <class T> function; // empty - undefined
Das
template <class Ret, class... Args> class function<Ret(Args...)>;

E
Objectives &
Outlines • It is a polymorphic wrapper for function objects applies to all callable elements:
◦ Function pointers

T
λ in C++:
Recap
◦ Member function pointers

P
std::function
Examples
◦ Functors (including closure objects)
Generic λ

N
Recursive λ in
Type Old School Define std::function
C++ Free int(*callback)(int,int) function< int(int,int) >
Practice Examples
Functor object t callback function< int(int,int) >
Generic Recursive λ
Practice Examples
Member int (object t::*callback)(int,int) function< int(int,int) >
Generalized λ
Captures • Function declarator syntax is: std::function< R ( A1, A2, A3...) > f;
Module Summary • The function object can be copied and moved around, and can be used to directly invoke the
callable object with the specified call signature
• The function objects can also be in a state with no target callable object, called empty
functions. Calling them throws a bad function call exception
Programming in Modern C++ Partha Pratim Das M53.8
std::function: Examples
#include <iostream> // std::cout
Module M53
#include <functional> // std::function, std::negate

L
Partha Pratim
Das int half(int x) { return x/2; } // a function
struct third_t { int operator()(int x) { return x/3; } }; // a function object class

E
Objectives &
Outlines
struct MyValue { int value; int fifth() { return value/5; } }; // a class with data members

T
λ in C++: int main () {
Recap
std::function<int(int)> fn1 = half; // function

P
std::function std::function<int(int)> fn2 = &half; // function pointer
Examples std::function<int(int)> fn3 = third_t(); // function object
Generic λ std::function<int(int)> fn4 = [](int x) { return x/4; }; // lambda expression

N
std::function<int(int)> fn5 = std::negate<int>(); // standard function object
Recursive λ in
C++
Practice Examples std::cout << "fn1(60): " << fn1(60) << ’\n’; // fn1(60): 30
Generic Recursive λ std::cout << "fn2(60): " << fn2(60) << ’\n’; // fn2(60): 30
Practice Examples std::cout << "fn3(60): " << fn3(60) << ’\n’; // fn3(60): 20
Generalized λ
std::cout << "fn4(60): " << fn4(60) << ’\n’; // fn4(60): 15
Captures std::cout << "fn5(60): " << fn5(60) << ’\n’; // fn5(60): -60
Module Summary
std::function<int(MyValue&)> value = &MyValue::value; // pointer to data member
std::function<int(MyValue&)> fifth = &MyValue::fifth; // pointer to member function
MyValue sixty {60}; std::cout << "value(sixty): " << value(sixty) << ’\n’; // value(sixty): 60
std::cout << "fifth(sixty): " << fifth(sixty) << ’\n’; // fifth(sixty): 12
}
Programming in Modern C++ Partha Pratim Das M53.9
std::function: Example: Pipeline

Module M53 #include <iostream> // std::cout


#include <algorithm> // std::for_each

L
Partha Pratim
Das
#include <vector> // std::vector
#include <functional> // std::function
struct machine {

E
Objectives &
Outlines template< typename T >
void add(T f) { to_do.push_back(f); } // adding a function to to_do pipeline of functions

T
λ in C++:
Recap int run(int v) {
std::for_each(to_do.begin(), to_do.end(), // iterate over the vector of pipeline of functions

P
std::function
[&v](std::function<int(int)> f) {
Examples
v = f(v); // apply the next function and pipeline the result
Generic λ });

N
Recursive λ in return v;
C++ }
Practice Examples std::vector< std::function<int(int)> > to_do; // to_do is a vector collection of pipeline functions
Generic Recursive λ };
Practice Examples
int foo(int i) { return i + 4; }
Generalized λ int main() { machine m;
Captures [Link]([](int i){ return i * 3; }); // add a lambda as function #1 in pipeline
Module Summary [Link](foo); // add foo as function #2 in pipeline
[Link]([](int i){ return i / 5; }); // add a lambda as function #3 in pipeline
std::cout << "run(7) : " << [Link](7) << std::endl;
}
run(7) : 5 // func. #1 on 7 => 7 * 3 = 21. func. #2 on 21 => 21 + 4 = 25. func. #3 on 25 => 25 / 5 = 5
Programming in Modern C++ Partha Pratim Das M53.10
Generic λ in C++14

Module M53
Source:

L
Partha Pratim
Das
Generic lambdas, ISO
• Lambda expressions (since C++11), [Link]
• Scott Meyers on C++

E
Objectives &
Outlines • Lambda expressions in C++, Microsoft
• Generalized Lambda Expressions in C++14

T
λ in C++:
Recap • Generic code with generic lambda expression

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive λ
Practice Examples

Generalized λ
Captures Generic λ in C++14
Module Summary

Programming in Modern C++ Partha Pratim Das M53.11


Generic / Generalized λ in C++14

Module M53

• C++11 introduced λ expressions as short inline anonymous functions that can be nested inside

L
Partha Pratim
Das
other functions and function calls

E
Objectives &
Outlines • C++ 14 buffed up λ expressions by introducing Generic or Generalized λ
• Following λ function returns the sum of two integers

T
λ in C++:
Recap
[](int a, int b) -> int { return a + b; } // Return type is optional

P
std::function
Examples
• Whereas we need a different λ to obtain the sum of two floating point values:
Generic λ

N
[](double a, double b) -> double { return a + b; } // Return type is optional
Recursive λ in
C++
Practice Examples
• In C++11 we could unify these two λ functions using template parameters:
Generic Recursive λ template<typename T>
Practice Examples
[](T a, T b) -> T { return a + b } // Return type is optional - compiler may infer
Generalized λ
Captures • C++ 14 circumvent this by the keyword auto in the input parameters of the λ expression.
Module Summary Thus the compilers can now deduce the type of parameters during compile time:
[](auto a, auto b) { return a + b; } // Compiler must infer return type

Programming in Modern C++ Partha Pratim Das M53.12


Generic / Generalized λ in C++14
#include <iostream>, #include <string>, using namespace std;
Module M53
// C++11 lambda’s - separate lambda for every type. Return type is optional

L
Partha Pratim
Das auto add_i = [](int a, int b) { return a + b; }; // Compiler may infer return type
auto add_d = [](double a, double b) { return a + b; }; // Compiler may infer return type

E
Objectives & auto add_s = [](string a, string b) { return a + b; }; // Compiler may infer return type
Outlines // C++11 templatized lambda - one lambda for multiple types. Return type is optional

T
λ in C++: template<typename T> auto add_t = [](T a, T b) { return a + b; }; // Compiler may infer return type
Recap // C++14 generic lambda. Return type cannot be specified
auto add = [](auto a, auto b) { return a + b; }; // Compiler must infer return type

P
std::function
Examples int main () {
// Different name of each lambda for each type: No inference
Generic λ

N
cout << add_i(3, 5); // add_i for int type // 8
Recursive λ in cout << add_d(2.6, 1.3); // add_d for double type // 3.9
C++
cout << add_s("Good ", "Day"); // add_s for string type converts from const char* // Good Day
Practice Examples
Generic Recursive λ
Practice Examples
// Same name of the lambda for all types, type must be specified: No inference
cout << add_t<int>(3, 5); // add_t<int> for int type
Generalized λ cout << add_t<double>(2.6, 1.3); // add_t<double> for double type
Captures
cout << add_t<string>("Good ", "Day"); // add_t<string> for string type converts from const char*
Module Summary
// Same name of the lambda for all types and no type need to be specified: It is inferred
cout << add(3, 5); // add for int type
cout << add(2.6, 1.3); // add for double type
cout << add(string("Good "), string("Day")); // add for string type - cannot convert from const char*
}
Programming in Modern C++ Partha Pratim Das M53.13
Return Type of Generic λ in C++14

Module M53
• The return type may be inferred by the compiler from the return expression:
auto add = [](auto a, auto b) { return a + b; };

L
Partha Pratim
Das cout << add(2, 3); // 5 // rt = int
cout << add(4, 3.3); // 7.3 // rt = double

E
Objectives & cout << add(2.6, 2); // 4.6 // rt = double
Outlines cout << add(3.8, 4.5); // 8.3 // rt = double

T
λ in C++:
Recap
• The return type may be specified from the parameters:

P
std::function
Examples auto add = [](auto a, auto b) -> decltype(a) { return a + b; };
Generic λ cout << add(2, 3); // 5 // rt = int

N
cout << add(4, 3.3); // 7 // rt = int
Recursive λ in
C++
cout << add(2.6, 2); // 4.6 // rt = double
Practice Examples
cout << add(3.8, 4.5); // 8.3 // rt = double
Generic Recursive λ
Practice Examples auto add = [](auto a, auto b) -> decltype(b) { return a + b; };
cout << add(2, 3); // 5 // rt = int
Generalized λ
Captures cout << add(4, 3.3); // 7.3 // rt = double
cout << add(2.6, 2); // 4 // rt = int
Module Summary
cout << add(3.8, 4.5); // 8.3 // rt = double

• The return type may be explicitly specified:


auto add = [](auto a, auto b) -> int { return a + b; };
Programming in Modern C++ Partha Pratim Das M53.14
Use of Generic λ in C++14

Module M53 // Sorting integers, floats, strings using a generalized lambda and sort function
// #include <iostream>, #include <string>, #include <vector>, #include <algorithm>, using namespace std;

L
Partha Pratim
Das
// Utility Function to print the elements of a collection
void printElements(auto& C) {

E
Objectives &
Outlines for (auto e : C) cout << e << " ";
cout << endl;

T
λ in C++:
Recap }
int main() {

P
std::function
// Declare a generalized lambda and store it in greater. Works for int, double, string, ...
Examples
auto greater = [](auto a, auto b) -> bool { return a > b; };
Generic λ

N
Recursive λ in vector<int> vi = { 1, 4, 2, 1, 6, 62, 636 }; // Initialize a vector of integers
C++ vector<double> vd = { 4.62, 161.3, 62.26, 13.4, 235.5 }; // Initialize a vector of doubles
Practice Examples vector<string> vs = { "Tom", "Harry", "Ram", "Shyam" }; // Initialize a vector of strings
Generic Recursive λ
Practice Examples
sort([Link](), [Link](), greater); // Sort integers
Generalized λ sort([Link](), [Link](), greater); // Sort doubles
Captures sort([Link](), [Link](), greater); // Sort strings
Module Summary
printElements(vi); // 636 62 6 4 2 1 1
printElements(vd); // 235.5 161.3 62.26 13.4 4.62
printElements(vs); // Tom Shyam Ram Harry
}
Programming in Modern C++ Partha Pratim Das M53.15
Capture-less Generic λ to Function Pointers

Module M53
• A non-generic λ with an empty capture-list can be converted to a function pointer

L
Partha Pratim typedef int (*fp) (int); // Function pointer
Das
const fp f = [](int i){ return i; }; // Converts to a func. ptr. w/o capture

E
Objectives &
Outlines • A capture-less generic λ behaves in the same way
• Further, it can be converted to more than one compatible function pointers

T
λ in C++:
Recap
#include <iostream>

P
std::function
Examples
void f(void(*fp)(int)) { fp(1); /*...*/ }
Generic λ
void g(void(*fp)(double)) { fp(2.2); /*...*/ }

N
Recursive λ in
C++
Practice Examples
int main () {
Generic Recursive λ auto op = [](auto x) { // generic code for x
Practice Examples std::cout << "x = " << x << std::endl;
Generalized λ };
Captures

Module Summary // use ’op’ as a generic callback function pointer


f(op); // x = 1
g(op); // x = 2.2
}
Programming in Modern C++ Partha Pratim Das M53.16
Recursive λ in C++

Module M53
Source:

L
Partha Pratim
Das
Recursive lambda expressions in C++, [Link]
• Recursive lambda functions in C++11, [Link]
• std::function, [Link]

E
Objectives &
Outlines • Usage and Syntax of std::function, [Link]
• std::function, [Link]

T
λ in C++:
Recap • std::function::function, [Link]

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive λ
Practice Examples

Generalized λ
Captures Recursive λ in C++
Module Summary

Programming in Modern C++ Partha Pratim Das M53.17


Recursive λ in C++11

Module M53 • A recursive function CountOnes(n) counts the number of 1’s in the binary of n:

L
Partha Pratim
Das CountOnes(n) = CountOnes((n − 1)/2) + 1, n > 0 & odd
= CountOnes(n/2), n > 0 & even

E
Objectives &
Outlines
= 0, n = 0

T
λ in C++:
Recap
For example, CountOnes(5) = 2 (5 ≡ 101) and CountOnes(14) = 3 (14 ≡ 1110)

P
std::function
Examples • Coded as a normal recursive function:
Generic λ

N
Recursive λ in #include <iostream> // std::cout
C++
Practice Examples // recursive function CountOnes
Generic Recursive λ int CountOnes(int n) { return (0 == n)? 0: CountOnes(n/2) + (n % 2); }
Practice Examples

Generalized λ int main() {


Captures auto Print = // no capture needed for CountOnes or std::cout
Module Summary // as they are available as global symbols
[](int n) { std::cout << "#(" << n << ") = " << CountOnes(n) << "; "; };

Print(0); Print(1); Print(2); Print(3); Print(1729);


// #(0) = 0; #(1) = 1; #(2) = 1; #(3) = 2; #(1729) = 5;
}
Programming in Modern C++ Partha Pratim Das M53.18
Recursive λ in C++11

Module M53 • An attempt to code CountOnes as a lambda runs into compilation error:
#include <iostream> // std::cout

L
Partha Pratim
Das
int main() {

E
Objectives & auto CountOnes = [] (int n) { // error: use of ‘CountOnes’ before deduction of ‘auto’
Outlines return (0 == n)? 0: CountOnes(n/2) + (n % 2);
};

T
λ in C++:
Recap // ...
}

P
std::function
Examples
• std::function allows to declare the signature of CountOnes before defining it as a λ:
Generic λ #include <iostream> // std::cout

N
Recursive λ in #include <functional> // std::function
C++
Practice Examples int main() {
Generic Recursive λ std::function<int(int)> CountOnes; // signature of CountOnes
Practice Examples CountOnes = // capture CountOnes as its use is free in the body
Generalized λ [&CountOnes] (int n) -> int { return (0 == n)? 0: CountOnes(n/2) + (n % 2); };
Captures

Module Summary auto Print = // capture needed for CountOnes now as it is a local symbol
[&CountOnes](int n) { std::cout << "#(" << n << ") = " << CountOnes(n) << "; "; };

Print(0); Print(1); Print(2); Print(3); Print(1729);


// #(0) = 0; #(1) = 1; #(2) = 1; #(3) = 2; #(1729) = 5;
}
Programming in Modern C++ Partha Pratim Das M53.19
Example 1: Co-recursive Functions

Module M53 #include <iostream>


#include <functional>

L
Partha Pratim
Das

int main() {

E
Objectives &
Outlines std::function<int(int)> f1;
std::function<int(int)> f2 =

T
λ in C++:
Recap [&](int i) {
std::cout << i << " ";

P
std::function
Examples if (i > 5) { return f1(i - 2); } else { return 0; }
Generic λ };

N
Recursive λ in
C++
f1 = [&](int i) { std::cout << i << " "; return f2(++i); };
Practice Examples
Generic Recursive λ
Practice Examples f1(10);
Generalized λ
Captures return 0;
Module Summary }

10 11 9 10 8 9 7 8 6 7 5 6 4 5

Programming in Modern C++ Partha Pratim Das M53.20


Example 2: Factorial

Module M53

#include <iostream>

L
Partha Pratim
Das
#include <functional>

E
Objectives &
Outlines
int main() {

T
λ in C++:
Recap
std::function<int(int)> fact;

P
std::function
Examples
fact =
Generic λ [&fact](int n) -> int

N
Recursive λ in { return (n == 0) ? 1 : (n * fact(n - 1)); };
C++
Practice Examples
Generic Recursive λ std::cout << "factorial(4) : " << fact(4) << std::endl;
Practice Examples

Generalized λ
Captures return 0;
Module Summary
}

Programming in Modern C++ Partha Pratim Das M53.21


Example 3: Fibonacci

Module M53
#include <iostream>

L
Partha Pratim
Das
#include <functional>
using namespace std;

E
Objectives &
Outlines

int main() {

T
λ in C++:
Recap
std::function<int(int)> fibo;

P
std::function
Examples fibo =
Generic λ [&fibo](int n)->int

N
Recursive λ in
C++
{ return (n == 0) ? 0 :
Practice Examples (n == 1) ? 1 :
Generic Recursive λ
Practice Examples (fibo(n - 1) + fibo(n - 2)); };
Generalized λ
Captures
cout << "fibo(8) : " << fibo(8) << endl;
Module Summary

return 0;
}
Programming in Modern C++ Partha Pratim Das M53.22
Generic Recursive λ in C++14

Module M53

• A λ does not have a named specific type. So a recursive λ expression needs std::function

L
Partha Pratim
Das
wrapper
• The generic λ expression in C++14 allows recursive λ functions without using std::function

E
Objectives &
Outlines
• Consider the CountOnes example again:

T
λ in C++:
Recap
#include <iostream> // std::cout

P
std::function
Examples
int main() {
Generic λ auto CountOnes = // we need to pass CountOnes as a parameter in the lambda

N
Recursive λ in // note the use of CountOnes as the first parameter in the call
C++ [] (auto&& CountOnes, int n) -> int { // C++14
Practice Examples return (0 == n)? 0: CountOnes(CountOnes, n/2) + (n % 2);
Generic Recursive λ };
Practice Examples

Generalized λ auto Print = // capture needed for CountOnes now as it is a local symbol
Captures [&CountOnes] (int n)
Module Summary { std::cout << "CountOnes(" << n << ") = " << CountOnes(CountOnes, n) << std::endl; };

Print(0); Print(1); Print(2); Print(3); Print(1729);


// #(0) = 0; #(1) = 1; #(2) = 1; #(3) = 2; #(1729) = 5;
}
Programming in Modern C++ Partha Pratim Das M53.23
Generic Recursive λ in C++14: Power

Module M53
#include <iostream> // C++11 solution using std::function. Works for int base

L
Partha Pratim
Das
#include <functional>
int main() {

E
Objectives & std::function<int(int,int)> pow; // pow recursive function. std::function used to define type of pow
Outlines pow = [&pow](int base, int exp) { return exp==0 ? 1 : base*pow(base, exp-1); };
std::cout << pow(2, 10); // 2^10 = 1024

T
λ in C++:
Recap std::cout << pow(2.71828, 10); // e^10 = 1024 // 2.71828 is cast to int giving 2 and wrong result
}

P
std::function
Examples
#include <iostream> // C++14 solution without using std::function. Works for any numeric base
Generic λ int main() {

N
Recursive λ in auto power = [](auto self, auto base, int exp) -> decltype(base) { // any numeric ’base’ type
C++ return exp==0 ? 1 : base*self(self, base, exp-1);
Practice Examples };
Generic Recursive λ // Wrapper of power to avoid passing power as first parameter to the call
Practice Examples
auto pow = [power](auto base, int exp) -> decltype(base) { return power(power, base, exp); };
Generalized λ
Captures std::cout << power(power, 2, 10); // 2^10 = 1024 // Needs to pass itself as first parameter
Module Summary std::cout << power(power, 2.71828, 10); // e^10 = 22026.3

std::cout << pow(2, 10); // 2^10 = 1024 // Wrapper provides a clean solution
std::cout << pow(2.71828, 10); // e^10 = 22026.3
}
Programming in Modern C++ Partha Pratim Das M53.24
Generic Recursive λ in C++14: Factorial

Module M53 #include <iostream> // Factorial lambda in C++11 solution using std::function
#include <functional>

L
Partha Pratim
Das int main () {
std::function < int (int) > fact;

E
Objectives &
Outlines fact = [&fact](int n) -> int
{ return (n == 0) ? 1 : (n * fact(n - 1));

T
λ in C++:
Recap };
std::cout << "factorial(4) : " << fact(4) << std::endl;

P
std::function
Examples }
Generic λ

N
Recursive λ in #include <iostream> // Factorial lambda in C++14 without using std::function
C++
int main () {
Practice Examples
Generic Recursive λ
auto factorial = [](auto self, int n) -> int
Practice Examples { return (n == 0) ? 1 : (n * self(self, n - 1));
Generalized λ };
Captures auto fact = [factorial](int n) -> int // Wrapper of factorial to skip passing factorial
Module Summary { return factorial(factorial, n);
};
std::cout << "factorial(4) : " << fact(4) << std::endl;
}
Programming in Modern C++ Partha Pratim Das M53.25
Generic Recursive λ in C++14: Fibonacci

Module M53 #include <iostream> // Fibonacci lambda in C++11 solution using std::function
#include <iostream>

L
Partha Pratim
Das #include <functional>
int main () {

E
Objectives & std::function < int (int) > fibo;
Outlines
fibo = [&fibo](int n) -> int {

T
λ in C++:
Recap return (n == 0) ? 0 : (n == 1) ? 1 : (fibo(n - 1) + fibo(n - 2));
};

P
std::function
Examples std::cout << "fibo(8) : " << fibo(8) << std::endl;
Generic λ }

N
Recursive λ in
C++ #include <iostream> // Fibonacci lambda in C++14 without using std::function
Practice Examples int main () {
Generic Recursive λ
Practice Examples
auto fibonacci = [](auto self, int n) -> int {
return (n == 0) ? 0 : (n == 1) ? 1 : (self(self, n - 1) + self(self, n - 2));
Generalized λ
Captures };
Module Summary auto fibo = [fibonacci](int n) -> int { // Wrapper of fibonacci to skip passing fibonacci
return fibonacci(fibonacci, n);
};
std::cout << "fibo(8) : " << fibo(8) << std::endl;
}
Programming in Modern C++ Partha Pratim Das M53.26
Generalized λ Captures

Module M53

L
Partha Pratim
Das

E
Objectives &
Outlines

T
λ in C++:
Recap

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive λ
Practice Examples

Generalized λ
Captures
Generalized λ Captures
Module Summary Source:
• Generalized lambda captures, [Link]

Programming in Modern C++ Partha Pratim Das M53.27


Generalized λ Captures in C++14

Module M53

• In C++11, λs could not (easily) capture by move. Generalized λ capture in C++14

L
Partha Pratim
Das
solves the problem and also allows to define arbitrary new local variables in the λ object:

E
Objectives &
Outlines auto u = make_unique<some_type>(some, parameters); // a unique_ptr is move-only (TBD later)

T
λ in C++: [Link]([u=move(u)] { do_something_with(u); }); // move the unique_ptr into the lambda
Recap

P
std::function
Examples
• We can also rename the variable u the same inside the λ
Generic λ

N
[Link]([u2=move(u)] { do_something_with(u2); }); // capture as u2
Recursive λ in
C++
Practice Examples • And we can add arbitrary new state to the λ object, because each capture creates a
Generic Recursive λ
Practice Examples new type-deduced local variable inside the λ:
Generalized λ
Captures int x = 4;
Module Summary
int z = [&r = x, y = x + 1] { // y is local, set to 5
r += 2; // set x to 6; "r is for Renamed Ref"
return y + 2; // return 7 to initialize z
}(); // invoke lambda

Programming in Modern C++ Partha Pratim Das M53.28


Module Summary

Module M53

• Learnt different techniques without or with std::function to write and use

L
Partha Pratim
Das
non-recursive and recursive λ expressions in C++11 / C++14

E
Objectives &
Outlines • Several practice examples to be tried and tested

T
λ in C++:
Recap

P
std::function
Examples

Generic λ

N
Recursive λ in
C++
Practice Examples
Generic Recursive λ
Practice Examples

Generalized λ
Captures

Module Summary

Programming in Modern C++ Partha Pratim Das M53.29

You might also like