Re: C++0x: variadic template puzzle
On Jul 7, 10:02 am, SG <s.gesem...@gmail.com> wrote:
Hi!
Suppose I stored some parameters in a tuple so I can forward these
parameters _later_ to some function object. I just don't want to
forward the tuple itself but to excract the parameters from the tuple.
However, I have trouble figuring out how to do that. The function
templates I try to define are
template<typename Func, typename... Args>
void tuple_forward(Func && f, tuple<Args...> && args);
template<typename Func, typename... Args>
void tuple_forward(Func && f, tuple<Args...> const& args);
The first takes a tuple rvalue and should extract and forward all
parameters properly to f so it works for move-only types as well. The
second function simply passes the extracted parameters directly to f.
I came up with the following helper class:
template<unsigned... Indices>
struct invoke_helper
{
template<typename Func, typename... Args>
static inline void doit(Func && f, tuple<Args...> && args)
{
f ( forward<Args>(get<Indices>(args))... );
}
template<typename Func, typename... Args>
static inline void doit(Func && f, tuple<Args...> const& args)
{
f ( get<Indices>(args)... );
}
};
The problem is to generate the template parameters "Indices". Here is
an implementation attempt for the first function template:
template<typename Func, typename... Args>
inline void tuple_forward(Func && f, tuple<Args...> && args)
{
typedef invoke_helper<0,1,2,...,(sizeof...(Args)-1)> ih;
ih::doit( forward<Func>(f) , move(args) );
// Note: "args" is always an rvalue reference. There is
// no reference collapsing involved.
}
I havn't yet been able to come up with a solution for the "ih"-
typedef. Obviously the line is ill-formed. But it shows the intention.
Is there any solution to this problem? It yes, what does it look like?
Credit for what I show begins with the authors of:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf
// code
#include <cstddef>
// make_tuple_indices
template <std::size_t...> struct tuple_indices {};
namespace detail
{
template <std::size_t S, class TupleIndices, std::size_t E>
struct make_indices_imp;
template <std::size_t S, std::size_t ...Indices, std::size_t E>
struct make_indices_imp<S, tuple_indices<Indices...>, E>
{
typedef typename make_indices_imp<S+1, tuple_indices<Indices...,
S>, E>::type type;
};
template <std::size_t E, std::size_t ...Indices>
struct make_indices_imp<E, tuple_indices<Indices...>, E>
{
typedef tuple_indices<Indices...> type;
};
}
template <std::size_t E, std::size_t S = 0>
struct make_tuple_indices
{
static_assert(S <= E, "make_tuple_indices input error");
typedef typename detail::make_indices_imp<S, tuple_indices<>,
E>::type type;
};
int main()
{
make_tuple_indices<0>::type t0; t0.show();
make_tuple_indices<1>::type t1; t1.show();
make_tuple_indices<2>::type t2; t2.show();
make_tuple_indices<3>::type t3; t3.show();
make_tuple_indices<4, 2>::type t42; t42.show();
}
This purposefully has error messages, to show the type of
tuple_indices<> generated:
test.cpp: In function ?int main()?:
test.cpp:36: error: ?struct tuple_indices<>? has no member named
?show?
test.cpp:37: error: ?struct tuple_indices<0ul>? has no member named
?show?
test.cpp:38: error: ?struct tuple_indices<0ul, 1ul>? has no member
named ?show?
test.cpp:39: error: ?struct tuple_indices<0ul, 1ul, 2ul>? has no
member named ?show?
test.cpp:40: error: ?struct tuple_indices<2ul, 3ul>? has no member
named ?show?
This can be used like:
template<typename Func, typename... Args, std::size_t ...Indices>
inline void doit(Func && f, tuple<Args...> && args,
tuple_indices<Indices...>)
{
f ( forward<Args>(get<Indices>(args))... );
}
template<typename Func, typename... Args>
inline void tuple_forward(Func && f, tuple<Args...> && args)
{
doit( forward<Func>(f) , move(args), typename
make_tuple_indices<sizeof...(Args)>::type() );
}
-Howard
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]