简体   繁体   English

模板函数中的std :: function

[英]std::function in template function

I was trying to write a template function which can accept functor as parameter and call it afterwards. 我试图编写一个模板函数,它可以接受仿函数作为参数并在之后调用它。 The program is as follows: 该计划如下:

#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;
}

The G++ compplains: 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

I suppose std::plus<int>() could be deduced to std::function<int(int,int)> , but it didn't. 我想std::plus<int>()可以推导到std::function<int(int,int)> ,但它没有。 Why was that? 那是为什么? GCC is gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC) GCC是gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)

I suppose std::plus() could be deduced to std::function 我想std :: plus()可以推导为std :: function

No. It could not be deduced given that you have passed an object of type std::plus<int> . 不可以。鉴于您已经传递了std::plus<int>类型的对象,因此无法推断出。

In your case, you do not need to use std::function , as generally you would mostly use it when storing different functions/function objects that can be called with a specific signature. 在您的情况下, 您不需要使用std::function ,因为通常在存储可以使用特定签名调用的不同函数/函数对象时通常会使用它。

With that, you can just have your call function accept the function/function object directly, with its original type deduced, without using std::function . 有了它,你可以让你的call函数直接接受函数/函数对象,推导出它的原始类型,而不使用std::function Also, you might also want to use perfect forwarding when accepting the parameters and use std::forward when passing them as arguments to the function/function object. 此外,您可能还希望在接受参数时使用完美转发,并在将它们作为参数传递给函数/函数对象时使用std::forward You should also use the return type of your function as the return type of call . 您还应该使用函数的返回类型作为返回call类型。 Use C++11's trailing return type with decltype for that. 使用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;
}

LIVE CODE 现场代码


As what @Jan Hudec has commented , __LINE__ in there will always result the same in all calls to call , whatever function is passed. 至于什么@Jan邬达克也评论说__LINE__中总会导致相同的所有呼叫call ,无论函数传递。

It can't deduce the template arguments. 它无法推断出模板参数。

I would recommend changing the function signature like so: 我建议更改功能签名,如下所示:

template<typename F, typename... Args>
auto call(F fun, Args... args )
    -> decltype( fun(args...) )

Most implicit conversions are not considered when deducing template arguments. 在推导模板参数时,不会考虑大多数隐式转换。 Certainly not user-defined ones. 当然不是用户定义的。 So even if plus is convertible to function , it doesn't make a difference. 因此即使plus可以转换为function ,它也没有什么区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM