Распаковать std:: Кортеж на месте без искусственного слоя для последовательности std:: index
У меня есть шаблон функции:
template <typename... Us>
void set_args(const void* p, Us&... args);
У меня есть std::tuple
, который я хочу распаковать в args
. Мое текущее решение -
template <typename... Us, std::size_t... Idx>
void set_args_2(
const void* p, std::tuple<Us...>& args, std::index_sequence<Idx...>) {
set_args(p, std::get<Idx>(args)...);
}
template <typename... Us>
void func(std::tuple<Us...>& args, ...) {
...
set_args_2(p, args, std::index_sequence_for<Us...>{});
...
}
Обратите внимание на искусственный set_args_2()
, который существует исключительно для того, чтобы получить Idx
, чтобы распаковать кортеж. Есть ли способ распаковать Кортеж на месте func()
, Чтобы set_args()
можно было вызвать напрямую?2 ответа:
C++17 вводит std:: apply:
std::apply([&](auto&&... args) { set_args(p, std::forward<decltype(args)>(args)... ); }, args);
Бессовестно воруя у Yakk, мы определяем некоторые вспомогательные функции
template<std::size_t... Is> auto index_over(std::index_sequence<Is...>) { return [](auto&& f) -> decltype(auto) { return decltype(f)(f)(std::integral_constant<std::size_t, Is>{}...); }; } template<std::size_t N> auto index_upto(std::integral_constant<std::size_t, N> = {}) { return index_over(std::make_index_sequence<N>{}); }
И вся распаковка может быть выполнена inline
template<typename... Ts> void func(std::tuple<Ts...>& tup) { index_upto<sizeof...(Ts)>()( [&](auto... Is) { set_args(p, std::get<Is>(tup)...); } ); }