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?
nc
? Could you edit your question to include a definition of botheverest
andnc
? – Notarync
andeverest
are missing in your example code.std::bind
was made before lambdas existed. You should generally always use lambdas, never bind. If you want to use references withstd::bind
you need to usestd::ref
orstd::cref
. – Reefereverest
andnc
! Use this as starting point: godbolt.org/z/zxh5sYafe ! – Seleuciabind
is for "capture", lambda equivalent would be[nc]() { return 1; }
(which won't compile for similar reason). – Untidy