C++/Funkcje anonimowe

< C++

Od początku istnienia C++, możliwy był zapis programów w postaci funkcji wolnych lub składowych klas. Nie istniała jednak możliwość tworzenia funkcji w innych formach, np. funkcji lokalnych. Można było posiłkować się klasami zagnieżdżonymi, ale było zwykle dalekie od wygody.

Standard C++11 dodał bardzo ważną możliwość tworzenia funkcji anonimowych, czasem nazywanych lambdami. Funkcje anonimowe mogą być przekazywane jako parametry, mogą być przypisywane do zmiennych itp. Regułą jest, że funkcje tego typu są krótkie.

Składnia

edytuj

Funkcja anonimowa składa się z czterech elementów:

  1. definicji domknięcia (ang. closure),
  2. listy parametrów,
  3. opcjonalnego typu zwracanego,
  4. bloku kodu.
[domknięcie](parametry) -> typ zwracany {
    
    kod
}

Domknięcie określa jakie zmienne i w jakim trybie są dostępne bezpośrednio w danej funkcji. W najprostszym przypadku domknięcie może być puste, wówczas funkcja nie ma dostępu do żadnych obiektów zdefiniowanych w zakresie, który ją zawiera. Najprościej można wskazać, że wszystkie obiekty są dostępne przez referencję, pisząc [&]; można również wskazać, że wszystkie dostępne są to kopie, [=]. Można też wyliczyć tylko te zmienne, które są rzeczywiście potrzebne, np. [x, y]. Zmienne domyślnie są dostępne tylko do odczytu, ale jeśli poprzedzimy je znakiem & zostaną przekazane przez referencję i będzie można je zmieniać.

Lista parametrów w niczym nie różni się od listy parametrów zwykłej funkcji.

Typ zwracany jest opcjonalny, jeśli nie zostanie podany kompilator wydedukuje typ funkcji na podstawie instrukcji return w kodzie.

Blok kodu może zawierać dowolne instrukcje, dostępne są w nim wszystkie obiekty zdefiniowane w domknięciu i na liście parametrów.

#include <iostream>
#include <string>

template <typename Funkcja>
double policz(Funkcja f) {

    return f(7, 3);
}

int main() {

    double wspolczynnik = 1.25;
    std::string napis = "test";

    double wynik = policz(
        [wspolczynnik, &napis](int a, int b) {
            napis = "zmieniony";
            return (a+b) * wspolczynnik;
        }
    );

    std::cout << "wynik = " << wynik << '\n';
    std::cout << "napis = " << napis << '\n';
}

Wynikiem będzie:

wynik = 12.5
napis = zmieniony

W kolejnym przykładzie funkcja anonimowa jest przypisywana do zmiennej i wielokrotnie wywoływana w kodzie funkcji.

#include <iostream>

int main() {

    int liczba_wywolan = 0;

    auto wyswietl = [&](const std::string& napis) {
        std::cout << "'" << napis << "'" <<  '\n';

        liczba_wywolan += 1;
    };

    wyswietl("witaj");
    wyswietl("wiki");
    wyswietl("books");

    std::cout << "liczba wywołań = " << liczba_wywolan << '\n';
}