std::function
è una classe che offre un'interfaccia per oggetti richiamabili come funzioni, puntatori a funzioni, espressioni lambda o oggetti con operator()
. Questa classe è parte della libreria standard C++.
Abbiamo bisogno di questa funzione per:
- Type erasure
- Container di funzioni
- Callback e gestione di eventi
- Polimorfismo funzionale
Espressioni lambda
In C++ ogni espressione lambda ha qualcosa di diverso, anche se due lambda hanno gli stessi tipi di parametro e di ritorno non si comporteranno allo stesso modo. Questa distinzione deriva dal fatto che le lambda sono essenzialmente una sorta di "zucchero sintattico" per le classi con operator()
definito e le loro catture contribuiscono a rendere unici i loro tipi.
auto lambda1 = [](int a) { return a * 2; };
auto lambda2 = [a](int b) { return a + b; };
// lambda1 e lambda2 hanno tipi diversi
Cancellazione di questi tipi
La motivazione per utilizzare std::function è di conservare oggetti richiamabili (funzioni, lambda) con tipi diversi in modo uniforme. Questo è utile quando si vuole conservare funzioni o lambda in un container o passarli come parametri come in un sistema di gestione attività.
#include <functional>
#include <iostream>
void esegui(std::function<int(int)> funzione) {
std::cout << funzione(5) << std::endl;
}
int principale() {
auto lambda1 = [](int x) { return x + 10; };
auto lambda2 = [x](int y) { return x * y; };
esegui(lambda1);
esegui(lambda2);
return 0;
}
Cancellazione dei tipi e costruttori:
Per cancellare dei tipi, std::function fornisce dei costruttori che accettano qualsiasi oggetto richiamabile (citati in precedenza) che soddisfi la sua verifica. Questo richiede l'uso di puntatori a funzione per richiamare l'oggetto richiamabile (perdonate il gioco di parole) e l'allocazione di spazio per le lambda o i dati dell'oggetto richiamabile. L'allocazione potrebbe avvenire nell'heap (area di memoria dove sono memorizzati gli oggetti e il loro stato) dato che le catture delle lambda possono avere dimensioni arbitrarie.
Discorso di ottimizzazione:
Un aspetto importante di std::function è l'ottimizzazione del buffer piccolo. Quando la lambda o l'oggetto invocabile è talmente piccolo da adattarsi allo spazio predefinito i dati possono essere allocati direttamente all'interno dell'oggetto std::function senza allocazione all'heap.
Meglio usare "using namespace std;" o "std::"?
Chiaramente in questo caso si parla di esempi complessi, per codici "semplici" using namespace std; può essere usato senza problemi.