I find it very confusing that the following code fails to compile
#include <functional>
class Mountain {
public:
Mountain() {}
Mountain(const Mountain&) = delete;
Mountain(Mountain&&) = delete;
~Mountain() {}
};
int main () {
Mountain everest;
// shouldn't the follwing rvalues be semantically equivalent?
int i = ([](const Mountain& c) { return 1; })(everest);
int j = (std::bind([](const Mountain& c) {return 1;},everest))();
return 0;
}
The compilation error being:
$ g++ -std=c++20 test.cpp -o test
In file included from test.cpp:1:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:486:26: error: no
matching constructor for initialization of 'tuple<Mountain>'
: _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...)
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:788:14: note: in
instantiation of function template specialization 'std::_Bind<(lambda at test.cpp:14:22)
(Mountain)>::_Bind<Mountain &>' requested here
return typename __helper_type::type(std::forward<_Func>(__f),
^
test.cpp:14:17: note: in instantiation of function template specialization 'std::bind<(lambda at
test.cpp:14:22), Mountain &>' requested here
int j = (std::bind([](const Mountain& c) {return 1;}, everest))();
^
...
So std::bind
sneakily tries to copy everest
even though the lambda only wants a reference to it. Am I rubbing against a weird edge case that nobody cares about (eg. it is always possible to just lambda-capture a reference to everest
) or is there a rationale? If the rationale is that bind is protecting me from calling the lambda after everest
was destroyed, is there an unsafe version of bind that would not do that?
Yes, arguments to std::bind
would be copied (or moved).
The arguments to bind are copied or moved, and are never passed by reference unless wrapped in
std::ref
orstd::cref
.
You can use std::cref
(or std::ref
) instead. E.g.
int j = (std::bind([](const Mountain& c) {return 1;}, std::cref(everest)))();
// ^^^^^^^^^^ ^
LIVE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With