std::function în C++

Variabilă care poate ține orice funcție, lambda sau obiect apelabil cu o anumită semnătură.

Sintaxă
#include <functional>
std::function<TipRetur(Parametri...)> f = ceva_apelabil;

Ce face std::function

std::function<int(int, int)> poate ține orice se poate apela cu doi int și returnează int: o funcție obișnuită, o lambda (chiar cu captură) sau un obiect cu operator().

Este utilă când vrei să păstrezi funcții într-un container, să le trimiți ca parametri fără șabloane sau să le schimbi în timpul rulării (callback-uri, meniuri, reguli de calcul).

Un std::function gol aruncă std::bad_function_call la apel; verifică-l cu if (f). Are un cost mic (apel indirect, uneori alocare), așa că în cod foarte rapid se preferă șabloanele sau auto.

Ce returnează

Un obiect apelabil cu semnătura dată.

Exemple

Exemplul 1: Un meniu de operații

#include <functional>
#include <map>
#include <print>
#include <string>

int scade(int a, int b) { return a - b; }

int main() {
    std::map<std::string, std::function<int(int, int)>> operatii{
        {"adunare", [](int a, int b) { return a + b; }},
        {"scădere", scade},
        {"înmulțire", std::multiplies<int>{}},
    };

    for (const auto& [nume, op] : operatii) {
        std::println("{}: {}", nume, op(12, 4));
    }
}

Rezultat

adunare: 16
scădere: 8
înmulțire: 48

Exemplul 2: Callback și std::function gol

#include <functional>
#include <print>
#include <string>

struct Buton {
    std::string text;
    std::function<void()> laClic;

    void apasa() const {
        if (laClic) {
            laClic();
        } else {
            std::println("[{}] nu are acțiune", text);
        }
    }
};

int main() {
    int clicuri = 0;
    Buton salveaza{"Salvează", [&clicuri] { ++clicuri; std::println("Salvat (clic {})", clicuri); }};
    Buton ajutor{"Ajutor", nullptr};

    salveaza.apasa();
    salveaza.apasa();
    ajutor.apasa();
}

Rezultat

Salvat (clic 1)
Salvat (clic 2)
[Ajutor] nu are acțiune

Greșeli frecvente

  • Apelezi un std::function gol. Se aruncă std::bad_function_call; verifică înainte cu if (f).
  • Pui într-un std::function o lambda care capturează prin referință ([&]) o variabilă locală și o apelezi după ce funcția s-a terminat. Referința arată spre o variabilă distrusă.

Comenzi înrudite

  • lambda ([](){}): O funcție fără nume, scrisă direct acolo unde e folosită; poate „captura” variabile din jur.
  • std::bind: Creează o funcție nouă dintr-una existentă, fixând unele argumente sau schimbându-le ordinea.
  • std::invoke: Apelează orice lucru apelabil cu argumentele date, inclusiv pointeri la metode și la membri.
  • std::bind_front: Fixează primele argumente ale unei funcții și returnează o funcție care le primește doar pe restul.