Lambdas
Contents
std::function
We have a class template called "std::function" that can store either a function, a functor or a lambda expression. It is used as a callable object that stores the functionality and can be used later to call the embedded function. The "std::function" is not a type but a class template that takes a function signature like: R(Args...) Now this is also not a type in the sense we cannot create an object from it using the notation: R(Args...) object ; It is more of a language feature that is very specialized and ( no pun intended ) is used in: 1) Template Specialization 2) std::function The "R(Args...)" is like a function signature with "R" sepcifying the return type and Args representing a variable number of arguments.
File: template1.cpp
#include <iostream> #include <string> #include <utility> // For forward #include <functional> using namespace std ; // Primary template definition template <typename T> class FunctionHandler { public: void handle(T val) { cout << "Handling generic type: " << typeid(T).name() << endl; } }; // Partial specialization for function types R(Args...) template <typename R, typename... Args> class FunctionHandler<R(Args...)> { public: void handle(R (*func)(Args...)) { cout << "Handling function pointer with return type " << typeid(R).name() << " and arguments: "; // A more advanced implementation could iterate through Args... to print types cout << " (function pointer)" << endl; //callable_ptr(args...) } void handle(function<R(Args...)> func) { cout << "Handling function with return type " << typeid(R).name() << " and arguments: "; cout << " (function)" << endl; } }; // A sample function for demonstration int add(int a, int b) { return a + b; } void greet(const string& name) { cout << "Hello, " << name << "!" << endl; } int main() { // Generic type handling FunctionHandler<int> intHandler; intHandler.handle(10); FunctionHandler<string> stringHandler; stringHandler.handle("test"); // Function pointer handling FunctionHandler<int(int, int)> addHandler; addHandler.handle(&add); //function handling function<void(const string&)> greetFunc = greet ; FunctionHandler<void(const string&)> greetHandler; greetHandler.handle(greetFunc); return 0; } $ g++ template1.cpp ; ./a.exe Handling generic type: i Handling generic type: Ss Handling function pointer with return type i and arguments: (function pointer) Handling function with return type v and arguments: (function) From the above code we have: // Primary class template (declaration only, intended for function types) templateThe other use case is for the "std:function".class CallableWrapper; // Specialization for function type R(Args...) template class CallableWrapper { We cannot use "R(Args...)" in a template declaration by itself. It has to be in a template specialization. What the above declaration is saying is that; we can pass a function type such as a lambda, a function or a function pointer to the "CallableWrapper" . However we cannot pass a functor object or a std::function object.
File: function1.cpp
#include <iostream> #include <functional> int add(int a, int b) { return a + b; } class Multiply { public: int operator()(int a, int b) { return a * b; } }; int main() { // Store a regular function function<int(int, int)> f1 = add; cout << "Result of add(5, 3): " << f1(5, 3) << endl; // Store a lambda expression function<int(int, int)> f2 = [](int a, int b) { return a - b; }; cout << "Result of lambda (-5, 3): " << f2(-5, 3) << endl; // Store a function object Multiply multiplier; function<int(int, int)> f3 = multiplier; cout << "Result of Multiply(7, 4): " << f3(7, 4) << endl; //Store a function pointer int(*func_ptr)(int, int) = add; function<int(int, int)> f4 = func_ptr; cout << "Result of func_ptr(10, 2): " << f4(10, 2) << endl; return 0; } $ g++ function1.cpp ; ./a.exe Result of add(5, 3): 8 Result of lambda (-5, 3): -8 Result of Multiply(7, 4): 28 Result of func_ptr(10, 2): 12 The above file shows how we can use "std::function" template. std::function
Exercise
File: function_ex1.cpp
#include <iostream> #include <functional> using namespace std ; void printString(const string& str1) { cout << str1 << endl ; } int main() { //Create a std::function object called f1. Store the function //printString in it. //TO DO const string str1 = "Hooray. Almost end of Semester." ; cout << "Result of f1: " ; f1( str1 ) ; //Create a std::function object called f2. Store //a lambda expression that does the same thing //as printString. The capture clause is empty and //it takes a single argument of type "const string&" //printString in it. //TO DO cout << "Result of f2: " ; f2( str1 ) ; return 0; }
Solutions
File: function_ex1s.cpp