This can become clearer if you write that schematically std::bind .
// 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 }
Since you can call the object of the std::bind function, you get it several times, it cannot "use" the captured argument, so it will be passed as an lvalue reference. The fact that you pass bind yourself to rvalue only means that there is no copy in the line where a is initialized.
If you try to compile your example with the bind scheme shown above, you will also get a more useful 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
5gon12eder
source share