vendredi 3 février 2017

Perfect forwarding of functions to build a function list class

Consider the following code that build a class storing functions.

// Function list class
template <class... F>
struct function_list
{
    template <class... G>
    constexpr function_list(G&&... g) noexcept
    : _f{std::forward<G>(g)...}
    {
    }
    std::tuple</* F... OR F&&... */> _f;
};

// Function list maker
template <class... F, class R = /* Can we compute the return type here? */>
constexpr R make_function_list(F&&... f)
{
    return function_list<
        /* decltype(std::forward<F>(f))...
         * OR F...
         * OR F&&...
        */>(std::forward<F>(f)...);
}

I would like these functions to be perfectly forwarded (regardless of whether they are function pointers, functors, lambdas...). But I don't exactly understand all the type deduction happening behind std::forward and universal references. In the code above, I have three questions:

  • Should _f be of type std::tuple<F...> or std::tuple<F&&...> (and why?)
  • Is it possible to deduce the return type R in the template parameter list (because doing it manually instead of auto/decltype(auto) would be helpful to understand what is going on)
  • In the maker, what the function_list template argument should be: decltype(std::forward<F>(f)...), F, or F&&... (and why?)

Note: the constructor of function_list is not meant to be called directly, instead make_function_list is doing the job.

Aucun commentaire:

Enregistrer un commentaire