std :: bind和rvalue参考 [英] std::bind and rvalue reference
问题描述
让我们考虑以下代码:
class Widget{
};
int main(){
Widget w;
auto lambda = bind([](Widget&& ref){ return; }, std::move(w));
return 0;
}
并触发错误
no match for call to ‘(std::_Bind<main()::<lambda(Widget&&)>(Widget)>) ()’
lambda();
我的问题是:为什么会出现错误?毕竟,我对右值引用进行了显式转换–我的意思是 std :: move(w)
,我通过右值引用接受了参数–我的意思是 Widget&&ref
.
And my question is: Why the error has appeared? After all, I do an explicit cast to rvalue reference – I mean std::move(w)
and I take argument by rvalue reference – I mean Widget&& ref
.
怎么了?
此外,以下代码有效,这让我更加担心:
Moreover the the below code works, what makes me worried the more:
class Widget{
};
int main(){
Widget w;
auto lambda = bind([](Widget& ref){ return; }, std::move(w));
return 0;
}
推荐答案
如果您写下 std :: bind
示意性的操作,它可能会变得更加清晰.
It might become clearer if you write down what std::bind
schematically does.
// C++14, you'll have to write a lot of boilerplate code for C++11
template <typename FuncT, typename ArgT>
auto
bind(FuncT&& func, ArgT&& arg)
{
return
[
f = std::forward<FuncT>(func),
a = std::forward<ArgT>(arg)
]() mutable { return f(a); }; // NB: a is an lvalue here
}
由于可以多次调用函数对象 std :: bind
,因此它不能用完"捕获的参数,因此将作为左值引用传递.您本身将 bind
传递给右值的事实仅意味着在初始化 a
的那一行上没有复制.
Since you can call the function object std::bind
gives you multiple times, it cannot "use up" the captured argument so it will be passed as an lvalue reference. The fact that you pass bind
itself an rvalue only means that there is no copy made on the line where a
is initialized.
如果您尝试使用上面显示的原理图 bind
编译示例,则还会从编译器中获得更有用的错误消息.
If you try to compile your example with the schematic bind
shown above, you'll also get a more helpful error message from your compiler.
main.cxx: In instantiation of ‘bind(FuncT&&, ArgT&&)::<lambda()> mutable [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]’:
main.cxx:10:33: required from ‘struct bind(FuncT&&, ArgT&&) [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]::<lambda()>’
main.cxx:11:31: required from ‘auto bind(FuncT&&, ArgT&&) [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]’
main.cxx:18:59: required from here
main.cxx:11:26: error: no match for call to ‘(main()::<lambda(Widget&&)>) (Widget&)’
]() mutable { return f(a); }; // NB: a is an lvalue here
^
main.cxx:11:26: note: candidate: void (*)(Widget&&) <conversion>
main.cxx:11:26: note: conversion of argument 2 would be ill-formed:
main.cxx:11:26: error: cannot bind ‘Widget’ lvalue to ‘Widget&&’
main.cxx:18:33: note: candidate: main()::<lambda(Widget&&)> <near match>
auto lambda = bind([](Widget&&){ return; }, std::move(w));
^
main.cxx:18:33: note: conversion of argument 1 would be ill-formed:
main.cxx:11:26: error: cannot bind ‘Widget’ lvalue to ‘Widget&&’
]() mutable { return f(a); }; // NB: a is an lvalue here
这篇关于std :: bind和rvalue参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!