I stumbled upon a bug in my code which I traced down to the fact that arguments to std::bind
"...are never passed by reference unless wrapped in std::ref
or std::cref
".
What I have
I have a function template which looks like this (stripped of irrelevant bits):
template<typename F, typename ... Args>
auto eval(F&& _f, Args&&... _args)
{
using ret_t = typename std::result_of<F&&(Args&&...)>::type;
std::function<ret_t()> func(std::bind(std::forward<F>(_f), std::forward<Args>(_args)...)));
// Etc.
}
So far so good, but this breaks down if function _f
takes references as arguments because the arguments are copied or moved unless wrapped in std::ref
or std::cref
.
What I would like
A way to pass arguments as references to _f
while preserving perfect forwarding as much as possible. I would very much like to avoid having to pass each of the _args
by wrapping it in std::ref
at the origin. Rather, I would like the references to be figured out automagically inside eval()
.
What I have tried
Using std::ref
instead of std::forward
when bind
ing _args
seems to work:
template<typename F, typename ... Args>
auto eval(F&& _f, Args&&... _args)
{
using ret_t = typename std::result_of<F&&(Args&&...)>::type;
// Replace std::forward<Args>() with std::ref()
std::function<ret_t()> func(std::bind(std::forward<F>(_f), std::ref(_args)...)));
// Etc.
}
But I don't know how this behaves with rvalue references. Is it safe to always use std::ref
? Is it an overkill? Do I still have perfect forwarding? Questions abound.
I have also considered replacing std::bind
with a generic lambda, but I am not sure how to capture the arguments in order to achieve perfect forwarding.
Any insight would be appreciated.