我试图编写一个模板函数,它可以接受functor作为参数并在之后调用它。该计划如下:
#include <iostream>
#include <functional>
using namespace std;
template<typename R, typename... Args>
R call(function<R(Args...)> fun, Args... args)
{
cout << "call@ " << __LINE__ <<endl;
return fun(args...);
}
int main()
{
cout << call(std::plus<int>(),1,2) <<endl;
return 0;
}
G ++ compplains:
g++ -c -Wall -std=c++0x -I../include a.cpp -o a.o
a.cpp: In function ‘int main()’:
a.cpp:16:38: error: no matching function for call to ‘call(std::plus<int>, int, int)’
a.cpp:16:38: note: candidate is:
a.cpp:7:3: note: template<class R, class ... Args> R call(std::function<_Res(_ArgTypes ...)>, Args ...)
a.cpp:7:3: note: template argument deduction/substitution failed:
a.cpp:16:38: note: ‘std::plus<int>’ is not derived from ‘std::function<_Res(_ArgTypes ...)>’
make: *** [a.o] Error 1
我认为std::plus<int>()
可以推断为std::function<int(int,int)>
,但事实并非如此。那是为什么?海湾合作委员会是gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)
答案 0 :(得分:6)
我认为std :: plus()可以推导为std :: function
没有。鉴于您已传递std::plus<int>
类型的对象,无法推断出。
在您的情况下,您不需要使用std::function
,因为在存储可以使用特定签名调用的不同函数/函数对象时,通常会使用它。< / p>
通过这种方式,您可以让call
函数直接接受函数/函数对象,并推导其原始类型,而不使用std::function
。此外,您可能还希望在接受参数时使用完美转发,并在将它们作为参数传递给函数/函数对象时使用std::forward
。您还应该使用函数的返回类型作为call
的返回类型。使用C ++ 11的尾随返回类型decltype
。
#include <iostream>
#include <functional>
using namespace std;
template<typename R, typename... Args>
auto call(R fun, Args&&... args) -> decltype(fun(std::forward<Args>(args)...))
{
cout << "call@ " << __LINE__ <<endl;
return fun(std::forward<Args>(args)...);
}
int main()
{
cout << call(std::plus<int>(),1,2) <<endl;
return 0;
}
正如@Jan Hudec commented __LINE__
中的call
,{{1}}的所有调用总是会产生相同的结果,无论函数是什么传递。
答案 1 :(得分:2)
它无法推断出模板参数。
我建议更改功能签名,如下所示:
template<typename F, typename... Args>
auto call(F fun, Args... args )
-> decltype( fun(args...) )
答案 2 :(得分:0)
在推导模板参数时,不会考虑大多数隐式转换。当然不是用户定义的。因此,即使plus
可转换为function
,也无法发挥作用。