C++ 自动类型推断并将lambda传递给std::function参数

C++ 自动类型推断并将lambda传递给std::function参数,c++,c++11,lambda,C++,C++11,Lambda,假设我有一个具有以下签名的函数: void foo(std::function<void(int&)>& bar); 这也成功地编译了: std::function<void(int&)> myFunction = [](int& x) { ++x; }; foo(myFunction); AFAIK推导出的lambda类型未指定,但它应该充当函子/可调用函数。我不明白的是,如果不允许将同一lambda作为同一类型的函数参数传递,那么如

假设我有一个具有以下签名的函数:

void foo(std::function<void(int&)>& bar);
这也成功地编译了:

std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);
AFAIK推导出的lambda类型未指定,但它应该充当函子/可调用函数。我不明白的是,如果不允许将同一lambda作为同一类型的函数参数传递,那么如何将同一lambda分配给
std::function

在GCC v4.8.5上测试,在这种情况下使用
-std=c++11

std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);
可以将命名对象
myFunction
(在第二种情况下)转换为
std::function
(在两种情况下);但一个暂时的结果产生了。临时变量无法绑定到
foo
所需的
std::function
引用,因此出现错误。添加一个
const
,如下所示,可以编译代码

void foo(std::function<void(int&)> const& bar);
void foo(标准::函数const&bar);
允许临时变量绑定到
const
引用

以下调用已成功编译:

foo([](int& x) { ++x; });
错了,是它。原因是您无法将临时文件绑定到引用

std::function<void(int&)>
int
出于同样的原因:

auto myFunction = [](int& x) { ++x; };
foo(myFunction);
也不编译。
myFunction
的类型是lambda的一种类型,因此创建临时函数将其传递给
foo
,因为
foo
需要
std::function&
并且
myFunction
必须隐式转换为
std::function

void foo3(std::function<void(int&)> bar);
在这里:

std::function myFunction=[](int&x){++x;};
foo(myFunction);

不创建临时文件。因此代码编译成功。

引用与值不同

std::function<void(int&)>&
int&
int x = 3.0;
这是一个参考

std::function<void(int&)>
int
这是一个价值观

std::function<void(int&)>&
int&
int x = 3.0;
以上工作

int& x = 3.0;
std::function<void(int&)>& f = [](int&x){++x;};
上述方法不起作用

std::function<void(int&)> f = [](int&x){++x;};
void foo(std::function<void(int&)>& bar);
foo2
const&
转换为
std::function
。在这里,您可以将可转换的内容传递给
std::function

void foo3(std::function<void(int&)> bar);
void foo3(标准::功能条);
foo3
按值获取
std::function
。在这里,您可以将可转换的内容传递给
std::function

void foo3(std::function<void(int&)> bar);
lambda不是
std::function
,但只要签名兼容,它就可以转换为一个。因此,其行为类似于“将
double
传递给
int
”情况,其中
double
转换为
int
,但无法将
int&
转换为
double


C++允许对临时变量使用
常量&
,但不允许
&
,因为
&
意味着您打算更改它,并且更改不会通过临时变量传播。

如果缺少
常量
,则所有变量都可以正常编译()。但是,如果没有第二个代码段(正如我所期望的那样),您的第一个示例就可以编译了???它没有,或者是的,在其他答案提到代码不应该编译之后,我在cpp.sh和godbolt上都检查过(在那里使用gcc v4.8.5),它确实没有编译。奇怪,因为在我的工作机器上,gcc编译它没有问题,现在我得到了解释如何只能将右值绑定到常量引用的答案。。。