Any function as template argument

#include <iostream> void padd(int a, int b) { std::cout << a + b << std::endl; } void psub(int a, int b) { std::cout << a - b << std::endl; } template <??? op> class Foo { public: template<typename... Arguments> void execute(Arguments... args) { op(args ...); } }; int main() { auto f1 = Foo<padd>(); f1.execute(5, 6); // ideally would print 11 auto f2 = Foo<psub>(); f2.execute(5, 6); // ideally would print -1 return 0; } 

I am trying to understand how to bind functions (and, if possible, template functions) as template parameters in C ++.

Be that as it may, I do not know if this is possible.

The kicker here is that function signatures are not guaranteed equally.

edit : thanks @sehe and @Potatoswatter, my current solution is: http://ideone.com/0jcbUi . If necessary, write an answer.

+7
c ++ templates variadic-functions
source share
3 answers

Thanks to Potatoswatter and help in the C ++ Lounge, and here I formulated a solution to my question.

 #include <iostream> #include <functional> template <typename func_t, func_t func> struct Foo { template <typename... Arguments> void execute(Arguments... args) { func(args ...); } }; template <typename T, typename func_t, func_t func> struct FooMember { T member; FooMember(T member) : member(member) {} template <typename... Arguments> void execute(Arguments... args) { std::function<void(T&, Arguments ...)> f(func); f(this->member, args ...); } }; struct Bar { int z; Bar(int z) : z(z) {} void add(int x, int y) { std::cout << x + y + z << std::endl; } }; void padd(int x, int y, int z) { std::cout << x + y + z << std::endl; } int main() { auto a = Foo<decltype(&padd), &padd>(); auto b = FooMember<Bar, decltype(&Bar::add), &Bar::add>(Bar(2)); a.execute(4, 5, 6); // prints 4+5+6 : 15 b.execute(4, 5); // prints 4+5+az : 4+5+2 : 11 return 0; } 
0
source share

I suggest letting the compiler worry about resolving function signatures when necessary. http://ideone.com/ZeLt1E (code included below).

If you need to adapt overload sets or polymorphic interfaces, I would also suggest looking at BOOST_PHOENIX_ADAPT_FUNCTION.

Change In response to comments: Here is an example of how you can use strictly functional pointers and / or element pointer functions directly as function arguments. This is another extreme approach: http://ideone.com/120Ezs

Full code

 #include <iostream> template <typename F> struct Foo { Foo(F&& f) : f(std::forward<F>(f)) {} template<typename... Arguments> void execute(Arguments... args) { f(args ...); } private: F f; }; template <typename F> Foo<F> make_foo(F&& f = F()) { return {f}; } void padd(int a, int b) { std::cout << a + b << std::endl; } void psub(int a, int b) { std::cout << a - b << std::endl; } int main() { auto f = make_foo(padd); f.execute(5, 6); make_foo(psub).execute(5, 6); return 0; } 
+6
source share

Just make an observation that you do not have or want a run-time state. Partially output from your comments in a C ++ chat.

Functions do not have unique types. If you want to generate a unique type that captures which function should be called, use the template template for this.

 template< typename t, tv > struct constant { typedef t type; static constexpr t value = v; operator t () { return v; } }; 

This is essentially the same as std::integral_constant , but removes integral from the name to save confusion. (Actually, I only tested this with std::integral_constant if you want to be cleaner for you.)

Now you can assign functions to individual types, which are defaultless constructive functors.

 typedef constant< decltype( & padd ), padd > padd_type; typedef constant< decltype( & psub ), psub > psub_type; padd_type()( 2, 3 ); // prints 5 

Note that stateless lambdas are converted to function pointers and are compatible with such a system, but you need to explicitly specify the type of the function pointer. Only decltype will not meet you.

+3
source share

All Articles