Я на самом деле сделал нечто похожее недавно. Поэтому попробуйте следующий код:
template<unsigned N, unsigned M>
struct call_up_impl{
template<class Func, class Mutator, class Tuple, class... Args>
static void do_call(const Func& func, const Mutator& mutator, const Tuple& args, Args&&... unpacked_args) {
call_up_impl<N-1, M>::do_call(func, mutator, args, std::get<N-1>(args), std::forward<Args>(unpacked_args)...);
}
};
template<unsigned M>
struct call_up_impl<0, M> {
template<class Func, class Mutator, class Tuple, class... Args>
static void do_call(const Func& func, const Mutator&, const Tuple&, Args&&... unpacked_args) {
func(std::forward<Args>(unpacked_args)...);
}
};
template<unsigned M>
struct call_up_impl<M, M> {
template<class Func, class Mutator, class Tuple, class... Args>
static void do_call(const Func& func, const Mutator& mutator, const Tuple& args, Args&&... unpacked_args) {
call_up_impl<M-1, M>::do_call(func, mutator, args, mutator(std::get<M-1>(args)), std::forward<Args>(unpacked_args)...);
}
};
template<int i, typename Function, typename... Parms>
void apply(Function f, Parms... parms) {
std::tuple<Parms...> t(parms...);
call_up_impl<std::tuple_size<decltype(t)>::value, i + 1>::do_call(f, &g, t);
}
Это быстрая адаптация моего исходного кода, поэтому он не полностью протестирован и, возможно, не является оптимальным способом сделать это, но он должен работать как минимум (по крайней мере, в соответствии с быстрым тестом и в зависимости от того, что именно вы хочу). Должна быть возможность сделать это без кортежа, но я не получил этого для компиляции с g ++ (похоже, ему не нравятся вложенные переменные шаблоны). Однако меняется apply
на:
template<int i, typename Function, typename... Parms>
void apply(Function f, Parms&&... parms) {
std::tuple<Parms&&...> t(std::forward<Parms>(parms)...);
call_up_impl<std::tuple_size<decltype(t)>::value, i + 1>::do_call(f, &g, t);
}
, вероятно, позволит избежать большинства накладных расходов, вносимых кортежем. Было бы даже лучше сделать правильную переадресацию результатов вызовов std::get
, но я слишком устала, чтобы писать это сейчас.