让我们假设我有一个具有以下签名的函数:
void foo(std::function<void(int&)>& bar);
以下调用成功编译:
foo([](int& x) { ++x; });
这也成功编译:
std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);
但是使用自动类型推导它突然无法编译:
auto myFunction = [](int& x) { ++x; };
foo(myFunction);
AFAIK推断出的lambda类型是未指定的,但它应该作为一个函子/可调用。我不明白的是,如果不允许将同一个lambda作为同一类型的函数参数传递,怎么可能将同一个lambda分配给std::function<void(int&)>
?
使用-std=c++11
在GCC v4.8.5上进行测试。
答案 0 :(得分:5)
考虑到这种情况;
std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);
转换发生,结果存储在命名对象myFunction
中。反过来,命名对象可以绑定到foo
所需的引用。
鉴于其他两个案例;
foo([](int& x) { ++x; });
// and
auto myFunction = [](int& x) { ++x; };
foo(myFunction);
可以进行从命名对象myFunction
(在第二种情况下)到std::function
的转换(在两种情况下);但是暂时产生了。临时无法绑定std::function
所需的foo
引用,因此错误。如下添加const
允许代码编译;
void foo(std::function<void(int&)> const& bar);
允许Temporaries绑定到const
个引用。
答案 1 :(得分:2)
以下调用成功编译:
KnoxContainerManager.getContainers()
错了,does not compile。原因是您无法将临时绑定到引用。
出于同样的原因:
<receiver
android:name=".receiver.KnoxContainerReceiver"
android:exported="true" >
<intent-filter>
<action android:name="com.samsung.knox.container.creation.status" />
</intent-filter>
</receiver>
public class KnoxContainerReceiver extends BroadcastReceiver{
@Override public void onReceive(Context context, Intent intent ){
//do something
}
}
也不编译。 foo([](int& x) { ++x; });
的类型是一种lambda,因此临时创建时将其传递给auto myFunction = [](int& x) { ++x; };
foo(myFunction);
,因为myFunction
期望foo
和foo
必须被隐式转换到std::function<void(int&)>&
。
下面:
myFunction
没有临时创建。所以代码编译成功。
答案 2 :(得分:1)
引用与值不同。
OnNavigateFromAsync
这是一个参考。
std::function<void(int&)>&
这是一个值。
std::function<void(int&)>
这是一个参考。
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);
会引用foo
。这意味着它需要传递一个实际的std::function
,而不是可转换为它的东西。
std::function
void foo2(std::function<void(int&)> const& bar);
将foo2
带到const&
。在这里,您可以将可转换的内容传递给std::function
。
std::function
void foo3(std::function<void(int&)> bar);
按值foo3
获取。在这里,您可以将可兑换的内容传递给std::function
。
lambda不是std::function
,但只要签名兼容,它就可以转换为lambda。所以这类似于“将std::function
传递给double
”的情况,其中int
转换为double
,但您无法获得int
到int&
。
C ++允许double
临时,但不允许const&
,因为&
暗示您打算更改它,并且更改不会传播通过临时。