Reputation: 2843
I have a function taking pairs of (argument type, data ptr) as a variadic list (C function). I would like to unpack the tuple into that function as follows:
foo(TypeIndex<std::tuple_element_t<I, Tuple>>(), &std::get<I>(tuple));
thus I wrote a following function:
template<typename Tuple, size_t ...I>
void doUnpack(Tuple const& tp, std::index_sequence<I...>)
{
foo((type<std::tuple_element_t<I, Tuple>>(), std::get<I>(tp))...);
}
the only problem is comma operator ignores everything on the left uses the right hand side. Imagine type<>
function returns 0 for now, so the above evaluates (using input tuple{1,2,3,4,5}) to foo(1,2,3,4,5)
instead of foo(0,1, 0,2, 0,3, 0,4, 0,5)
Is there any way to accomplish this?
Code to reproduce:
template<typename Tp>
int type() { return 0; }
template<typename ...Args>
void fun(Args&& ...args)
{
(std::cout << ... << args) << std::endl;
}
template<typename Tuple, size_t ...I>
void doUnpack(Tuple const& tp, std::index_sequence<I...>)
{
fun((type<std::tuple_element_t<I, Tuple>>(), std::get<I>(tp))...);
}
int main()
{
doUnpack(std::tuple{1,2,3,4,5}, std::make_index_sequence<5>{});
return 0;
}
Upvotes: 0
Views: 608
Reputation: 5095
The following does what you want:
#include <tuple>
#include <iostream>
template<typename Tp>
int type() {
return 0;
}
template<typename Tuple, size_t... I>
auto doUnpack(Tuple const &tp, std::index_sequence<I...>) {
auto fun = [](auto &&...args) { (std::cout << ... << args) << std::endl; };
std::apply(fun, std::tuple_cat(std::pair{type<std::tuple_element_t<I, Tuple>>(), std::get<I>(tp)}...));
}
int main() {
doUnpack(std::tuple{1, 2, 3, 4, 5}, std::make_index_sequence<5>{});
return 0;
}
We use two nice STL-functions. std::tuple_cat
takes a bunch of tuples (here pairs of the type and the value of the tuple) and concatenates them to one big tuple. So you go from (type0, val0), (type1, val1)...
to (type0, val0, type1, val1, ...)
. This goes around the problem with the comma operator. After that, we apply the function to that with std::apply
. Note that I use a lambda since std::apply
needs (basically) a callable with a type and a function template does not qualify for that (whereas a lambda is (basically) a struct with templated operator()
which works for that.
Upvotes: 3