You cannot call the generic std :: function element from a template class

When compiling the following code:

#include <functional> template <typename functionSignature> class Class { std::function<functionSignature> func; public: Class(const std::function<functionSignature>& arg) : func(arg) {} void callFunc() { func(); } }; void f(const int i) {} int main() { Class<void(const int)> a(std::bind(f, 10)); a.callFunc(); return 0; } 

The VS 2015 compiler generates the following error message on the sixth line:

 error C2064: term does not evaluate to a function taking 0 arguments. 

Now I believe that this is because the compiler thinks that functionSignature not, well, a function signature; the same error occurs when I create an instance and try to call operator() on std::function<int> instead of std::function<int()> , for example.

How can I guarantee that the template argument will always be the signature of the function, so that I can call operator() on std::function ?

+6
source share
3 answers

Your mistake:

 Class<void(const int)> a(std::bind(f, 10)); 

The Class::callFunc() function calls func() - that is, no arguments. The result of std::bind(f, 10) also a function that takes no arguments that are consistent with the template argument to the class template. Using Class<void(const int)> incompatible with using the class template and initialization.

The solution is easy: change the weird string to

 Class<void()> a(std::bind(f, 10)); 
+2
source

I suspect you want something like this:

 template <typename F> class Class; template<typename R, typename... P> class Class<R(P...)> { public: std::function<R(P...)> func; void callFunc(P... p) { func(p...); } }; 

Using partial specialization, you can easily determine the type you want.
As an example, you can use it like:

 Class<int(double)> c; 

Of course, I noticed that you do not have constructors for your class, so calling func is not a good idea, but it is pretty easy to define it and pass the correct function as an argument.

The following is a working and working example in which I used operator() to call a function:

 #include <functional> template <typename F> class Class; template<typename R, typename... P> class Class<R(P...)> { public: Class(std::function<R(P...)> f): func{f} { } void operator()(P... p) { func(p...); } private: std::function<R(P...)> func; }; void fn() { } int main() { std::function<void()> f = fn; Class<void()> c{f}; c(); } 
+6
source

Is this what you are trying to do?

http://ideone.com/fork/IZ0Z1A

If functionSignature is NOT a function, std :: function will cause errors when creating the class, but you can add a constructor and throw static_assert(std::is_function<functionSignature>::value == true," "); there static_assert(std::is_function<functionSignature>::value == true," "); if you want, I think.

 #include <functional> #include <iostream> template <typename functionSignature> class Class { public: std::function<functionSignature> func; void callFunc() { func(); } }; void f() { std::cout << "hello" << std::endl; } int main() { Class<decltype(f)> t {f}; t.callFunc(); return 0; } 
+1
source

All Articles