Using lambdas in a template class

I am trying to use a template class with a lambda function parameter. However, I do not understand how to pass the parameter. Here is what I have tried so far:

#include <iostream> using namespace std; template <class F> class A { public: int f(int i) { return F(i); //* } }; int main(int argc, const char * argv[]) { auto f = [](int i){return i+5;}; A<decltype(f)> a; cout << af(5); return 0; } 

I get an error in the marked line.

Can anyone help?

+8
c ++ lambda c ++ 11 templates
source share
3 answers

Your example does not work, because F is a type, not a callable. The next step is to create an instance by creating a member variable.

 template <class F> class A { F function; public: int f(int i) { return function(i); } }; 

However, this still will not work, as the lambda default constructors are removed. This means that we need another way to build the function . This can be achieved by passing an argument to constructor A

 template<typename F> class A { F function; public: A(const F& f) : function(f) {} int f(int i) { return function(i); } }; // ... auto f = [](int i) { return i+5; }; A<decltype(f)> a(f); 

This uses the lambda copy constructor, which is not removed.

Living example

If you want it to work with any lambda, you can add some more magic.

 template<typename F> class A { F function; public: A(const F& f) : function(f) {} template<typename ...Args> auto f(Args... args) -> std::result_of_t<F(Args...)> { return function(std::forward<Args>(args)...); } }; 

Living example

+6
source share

If you really want to use the template to accept any signature of any type, then the implementation should be something like this:

 class A { public: template<typename F, typename... Args> auto f(F&& funct, Args&&... args) { return funct(std::forward<Args...>(args)...); } }; 

This is because you said in the comment:

Q: Is type F in the class required only for method F ?
A: method only.

Because of this, it is useless to have a template class when you can just have a template method.

Here is an example of how to call a method that simply calls the "called object with its parameters", in this case a lambda function:

 int main(int argc, char* argv[]) { A a; af([](int i) -> int { return i + 5; }, 12); // |------callable object-----------| |argument of function| return 0; } 

In practice, the F method accepts the β€œcalled object” as the first argument and asks for any parameters to call the first argument as additional arguments.


Additional notes:

If you want to pass a certain type of function signature to the F method, for example: int (*)(int) , then you can avoid using a template and pass an object of type std::function .

This is just an example:

 #include <functional> class A { public: // method g accept a function which get a integer and return an integer as well. int g(std::function<int(int)> funct, int arg) { return funct(arg); } }; 
+3
source share

It is not enough to define A as being inherited from or somehow containing a lambda function, you still have to initialize the subobject when creating an instance of A
For this, as an example, you can inherit lambda and use A as the called object.
This follows a minimal working example:

 #include <iostream> using namespace std; template <class F> class A: public F { public: A(F f): F(f) {} }; int main() { auto f = [](int i){return i+5;}; A<decltype(f)> a{f}; cout << a(5); return 0; } 

You do not need to define any function f to execute lambda.
In any case, if you want the function f called af(5) , you can define it as follows:

 int f(int i) { return F::operator()(i); } 

Or as it should:

 int f(int i) { return (*this)(i); } 
+2
source share

All Articles