I would like to understand how deductions guides work with universal references and std::forward
, in particular to create perfectly forwarding wrappers. The code below provides a code to experiment with a functor wrapper in two cases: one with an implicit deduction guide and one with an explicit deduction guide.
I have put a lot of &&
and std::forward
in comments, because I do not know where they are needed to achieve perfect forwarding. I would like to know where to put them, and where they are not needed.
// Case with not conversion constructor
template <class F>
struct functor1
{
explicit constexpr functor1(F/*&&*/ f)
noexcept(std::is_nothrow_copy_constructible_v<F/*&&*/>)
: _f(/*std::forward<F>(*/f/*)*/)
{}
template <class... Args>
constexpr operator()(Args&&... args)
noexcept(std::is_nothrow_invocable_v<F/*&&*/, Args/*&&*/...>)
{
/*std::forward<F>(*/_f/*)*/(std::forward<Args>(args)...);
}
private: F/*&&*/ _f;
};
// Case with a conversion constructor
template <class F>
struct functor2
{
template <class G>
explicit constexpr functor2(G&& g)
noexcept(std::is_nothrow_constructible_v<G/*&&*/, F/*&&*/>)
: _f(/*std::forward<G>(*/g/*)*/)
{}
template <class... Args>
constexpr operator()(Args&&... args)
noexcept(std::is_nothrow_invocable_v<F/*&&*/, Args/*&&*/...>)
{
/*std::forward<F>(*/_f/*)*/(std::forward<Args>(args)...);
}
private: F/*&&*/ _f;
};
template <class G>
functor2(G&&) -> functor2<G/*&&*/>;
EDIT: For the sake of simplicity, and because it is not the point of the question, in the preceding examples, we consider that F
and G
are function objects ie classes/structs with an operator()
.