捕获的变量有问题,但我无法弄清楚是什么.我得到的错误是
error: no matching function for call to ‘applyFunc(int, main()::<lambda(int)>)’
applyFunc<int,int>(0,[=](int z) -> int{return z + xx;}); //error!
Run Code Online (Sandbox Code Playgroud)
什么是错的任何见解?
//given input x and function func, return func(x)
template <typename T, typename U>
U applyFunc( T x, U func(T) )
{
return func(x);
}
int main()
{
int xx = 2;
applyFunc<int,int>(0,[](int x) -> int {return x + 1;}); //no error
applyFunc<int,int>(0,[=](int z) -> int{return z + xx;}); //error!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:修复<functional>中的函数对象.
#include <functional>
template <typename RET, typename INPUT>
RET applyFunc( INPUT x, std::function<RET(INPUT)> func )
{
return func(x);
}
int aFunc(int x)
{
return x;
}
int main()
{
int xx = 4;
applyFunc<int,int>(0,[](int x) -> int {return x + 1;});
applyFunc<int,int>(0,[=](int z) -> int{return z + xx;});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您的参数func被声明为常规函数指针.Lambdas不是常规功能.然而lambdas可以转换为常规函数指针,但前提是它们具有空捕获子句.
LAMBDA
[](int x) -> int {return x + 1;}
Run Code Online (Sandbox Code Playgroud)
具有空捕获子句,这使得它可以转换为函数指针类型int (*)(int).
LAMBDA
[=](int z) -> int{return z + xx;}
Run Code Online (Sandbox Code Playgroud)
具有非空捕获子句,这意味着它不能转换为常规函数指针.
您的使用想法std::function将使您的代码编译和工作.然而,这种方法存在固有的低效率.std::function是基于运行时多态性的类型擦除技术的实现.其主要目的之一是促进从编译时多态转换到运行时多态,从而减少代码的"模板化".基本上,通过使用std::function你同意隐藏在std::function实现中的运行时开销,以减少模板引起的代码膨胀.
此问题不适用于您的特定代码.您的模板函数很小,并且在每个方面都依赖于编译时参数.你的函数纯粹是概念性的,应该在结果代码中完全消解(消失).在这种情况下,您希望它通过编译时多态来工作.引入std::function它只是为了使它编译看起来不是正确的想法.这是用大炮射击麻雀并支付头顶费用.
你可以做什么(作为第一步)只是为仿函数类型添加另一个模板参数
template <typename T, typename U, typename F>
U applyFunc( T x, F func )
{
return func(x);
}
Run Code Online (Sandbox Code Playgroud)
作为第二个步骤,你会立即注意到模板参数U现在是过度的:它是由组合隐含带来了T和F.通过从中提取此类型,F您可以将模板重写为
template <typename T, typename F>
std::result_of_t<F(T)> applyFunc( T x, F func )
{
return func(x);
}
Run Code Online (Sandbox Code Playgroud)
(这可以通过使用该语言的"完美转发"功能进一步改进.)
请注意,这也可以使编译器完全扣除函数模板参数,因此您不必再明确指定它们
int xx = 2;
applyFunc(0,[](int x) { return x + 1; });
applyFunc(0,[=](int z) { return z + xx; });
Run Code Online (Sandbox Code Playgroud)
我们还可以注意到,我们甚至可以尝试摆脱T模板参数(从中提取F),但我不会这样做.保持T灵活性使模板支持函数重载的自然概念.
| 归档时间: |
|
| 查看次数: |
372 次 |
| 最近记录: |