Search code examples
c++metaprogrammingvariadic-templatesvariadic-functionsstdtuple

Generate a std::tuple of std::function from variadic templates


Suppose a function like

template <typename ...ts>
void f(std::tuple<ts...> & data);

I would like to generate a std::tuple of std::function, each with this signature: std::function<void(t&)>, where t is the corresponding type in data.

Something like:

template <typename ...ts>
void f(std::tuple<ts...> & data, std::tuple<std::function<void(ts)>, ...> functions);

I suppose using std::index_sequence on ts... somehow, but I could not figure it out.


Solution

  • As mentioned in comments you can express the pack expansion like this:

    template <typename... Ts>
    void f(std::tuple<Ts...> & data, std::tuple<std::function<void(Ts &)>...> functions);
    

    though, I'd argue that requiring each element to be a std::function is pretty expensive. Maybe you want something more like this: ()

    template <typename... Ts, typename... Fs>
      requires (... and std::is_invocable_r_v<void, Fs, Ts &>)
    void f(std::tuple<Ts...> & data, std::tuple<Fs...> functions);
    

    or this: ()

    template <typename... Ts, typename... Fs>
    std::enable_if_t<std::conjunction_v<std::is_invocable_r<void, Fs, Ts &>...>>
    f(std::tuple<Ts...> & data, std::tuple<Fs...> functions);
    

    It should be pretty straightforward to derive the solution in or below from the approach, if needed. The advantage of these last two approaches is that the caller of f can provide a tuple of lambdas, functors, function pointers, or any combination that is compatible with the call signature of the respective std::function in the first approach.