std::invoke în C++

Apelează orice lucru apelabil cu argumentele date, inclusiv pointeri la metode și la membri.

Sintaxă
#include <functional>
template<class F, class... Args>
constexpr std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... argumente);

Ce face std::invoke

Pentru o funcție sau o lambda, std::invoke(f, a, b) este la fel ca f(a, b). Diferența apare la pointerii la membri: std::invoke(&Clasa::metoda, obiect, a) apelează obiect.metoda(a), iar std::invoke(&Clasa::camp, obiect) returnează obiect.camp.

Se folosește în cod generic, care primește „ceva apelabil” de la utilizator și trebuie să funcționeze cu toate formele. Algoritmii din std::ranges folosesc std::invoke pentru proiecții.

Parametri

Parametru Descriere
f Funcția, lambda, obiectul apelabil sau pointerul la membru.
argumente Argumentele; la pointerii la membri, primul este obiectul.

Ce returnează

Rezultatul apelului.

Exemple

Exemplul 1: Funcții, metode și câmpuri

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

struct Produs {
    std::string nume;
    double pret;
    double cuReducere(double procent) const { return pret * (1 - procent / 100); }
};

int dublu(int x) { return 2 * x; }

int main() {
    Produs p{"Laptop", 3000};

    std::println("{}", std::invoke(dublu, 21));
    std::println("{}", std::invoke(&Produs::cuReducere, p, 10));
    std::println("{}", std::invoke(&Produs::nume, p));
}

Rezultat

42
2700
Laptop

Exemplul 2: O funcție generică

aplicaTuturor acceptă și o lambda, și un pointer la câmp.

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

struct Elev { std::string nume; double medie; };

template <class F>
void aplicaTuturor(const std::vector<Elev>& elevi, F f) {
    for (const auto& e : elevi) {
        std::print("{}  ", std::invoke(f, e));
    }
    std::println();
}

int main() {
    std::vector<Elev> elevi{{"Ana", 9.5}, {"Dan", 8.25}};
    aplicaTuturor(elevi, &Elev::nume);
    aplicaTuturor(elevi, [](const Elev& e) { return e.medie >= 9; });
}

Rezultat

Ana  Dan  
true  false

Greșeli frecvente

  • Încerci să apelezi un pointer la metodă direct: (&Produs::cuReducere)(p, 10). Nu compilează; sintaxa corectă este (p.*ptr)(10) sau, mai simplu, std::invoke(ptr, p, 10).

Comenzi înrudite

  • std::function: Variabilă care poate ține orice funcție, lambda sau obiect apelabil cu o anumită semnătură.
  • std::mem_fn: Transformă un pointer la metodă sau la câmp într-o funcție obișnuită care primește obiectul ca argument.
  • std::bind: Creează o funcție nouă dintr-una existentă, fixând unele argumente sau schimbându-le ordinea.