我有这样的模板功能:
template<class R> list<R> f(const boost::function<R()>&);
template<class R, class A0> list<R> f(const boost::function<R(T0)>&, list<A0>);
template<class R, class A0, class A1> list<R> f(const boost::function<R(T0)>&, list<A0>, list<A1>);
要运行其中一个,我需要编写例如:
int one() { return 1; }
int inc(int x) { return x + 1; }
list<int> l;
f<int>(one);
f<int, int>(inc, l);
我的目标是写下:
f(one);
f(inc, l);
我听说这可以通过某种模板签名专业化来实现,但我无法弄清楚如何。
答案 0 :(得分:2)
如果没有C ++ 11,你就无法避免指定函数的返回类型。
template<typename R, typename F>
R bar(F func) {
return func();
}
bar<int>(foo);
您可以使用新的C ++ 11功能。
template<typename F>
auto baz(F func) -> decltype(func()) {
return func();
}
baz(foo);
您可以将函数/仿函数模板化为参数,而不是尝试指定它必须是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);
}
这使您可以简单地传递函数指针。
f(zero);
f(one, 1);
f(two, 1, 2);
如果你需要实际使用函数或绑定,你可以将它传递到同一个界面。
// 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);
与仿函数一样,这对于将严格的弱排序行为传递给标准容器是典型的。
struct zoobies {
void operator()() const {}
};
f(zoobies());
它不必检查传递给它的类型,只需要它满足接口。这是C ++模板通常比其他语言中的泛型更强大的原因之一。
为了完整性......如果你确实想将它限制为boost :: function,这是一个例子。
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);
更新
void foo() {cout << "zero" << endl;}
void foo(int a) {cout << "one" << endl;}
void foo(int a, int b) {cout << "two" << endl;}
尽管原始函数指针存在更多问题,但是使用此方法,boost :: bind可以开箱即用。 foo在那里很暧昧。
f( (void(*)()) foo );
f( (void(*)(int)) foo, 1 );
f( (void(*)(int,int)) foo, 1, 2);
如果您完全指定了函数指针,那么它可以工作,尽管这不是任何人想要做的。
使用boost :: bind作为证据,您应该能够根据f
的调用约定来确定arity。如果我今天得到一些时间,我会玩它。