C++ 什么';这个(简单的)lambda函数有什么问题?

C++ 什么';这个(简单的)lambda函数有什么问题?,c++,c++11,lambda,C++,C++11,Lambda,捕获的变量有问题,但我不知道是什么。我得到的错误是 error: no matching function for call to ‘applyFunc(int, main()::<lambda(int)>)’ applyFunc<int,int>(0,[=](int z) -> int{return z + xx;}); //error! 错误:调用“applyFunc(int,main():)”时没有匹配的函数 applyFunc(0,[=](intz)-

捕获的变量有问题,但我不知道是什么。我得到的错误是

error: no matching function for call to ‘applyFunc(int, main()::<lambda(int)>)’
  applyFunc<int,int>(0,[=](int z) -> int{return z + xx;}); //error!
错误:调用“applyFunc(int,main():)”时没有匹配的函数
applyFunc(0,[=](intz)->int{returnz+xx;})//错误!
有什么问题吗

//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;
}
//给定输入x和函数func,返回func(x)
模板
U applyFunc(tx,U func(T))
{
返回func(x);
}
int main()
{
int xx=2;
applyFunc(0,[](int x)->int{return x+1;});//无错误
applyFunc(0,[=](intz)->int{return z+xx;});//错误!
返回0;
}
编辑:使用中的函数对象进行修复

#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;
}
#包括
模板
RET applyFunc(输入x,标准::函数func)
{
返回func(x);
}
int aFunc(int x)
{
返回x;
}
int main()
{
int xx=4;
applyFunc(0,[](int x)->int{return x+1;});
applyFunc(0,[=](intz)->int{returnz+xx;});
返回0;
}

您的参数
func
被声明为常规函数指针。lambda不是常规函数。然而,lambda可以转换为常规函数指针,但前提是它们具有空的capture子句

兰姆达

[](int x) -> int {return x + 1;}
[=](int z) -> int{return z + xx;}
具有空的capture子句,这使得它可以转换为函数指针类型
int(*)(int)

兰姆达

[](int x) -> int {return x + 1;}
[=](int z) -> int{return z + xx;}
具有非空的capture子句,这意味着它不能转换为常规函数指针


您使用
std::function
的想法将使您的代码能够编译并工作。然而,这种方法存在固有的低效性
std::function
是基于运行时多态性的类型擦除技术的实现。其主要目的之一是促进从编译时多态性到运行时多态性的转换,从而减少代码的“模板化”。基本上,通过使用
std::function
您同意
std::function
实现中隐藏的运行时开销,以减少模板导致的代码膨胀

此问题不适用于您的特定代码。模板函数很小,在各个方面都依赖于编译时参数。您的函数纯粹是概念性的,应该完全溶解(消失)在结果代码中。在这种情况下,您希望它通过编译时多态性工作。引入
std::function
只是为了让它编译,这看起来不是一个正确的想法。这是用加农炮射杀麻雀并支付头顶费用

您可以做的(作为第一步)只是为functor类型添加另一个模板参数

template <typename T, typename U, typename F>
U applyFunc( T x, F func )
{
    return func(x);
}
(这可以通过使用该语言的“完美转发”功能进一步改进。)

请注意,这还允许编译器完全推断函数模板参数,因此您不再需要显式指定它们

int xx = 2;
applyFunc(0,[](int x) { return x + 1; });
applyFunc(0,[=](int z) { return z + xx; });

还可以注意到,我们甚至可以尝试将
T
作为模板参数(从
F
中提取),但我不会这样做。保持
T
的灵活性可以使模板支持函数重载的自然概念。

以下方法可行,唯一需要注意的是必须手动指定lambda函数的返回类型:

//given input x and function func, return func(x)
template <typename RET, typename T, typename U>
RET applyFunc(T x, U func)
{
  return func(x);
}

int main()
{
  int xx = 2;
  bool a = applyFunc<bool>(0,[](int x) -> bool {return x > 0;});
  bool b = applyFunc<bool>(0,[=](int z) -> bool {return z + xx > 0;});

  return 0;
}
//给定输入x和函数func,返回func(x)
模板
RET applyFunc(T x,U func)
{
返回func(x);
}
int main()
{
int xx=2;
boola=applyFunc(0,[](int x)->bool{return x>0;});
bool b=applyFunc(0,[=](intz)->bool{returnz+xx>0;});
返回0;
}
我无法对答案发表评论,因此我将提供另一条评论。您可以使用autodecltype来代替指定返回类型:

#include <iostream>
using namespace std;

template <typename T, typename U>
auto applyFunc(T x, U func) -> decltype(func(x))
{
  return func(x);
}

int main()
{
  int xx = 2;
  bool a = applyFunc<bool>(0,[](int x) -> bool {return x > 0;});
  bool b = applyFunc<bool>(0,[=](int z) -> bool {return z + xx > 0;});

  cout << "a = " << a << " b = " << b << endl;
}
#包括
使用名称空间std;
模板
自动应用程序函数(T x,U func)->decltype(func(x))
{
返回func(x);
}
int main()
{
int xx=2;
boola=applyFunc(0,[](int x)->bool{return x>0;});
bool b=applyFunc(0,[=](intz)->bool{returnz+xx>0;});

我明白了。我可以使用函数库中的函数声明来传递带有捕获的lambda函数吗?@roro:我不确定我是否理解这个问题。你能用一个例子来说明吗?@roro:更新了答案。使用@BasileStrynkevitch这是我的想法,但是我得到了一个关于模板参数数量错误的错误。请阅读文件的.Re.Edv.Eng.,修改为<代码> STD::函数 <代码> STD::函数我们将在代码中不合适,这将使它“编译”和“运行”,但这不是正确的方法。这不是“代码> STD::函数< /COD>”。这将把FUNC看作是U类型的对象(在main中被模板化为int)。FUNC(x)将是一个语法错误。是的,这将考虑FUNC是一个类型的对象。我将为您调用此运算符。代码符合要求,我检查过了。我明白您的意思。当我的返回类型与输入类型匹配时,我更喜欢此解决方案,但在其他情况下更笨拙。如果我错了,请纠正我,但如果我希望lambda函数的返回类型与输入不同,我需要三个模板变量。是的,我认为返回值应该相同。我修改了答案以允许不同的返回类型。您不需要指定其他两个模板参数,编译器将推导它们。