Without C ++ 11, you cannot avoid specifying the type of function return.
template<typename R, typename F> R bar(F func) { return func(); } bar<int>(foo);
With the new features of C ++ 11 you can, however.
template<typename F> auto baz(F func) -> decltype(func()) { return func(); } baz(foo);
You can configure the function / functor as a parameter, instead of specifying that it should be a boost :: function.
void zero() {cout << "zero" << endl;} void one(int a) {cout << "one" << endl;} void two(int a, int b) {cout << "two" << endl;} template<typename F> void f(const F &func) { func(); } template<typename F, typename T0> void f(const F &func, T0 t0) { func(t0); } template<typename F, typename T0, typename T1> void f(const F &func, T0 t0, T1 t1) { func(t0, t1); }
This allows you to simply pass a pointer to a function.
f(zero); f(one, 1); f(two, 1, 2);
If you really need to use functions or bindings, you can pass this to the same interface.
// without specifying the function f(boost::bind(zero)); f(boost::bind(one, _1), 1); f(boost::bind(two, _1, _2), 1, 2); // or by specifying the object boost::function<void()> f0 = boost::bind(zero); boost::function<void(int)> f1 = boost::bind(one, _1); boost::function<void(int,int)> f2 = boost::bind(two, _1, _2); f(f0); f(f1, 1); f(f2, 1, 2);
As with the functor, which is typical for passing in a strict weak order in standard containers.
struct zoobies { void operator()() const {} }; f(zoobies());
There is no need to check the type of what you pass to it, only that it satisfies the interface. This is one of the reasons why C ++ templates are generally much more powerful than generics in other languages.
And for completeness ... If you really wanted to limit it to boost ::, here is an example.
template<typename T> void p(const boost::function<T> &func) { func(); } template<typename T, typename A0> void p(const boost::function<T> &func, A0 a0) { func(a0); } boost::function<void()> f0(zero); p(f0); boost::function<void(int)> f1(one, _1); p(f1, 1);
Update:
void foo() {cout << "zero" << endl;} void foo(int a) {cout << "one" << endl;} void foo(int a, int b) {cout << "two" << endl;}
boost :: bind works out of the box, even though the original function pointers have a big problem. Here foo is ambiguous.
f( (void(*)()) foo ); f( (void(*)(int)) foo, 1 ); f( (void(*)(int,int)) foo, 1, 2);
If you completely point to a function pointer, this will work, although this is not what someone wants to do.
With boost :: bind as proof, you must define arity from the calling convention f . If I get some time today, I will play with him.