一个C ++ 11模板函数,它接受一个函数对象参数,例如:
template <typename F, typename T>
auto foo(F f, T x) -> decltype(f(x)) {
return f(x);
}
可以采取如下函数:
int succ(int i) { return i+1; }
并将foo
应用于succ
并获得10的结果:
foo(succ,9);
重载的函数不起作用,例如,sin
失败:
foo(std::sin,0.5);
在GCC(4.7)中,“无法推断出模板参数F”。
(提供sin<double>
仅与btw的复杂类型有关。)是的,我可以直接构建它:
template <typename T>
struct Sin {
T operator()(T x) { return std::sin(x); }
};
一点点:
foo(Sin<double>(),0.5);
我的问题是,是否存在避免需要这种新定义的替代方案;仅在foo
的电话会址使用?
答案 0 :(得分:8)
对于函数指针,您只需让用户键入签名:
template<class F, class T>
void foo(F f, T x){
f(x);
}
void bar(int){}
void bar(double){}
int main(){
foo<void(int)>(bar, 5);
}
替换后 foo
将为void foo(void f(int), int x)
,与foo(void (*f)(int), int x)
相同。这提供了所谓的“调用上下文”,允许编译器选择正确的重载。显然,只有当第一个模板参数是函数时,这才有效。要解决这个限制,并让它看起来更好(imho,至少),你可以提供一个简单的帮助函数:
template<class F>
auto get_overload(F f) -> decltype(f) { return f; }
实际上,你只能重载参数类型,但是你不能剔除让用户输入返回类型的需要,因为这会再次禁用调用上下文,因为需要推导出一种类型。 / p>
由于您很可能(或肯定)只想要这个函数指针,您可以将其更改为:
template<class F>
F* get_overload(F* f){ return f; }
它仍然完全相同。第一个版本不能仅将F
作为返回类型的唯一原因是,如果您使用F
调用void(int)
,则get_overload<void(int)>(bar)
为void(int)
,且标准不会t允许你返回函数(是的,这是一个函数类型)。功能指针转换(void(*)(int)
- &gt; get_overload
)部分的功能仅适用于参数。
由于无论出于何种原因@VJovic删除了他的答案,我只会编辑:
您实际上可以使用简单的lambda而不是foo([](int i){ return bar(i); }, 5);
函数。它的性格大致相同,更方便,更清晰。它也会更高效,因为不涉及(函数)指针,编译器完全能够内联调用。
{{1}}