I have a function template that takes an argument of some callable type, and uses std::bind to make a new callable object with predefined argument values for the original callable. I've written it with a forwarding reference parameter and std::forward, like this:
template <typename F>
auto make_example_caller(F &&f) {
return std::bind(std::forward<F>(f), 123, 456, 789);
}
The cppreference documentation for std::bind says that the bound object "holds a member object of type std::decay<F>::type constructed from std::forward<F>(f)". Since std::bind forwards the function to its internal data member, forwarding the same function to the std::bind call in my own code seems reasonable and appropriate.
However, it's not clear what benefit that brings. If F is a reference type, std::decay removes the reference, so the bind object is going to store its own instance of the callable type. That instance will be constructed as a move if F is an rvalue reference, or a copy if F is an lvalue, and I can get the same result if I write my function like this:
template <typename F>
auto make_example_caller(F f) { // Note, no &&
return std::bind(std::move(f), 123, 456, 789); // move, not forward
}
Now my function's own f parameter will be initialized by either move or copy depending on how the function is called, but either way I now have my own instance of the function object, which I can move into the bind object.
The latter way seems simpler, but I wonder if I'm missing something — especially since the same reasoning would apply to std::bind itself, yet it takes an F&& and forwards it, instead of taking an F by value and moving it. Is there a disadvantage in doing it that way? Something that I'm not seeing?