Instead of implementing INVOKE yourself, use one of the functions of the library that uses it . In particular, std::reference_wrapper works. So you can get 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 did not forward f because std::reference_wrapper requires that the passed object is not a value. Using std::bind instead of std::ref does not solve the problem. This means that for such a functional object:
struct F { void operator()() && { std::cout << "Rvalue\n"; } void operator()() const& { std::cout << "Lvalue\n"; } };
invoke(F{}) will print an Lvalue , while std::invoke(F{}) in C ++ 17 will print an Rvalue .
I found the technique from this article.
source share