template <class T0, class...Ts,
std::enable_if_t< std::is_same_v<T0, Ts> && ..., bool > =true
>
void fun(T0 arg0, Ts ...args)
{
constexpr auto argsCount = sizeof...(args)+1;
std::array<T0, argsCount>{ arg0, args... };
}
this is c++17; it could be done in c++14, it would just require more typing and I am lazy (replacing the fold expression mainly).
This requires the call site have Foo
s, which you don't want.
template<std::size_t I, class T>
struct helper { using type = T; };
template<std::size_t I, class T>
using X = typename helper<I,T>::type;
template<class T, std::size_t...Is>
void fun(std::index_sequence<Is...>, X<Is, T>... ts) {
std::array<T, sizeof...(Is)> args(ts...);
}
use:
fun<Foo>( std::make_index_sequence<7>, /* 7 Foo objects */ );
we can also do:
fun<Foo, 7>()( /* 7 Foo objects */ );
with a slight change:
template<class T, std::size_t N>
auto fun() {
auto seq = std::make_index_sequence<N>{};
return []<std::size_t...Is>(std::index_sequence<Is...>) {
return [](X<Is, Foo>... ts) {
std::array<Foo, sizeof...(Is)> args{ts...};
};
}( seq );
}
this is c++20, but you can backport to c++14 by writing argument pack unpackers.
The trick here is that foo<Foo,7>()
returns a function object that knows it takes 7
Foo
objects exactly.
Live example.
In c++14, we can:
template<class T, class Pack>
struct fun_impl;
template<class T, std::size_t...Is>
struct fun_impl<T, std::index_sequence<Is...>> {
void operator()(X<Is, T>... ts)const {
std::array<T, sizeof...(Is)> args{ts...};
}
};
template<class T, std::size_t N>
auto fun() {
return fun_impl<T, std::make_index_sequence<N>>{};
}
Live example (based off @Jarod42's version below).