Consider the following dumb example :
class MyClass
{
public:
template <class Function>
inline double f(double x, Function&& function)
{
return function(x);
}
};
With this class, I can call MyClass::f(x, function)
, with a lambda function to execute it on x
, with (I hope) no overhead. My question is : what would be the equivalent with the function
as a settable member of the MyClass
?
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
// What are the setter and the type of the protected member _function ?
};
To summarize: If the purpose of the lambda expression is solely to pass a parameter to an instance method, then you may replace it with a method reference on the instance. If the pass-through is to a static method, then you may replace it with a method reference on the class.
A lambda expression can't define any new scope as an anonymous inner class does, so we can't declare a local variable with the same which is already declared in the enclosing scope of a lambda expression. Inside lambda expression, we can't assign any value to some local variable declared outside the lambda expression.
Interface BiConsumer<T,U> Represents an operation that accepts two input arguments and returns no result. This is the two-arity specialization of Consumer . Unlike most other functional interfaces, BiConsumer is expected to operate via side-effects.
Lambda functions (as well as some other types of "callable" functions) can be wrapped and stored using the std::function
template class, found in the <functional>
header. Its template parameter is a function signature with the syntax
ReturnType(ArgumentType1, ArgumentType2, ...)
so in your case the whole function wrapper type becomes
std::function<double(double)>
and thus, your code becomes
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
is "more" than a wrapper for function pointers. As you might know, lambda functions can capture part of the variable context, which needs to be stored somewhere. std::function
does this for you transparently.
Note that std::function
does not support overloaded signatures / templated call operators for functors. When assigning a functor with a call-operator signature like T operator()(T value)
to a std::function<double(double)>
, it can only be called with this signature. So there is no std::function<T(T)>
(unless T
is already known, such as a template parameter of your class).
An alternative which might be more efficient in some cases (you need to benchmark / profile it), is to make your whole class a template class with the function type parameter being the template parameter. Then you can store a function as a member:
template<typename Function>
class MyClass
{
public:
MyClass(Function && f) :
_function(f)
{}
inline double f(double x)
{
return _function(x);
}
private:
Function _function;
};
In order to create such an object, you need to specify the template parameter, like this:
auto myLambda = [](double x){ return x * 0.25; };
MyClass<decltype(myLambda)> myObject { myLambda };
To avoid this ugly syntactic overhead, add a "maker" function which takes advantage of template type deduction:
template<typename Function>
auto makeMyClass(Function && f) -> MyClass<Function> {
return MyClass<Function>(f);
}
Then, the code becomes more readable, with use of auto
again:
auto myLambda = [](double x){ return x * 0.25; };
auto myObject = makeMyClass(myLambda);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With