Le funzioni lambda (così come altri tipi di funzioni "callable") possono essere spostate e memorizzate utilizzando la classe di modello std::function
, trovata nell'intestazione <functional>
. Il suo parametro di modello è una firma di funzione con la sintassi
ReturnType(ArgumentType1, ArgumentType2, ...)
Quindi nel tuo caso tutto il tipo di funzione wrapper diventa
std::function<double(double)>
e, quindi, il codice diventa
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
void setFunction(std::function<double(double)> && f)
{
_function = f;
}
private:
std::function<double(double)> _function;
};
std::function
è " più "di un wrapper per i puntatori di funzione. Come saprai, le funzioni lambda possono acquisire parte del contesto delle variabili, che deve essere memorizzato da qualche parte. std::function
fa questo per te in modo trasparente.
Nota che std::function
non supporta le firme sovraccaricate/operatori di chiamata basati su modelli per i funtori. Quando si assegna un funtore con una firma dell'operatore di chiamata come T operator()(T value)
a std::function<double(double)>
, può essere chiamato solo con questa firma. Quindi non esiste lo std::function<T(T)>
(a meno che non sia noto lo T
, ad esempio un parametro del modello della classe).
Un'alternativa che potrebbe essere più efficiente, in alcuni casi (è necessario punto di riferimento/profilo it), è quello di rendere tutta la classe una classe template con il parametro tipo di funzione è il parametro di template.Poi si può memorizzare una funzione come membro:
template<typename Function>
class MyClass
{
public:
MyClass(Function && f) :
_function(f)
{}
inline double f(double x)
{
return _function(x);
}
private:
Function _function;
};
Al fine di creare un oggetto del genere, è necessario specificare il parametro del modello, in questo modo:
auto myLambda = [](double x){ return x * 0.25; };
MyClass<decltype(myLambda)> myObject { myLambda };
Per evitare questo overhead sintattica brutto, aggiungere una funzione "maker" che sfrutta tipo di modello deduzione:
template<typename Function>
auto makeMyClass(Function && f) -> MyClass<Function> {
return MyClass<Function>(f);
}
Poi, il codice diventa più leggibile, con l'utilizzo di auto
ancora:
auto myLambda = [](double x){ return x * 0.25; };
auto myObject = makeMyClass(myLambda);
potrebbe essere qualsiasi cosa che prende un singolo doppio e restituisce un double. Potresti usare 'std :: function'. –
juanchopanza