std :: bind和rvalue参考 [英] std::bind and rvalue reference

查看:57
本文介绍了std :: bind和rvalue参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们考虑以下代码:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆