Perhaps this is the simplest example I can come up with (and given my familiarity with rvalues, this pushes my limitations).
At first the code (maybe too simple, but I think this is right for the demonstration):
#include <iostream> #include <utility> #include <functional> struct Obj { Obj() { std::cout << __PRETTY_FUNCTION__ << '\n'; } Obj(Obj const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; } Obj(Obj&&) { std::cout << __PRETTY_FUNCTION__ << '\n'; } }; void foo(Obj, Obj) { std::cout << __PRETTY_FUNCTION__ << '\n'; } int main() { using namespace std::placeholders; auto fn = std::bind(foo, _1, _1); fn(Obj()); }
Output
Obj::Obj() Obj::Obj(Obj &&) Obj::Obj(Obj &&) void foo(Obj, Obj)
The important thing is that initially only one Obj was built, but subsequently it was "moved" twice , which does not matter for move-semantics. As soon as the first move is completed, the object is in purgatory. The second move is not correct, since the source object is no longer correct. A repeating placeholder cannot be a movable value or what you see here can happen.
source share