Given say N
user-specified types, I'd like a function to return a std::tuple
of length N
where each element is constructed via a function call to some function (exemplified by func
below):
#include <tuple>
#include <utility>
template <typename T>
T func(int x)
{
return T();
}
template<typename... T, std::size_t... I>
std::tuple<T...> build_tuple()
{
// How do I write this in a generic way?
return std::make_tuple(
func<std::string>(0),
func<int>(1),
func<int>(2)
);
// This won't work, obviously
// return std::make_tuple(func<T...>(I...));
}
int main()
{
build_tuple<std::string, int, int>();
}
Essentially, my question is how do I unpack arguments to get something along the lines of "type0, 0", "type1, 1" etc., instead of "type0, type1, ..., 0, 1, ...", if that makes sense.
This feels like a common problem, so is there an idiomatic solution?
If size_t
arguments are 0, 1, ...
, you can simply use additional level of indirection:
template<class Tuple, std::size_t... I>
Tuple build_tuple_impl(std::index_sequence<I...>)
{
return std::make_tuple(
func<std::tuple_element_t<I, Tuple>>(I)...);
}
template<typename... Ts>
auto build_tuple()
{
using Tuple = std::tuple<Ts...>;
return build_tuple_impl<Tuple>(std::make_index_sequence<sizeof...(Ts)>{});
}
// Usage:
auto t = build_tuple<std::string, int, int>();
More general case:
template<class Tuple, std::size_t... Is, std::size_t... I>
Tuple build_tuple_impl(std::index_sequence<Is...>, std::index_sequence<I...>)
{
constexpr std::size_t is[] = {Is...};
return std::make_tuple(
func<std::tuple_element_t<I, Tuple>>(is[I])...);
}
template<typename... Ts, std::size_t... Is>
auto build_tuple(std::index_sequence<Is...> is)
{
static_assert(sizeof...(Ts) == sizeof...(Is));
using Tuple = std::tuple<Ts...>;
return build_tuple_impl<Tuple>(is, std::make_index_sequence<sizeof...(Ts)>{});
}
// Usage:
auto t = build_tuple<std::string, int, int>(std::index_sequence<3, 4, 5>{});
Not that you can't write build_tuple<std::string, int, int, 3, 4, 5>()
. One of the sequences should be packed into a single type.