Rather than implementing INVOKE
yourself, use one of the library features that uses it. In particular, std::reference_wrapper
works. Thus you can have the effect of std::invoke(f, args...)
with std::ref(f)(args...)
:
template<typename F, typename... Args>
auto invoke(F f, Args&&... args)
-> decltype(std::ref(f)(std::forward<Args>(args)...))
{
return std::ref(f)(std::forward<Args>(args)...);
}
I didn’t forward f
because std::reference_wrapper
requires that the object passed in is not an rvalue. Using std::bind
instead of std::ref
doesn’t fix the problem. What this means is that for a function object like this:
struct F
{
void operator()() && {
std::cout << "Rvalue\n";
}
void operator()() const& {
std::cout << "Lvalue\n";
}
};
invoke(F{})
will print Lvalue
, whereas std::invoke(F{})
in C++17 would print Rvalue
.
I found the technique from this paper