Если вы не хотите или не можете использовать std::apply
, я могу предложить несколько альтернатив.
Приведенные ниже фрагменты основаны на предыдущей редакции вашего вопроса, в которой не было class Bar
. Те же самые решения работают и для новой редакции.
(1) Вы можете заменить call_foo
лямбда-выражением C ++ 20 с явным списком параметров шаблона:
#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>
template<typename... Ts>
void foo(const std::string& s, Ts... ts)
{
std::cout << "foo called with " << s << " and " << sizeof...(Ts) << " ts\n";
}
template<typename... Ts>
void bar(Ts... ts)
{
const std::string s = "hello world";
const auto t = std::make_tuple(ts...);
[&]<std::size_t ...I>(std::index_sequence<I...>)
{
foo(s, std::get<I>(t)...);
}
(std::make_index_sequence<std::tuple_size_v<decltype(t)>>{});
}
int main()
{
bar(1, 'a', 2.3);
}
Попробуй вживую
К сожалению, в настоящее время GCC 8, похоже, является единственным крупным компилятором, который их поддерживает.
(2) Если у вашего компилятора нет новых причудливых лямбд, или вы не хотите писать шаблон index_sequence
каждый раз, когда вам нужно расширить кортеж, я предлагаю следующее:
#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>
template <std::size_t ...I, typename F> void with_sequence_impl(F &&func, std::index_sequence<I...>)
{
func(std::integral_constant<std::size_t, I>{}...);
}
template <std::size_t N, typename F> void with_sequence(F &&func)
{
with_sequence_impl(std::forward<F>(func), std::make_index_sequence<N>{});
}
template<typename... Ts>
void foo(const std::string& s, Ts... ts)
{
std::cout << "foo called with " << s << " and " << sizeof...(Ts) << " ts\n";
}
template<typename... Ts>
void bar(Ts... ts)
{
const std::string s = "hello world";
const auto t = std::make_tuple(ts...);
with_sequence<std::tuple_size_v<decltype(t)>>([&](auto ... i)
{
foo(s, std::get<i.value>(t)...);
});
}
int main()
{
bar(1, 'a', 2.3);
}
Попробуй в живую