DEV Community

Swastik Baranwal
Swastik Baranwal

Posted on • Updated on

Modern C++: Lambdas

Following my series from less known features of Modern C++.

Lambdas

Lambdas are anonymous functions which are un-named functions as they are mostly needed for High Order Functions and for small purposes where they don't need much importance to be named. Lambdas were introduced in C++11 and heavily improved in the new standards.

Syntax

[capture list](parameter list) -> return type (optional) {
  function body
}
Enter fullscreen mode Exit fullscreen mode
  • Capture List: Specifies how the value will be captured in the scope.
  • Parameter List: Parameters required for the function
  • Return Type (Optional) : The return type of the function.
  • Function Body: Body of the function.

Basic Examples

#include <iostream>

int main() {

 int add = [](int a){ return 2 + 3; }(); // using lambda and then storing the value

 [](){ std::cout<< "Caliing like this also works" << std::endl; }(); 

 auto callback = [](auto a, auto b) { 
        a == b;
  }; // using a label and then using it for various purposes
}
Enter fullscreen mode Exit fullscreen mode

Capture List

A lambda can introduce new objects in its body and can also access or capture objects from the surrounding scope. A lambda begins with the capture clause which specifies the objects that are captured and whether the capture is by value or by reference. Objects that have the ampersand (&) prefix are accessed by reference and objects that do not have it are accessed by value.

An empty capture list [] means that there are no variables captured. If the user wants all variables to be captured by reference then one should use [&] or pass by value then use [=]. If one wants some variable to be captured by reference or value then they should do [foo, &var].

The following are valid:

[&var, foo] // var is captured by reference and foo is passed by value.
[&, factor] // only factor is captured by value here.
[=, &total] // only total is passed by reference.
[] // no objects are passed.
Enter fullscreen mode Exit fullscreen mode

Parameter List

Like functions, parameters are optional for lambdas.

#include <iostream>

int main() {

auto add = [](int a, int b) -> int {
      return a + b;
  };

auto print = []() {
  std::cout << "Printing from lambda." << std::endl;
};

std::cout << add(5, 5) << std::endl;
std::cout << print() << std::endl;
}
Enter fullscreen mode Exit fullscreen mode

In this example we have add() lambda which takes parameter and print() lambda which doesn't take.

Since C++ 14, we can now use auto for type deceleration which can be helpful for combating more problems.

#include <iostream>

int main() {

 auto add = [](auto a, auto b) {
      return a + b;
   };

 std::cout << add(5, 5) << std::endl; // for int
 std::cout << add(24.567, 456.7) << std::endl; // for float
 std::cout << add("generic", "lambdas") << std::endl; // for std::string
}
Enter fullscreen mode Exit fullscreen mode

mutable Specifier

mutable allows objects captured by value to be modified and use it's non-constant methods/functions in the specific lambda function.

#include <iostream>

int main() {

 int var = 5;

 auto change = [var]() mutable { var = 10; std::cout << var << std::endl;  };
 change();

 std::cout << var << std::endl; // var is 5
} 
Enter fullscreen mode Exit fullscreen mode

Examples

Nested Lambdas

A simple program which takes input and then determines if they are negative or not.

#include <iostream>

int main() {

    auto is_negative = [](int x) { return [](int y) { return y + 2; }((5) + x) <  0; }(7);
    std::cout << is_negative;

}
Enter fullscreen mode Exit fullscreen mode

High Order Functions

A simple program which takes a function to sort an array in the reverse order.

#include <iostream>
#include <algorithm>
#include <array>

int main() {

    std::array<int, 9> arr = {4, 6, 7, 5, 8, 0, 2, 3, 7 };
    std::sort(begin(arr), end(arr), [](int a, int b){ return a < b;});

    for (auto& i : arr) {
        std::cout << i << " ";
    }

}
Enter fullscreen mode Exit fullscreen mode

Lambdas with Templates

A program which uses templates and lambdas together.

#include <iostream>
#include <algorithm>
#include <array>

template<typename T>
void multi_by_two(std::array<T, 9>& arr) {
  std::for_each(arr.begin(), arr.end(), [](T& a){a *= 2;});
}

int main() {

    std::array<int, 9> arr = {4, 6, 7, 5, 8, 0, 2, 3, 7 };
    add_by_two(arr);

    for (auto& i : arr) {
        std::cout << i << " ";
    } 
}
Enter fullscreen mode Exit fullscreen mode

Code

All the code used in this article is available in this repo.

If someone has any doubt or something is misleading then do inform me by commenting below.

Top comments (2)

Collapse
 
banzyme2 profile image
ENDEESA

[=, &total] please explain what the = does on this line?

Collapse
 
delta456 profile image
Swastik Baranwal

It passes all objects by value.