模板函数中的std :: function

Edm*_*und 2 c++ templates stl c++11

我试图编写一个模板函数,它可以接受函数作为参数并在之后调用它.该计划如下:

#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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我想std::plus<int>()可以推断std::function<int(int,int)>,但事实并非如此.那是为什么?GCC是gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)

Mar*_*cia 6

我想std :: plus()可以推导为std :: function

不可以.鉴于您已经传递了类型的对象,因此无法推断出std::plus<int>.

在您的情况下,您不需要使用std::function,因为通常您在存储可以使用特定签名调用的不同函数/函数对象时通常会使用它.

有了它,你可以让你的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;
}
Run Code Online (Sandbox Code Playgroud)

现场代码


至于什么@Jan邬达克已经评论说,__LINE__在总会导致相同的所有调用call,无论函数传递.