# Använder du lambda-uttryck i C++?

15 april 2025 | https://www.ribomation.se/blog/2025/anvander-du-lambda-uttryck-i-c++/

En av de mest uppskattade nyheterna i Modern C++ är utan tvekan lambda-uttryck. När de introducerades i C++11, så innebar det ett stort steg mot mer uttrycksfull och koncis kod. Lambda-uttryck gör det möjligt att deklarera funktioner direkt i kontexten där de används, vilket gör att man slipper definiera hjälpfunktioner på andra ställen i koden. Här nedan kommer jag att gå igenom syntaxen, visa flera exempel, samt peka ut några viktiga fördelar.

### En första titt

Låt oss börja med ett enkelt exempel. Vi vill sortera en lista med strängar, men på ett specialanpassat sätt. Med ett lambda-uttryck kan vi skriva:

```cpp
#include <vector>
#include <string>
#include <algorithm>

int main() {
    auto names = std::vector<std::string>{"Eva", "Anna", "Kalle", "Bo"};

    std::sort(std::begin(names), std::end(names),
              [](std::string const& a, std::string const& b) {
                  return a.size() < b.size();
              });
}
```

Här definieras en anonym funktion inline, som tar två strängar och jämför deras längd. Funktionen skickas som tredje argument till `std::sort`. Notera hur mycket smidigare detta är än att behöva skapa en separat jämförelsefunktion någon annanstans i filen.

### Syntaxen

Syntaxen för lambda ser ut så här:

```cpp
[capture](parameter-list) -> return-type { body };
```

De flesta delar kan utelämnas om de inte behövs. Här är några varianter:

```cpp
[]() { std::cout << "Hello\n"; }();                     // Ingen parameter
[](int x) { return x * x; };                            // Med parameter
[=](int x) { return x + offset; };                      // Fångar variabler med värde
[&](int x) { total += x; };                             // Fångar variabler med referens
```

### Användning med standardalgoritmer

Lambda-uttryck kommer verkligen till sin rätt när de används tillsammans med algoritmer i STL. Här är ett par exempel:

```cpp
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    auto values = std::vector<int>{1, 3, 5, 7, 9, 10, 12};

    auto even_count = std::count_if(std::begin(values), std::end(values),
                                    [](int x) { return x % 2 == 0; });

    std::cout << "# even: " << even_count << "\n";
}
```

Eller varför inte filtrera ut värden:

```cpp
#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    auto values = std::vector<int>{1, 2, 3, 4, 5, 6};
    auto evens  = std::vector<int>{};

    std::copy_if(std::begin(values), std::end(values), std::back_inserter(evens),
                 [](int x) { return x % 2 == 0; });

    for (auto val : evens) std::cout << val << " ";
}
```

### Lambdas som funktionsobjekt

Ibland behöver man spara ett lambda för senare användning. Det går utmärkt:

```cpp
auto is_positive = [](int x) { return x > 0; };

if (is_positive(42)) std::cout << "Positive\n";
```

Man kan även skicka lambdas till funktioner som tar std::function:

```cpp
#include <functional>

void do_twice(const std::function<void()> &f) { f(); f(); }

int main() {
    auto count = 0;
    do_twice( [&]{ count++; } );
    std::cout << count << "\n";  // prints 2
}
```

### Generiska lambdas

Från och med C++14 kan lambdas vara generiska, d.v.s. de kan ta parametrar av vilken typ som helst:

```cpp
auto print = [](const auto& value) { std::cout << value << "\n"; };

print(42);
print("hej");
print(3.14);
```

Detta är kraftfullt, särskilt i generisk kod eller när du arbetar med templates.

### Mutable lambdas

Som standard är lambdas som fångar variabler med värde (\[=\]) const, d.v.s. de kan inte ändra de fångade värdena. Om man vill tillåta ändring krävs mutable:

```cpp
auto counter = [n = 0]() mutable { return ++n; };

std::cout << counter() << counter() << counter() << "\n"; // prints 123
```

### Avslutande reflektioner

Lambda-uttryck har blivit ett oumbärligt verktyg i min C++-verktygslåda. De gör koden kompaktare, tydligare och mer lokalt begriplig. Särskilt i kombination med auto, std::function och ranges (C++20) uppstår en elegant programmeringsstil som jag uppriktigt tycker är både kraftfull och njutbar att använda.

Och precis som alltid i Modern C++, så handlar det om att använda rätt verktyg för rätt situation. Lambda-uttryck är ett av de verktygen som jag gärna sträcker mig efter – ofta.

Min katt tycker också om lambda. Men han använder bara den som liggplats på tangentbordet.
