Retinal lambda function?

Consider the following mute 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) , using the lambda function, to execute it on x , with (hopefully) no overhead. My question is: what would be equivalent with function as an installable member of MyClass ?

 class MyClass { public: inline double f(double x) { return _function(x); } // What are the setter and the type of the protected member _function ? }; 
+6
source share
2 answers

Lambda functions (as well as some other types of β€œcalled” functions) can be wrapped and stored using the std::function template std::function found in the <functional> header. Its template parameter is a function signature with syntax

 ReturnType(ArgumentType1, ArgumentType2, ...) 

so in your case the whole type of function wrapper will become

 std::function<double(double)> 

and thus your code will become

 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 "larger" than the wrapper for function pointers. As you may know, lambda functions can capture part of the context of a variable that needs to be stored somewhere. std::function does this transparently for you.

Note that std::function does not support overloaded signatures / template call operators for functors. When assigning a functor with a signature of a call operator, for example, T operator()(T value) , to std::function<double(double)> , it can be called only with this signature. Thus, there is no std::function<T(T)> (if T is not already known, for example, the template parameter of your class).


An alternative that may be more efficient in some cases (you need to check / profile it) is to make the entire class a template class with a function type parameter that is a template parameter. Then you can save the 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; }; 

To create such an object, you need to specify a template parameter, for example:

 auto myLambda = [](double x){ return x * 0.25; }; MyClass<decltype(myLambda)> myObject { myLambda }; 

To avoid these ugly syntax overheads, add the "maker" function, which uses template type deduction:

 template<typename Function> auto makeMyClass(Function && f) -> MyClass<Function> { return MyClass<Function>(f); } 

Then the code becomes more readable with the repetition of using auto :

 auto myLambda = [](double x){ return x * 0.25; }; auto myObject = makeMyClass(myLambda); 
+10
source

You will need to use the std::function shell, it is possible for the constructor to initialize it from the object called by the input:

 #include <functional> // <== REQUIRED FOR std::function class MyClass { public: template<typename F> MyClass(F&& f) : _function(std::forward<F>(f)) { } inline double f(double x) { return _function(x); } private: std::function<double(double)> _function; }; 

Please note that this may bring you some overhead at runtime, but the design is simple and flexible. If you cannot prove that these short-term overheads are a bottleneck for your software performance requirements, this runtime overhead should not be a concern.

+3
source

Source: https://habr.com/ru/post/945486/


All Articles