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.
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: (c++20)
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: (c++17)
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 c++14 or below from the c++17 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.