Possible Duplicate:
How do I expand a tuple into variadic template function's arguments?
“unpacking” a tuple to call a matching function pointer
In C++11 templates, is there a way to use a tuple as the individual args of a (possibly template) function?
Example:
Let's say I have this function:
void foo(int a, int b) { }
And I have the tuple auto bar = std::make_tuple(1, 2)
.
Can I use that to call foo(1, 2)
in a templaty way?
I don't mean simply foo(std::get<0>(bar), std::get<1>(bar))
since I want to do this in a template that doesn't know the number of args.
More complete example:
template<typename Func, typename... Args> void caller(Func func, Args... args) { auto argtuple = std::make_tuple(args...); do_stuff_with_tuple(argtuple); func(insert_magic_here(argtuple)); // <-- this is the hard part }
I should note that I'd prefer to not create one template that works for one arg, another that works for two, etc…
Try something like this:
// implementation details, users never invoke these directly namespace detail { template <typename F, typename Tuple, bool Done, int Total, int... N> struct call_impl { static void call(F f, Tuple && t) { call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t)); } }; template <typename F, typename Tuple, int Total, int... N> struct call_impl<F, Tuple, true, Total, N...> { static void call(F f, Tuple && t) { f(std::get<N>(std::forward<Tuple>(t))...); } }; } // user invokes this template <typename F, typename Tuple> void call(F f, Tuple && t) { typedef typename std::decay<Tuple>::type ttype; detail::call_impl<F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t)); }
Example:
#include <cstdio> int main() { auto t = std::make_tuple("%d, %d, %d\n", 1,2,3); call(std::printf, t); }
With some extra magic and using std::result_of
, you can probably also make the entire thing return the correct return value.
Create an "index tuple" (a tuple of compile-time integers) then forward to another function that deduces the indices as a parameter pack and uses them in a pack expansion to call std::get
on the tuple:
#include <redi/index_tuple.h> template<typename Func, typename Tuple, unsigned... I> void caller_impl(Func func, Tuple&& t, redi::index_tuple<I...>) { func(std::get<I>(t)...); } template<typename Func, typename... Args> void caller(Func func, Args... args) { auto argtuple = std::make_tuple(args...); do_stuff_with_tuple(argtuple); typedef redi::to_index_tuple<Args...> indices; caller_impl(func, argtuple, indices()); }
My implementation of index_tuple
is at https://gitlab.com/redistd/redistd/blob/master/include/redi/index_tuple.h but it relies on template aliases so if your compiler doesn't support that you'd need to modify it to use C++03-style "template typedefs" and replace the last two lines of caller
with
typedef typename redi::make_index_tuple<sizeof...(Args)>::type indices; caller_impl(func, argtuple, indices());
A similar utility was standardised as std::index_sequence
in C++14 (see index_seq.h for a standalone C++11 implementation).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With