c++ - C++0x: iterating through a tuple with a function -
i have function named _push
can handle different parameters, including tuples, , supposed return number of pushed elements.
for example, _push(5)
should push '5' on stack (the stack of lua) , return 1 (because 1 value pushed), while _push(std::make_tuple(5, "hello"))
should push '5' , 'hello' , return 2.
i can't replace _push(5, "hello")
because use _push(foo())
, want allow foo()
return tuple.
anyway can't manage make work tuples:
template<typename... args, int n = sizeof...(args)> int _push(const std::tuple<args...>& t, typename std::enable_if<(n >= 1)>::type* = nullptr) { return _push<args...,n-1>(t) + _push(std::get<n-1>(t)); } template<typename... args, int n = sizeof...(args)> int _push(const std::tuple<args...>& t, typename std::enable_if<(n == 0)>::type* = nullptr) { return 0; }
let's want push tuple<int,bool>
. how expect work:
_push<{int,bool}, 2>
called (first definition)_push<{int,bool}, 1>
called (first definition)_push<{int,bool}, 0>
called (second definition)
however g++ 4.5 (the compiler have supports variadic templates), error concerning _push<args...,n-1>(t)
(line 3) saying couldn't find matching function call (without further detail). tried without "..." error saying parameters pack not expanded.
how can fix this?
ps: know can using template struct (this in fact doing before), i'd know how function
ps 2: ps2 solved, gman
i don't have compiler test of this, you'll have report issues.
the following should allow iterate across tuple calling function. it's based off logic, few minor changes. (n
std::size_t
, it's first parameter allow args
(and func
) deduced on further calls, calls function instead of performing specific task). nothing drastic:
namespace detail { // keep things concise , readable #define enable_if(x) typename std::enable_if<(x)>::type // recursive case template <std::size_t n, typename... args, typename func> enable_if(n >= 1) iterate(const std::tuple<args...>& ptuple, func& pfunc) { pfunc(std::get<n - 1>(ptuple)); iterate<n - 1>(ptuple, pfunc); } // base case template <std::size_t n, typename... args, typename func> enable_if(n == 0) iterate(const std::tuple<args...>&, func&) { // done } } // iterate tuple template <typename... args, typename func> func iterate(const std::tuple<args...>& ptuple, func pfunc) { detail::iterate<sizeof...(args)>(ptuple, pfunc); return pfunc; }
assuming works, have:
struct push_lua_stack { // constructor taking reference stack push onto // initialize count 0, etc.... template <typename t> void operator()(const t& px) { // push px onto lua stack ++count; } std::size_t count; };
and lastly:
std::size_t pushcount = iterate(sometuple, push_lua_stack()).count;
let me know if makes sense.
since seem against structs reason, make function this:
template <typename t> void push_lua(const t& px) { // push px onto lua stack }
and change call function:
namespace detail { // keep things concise , readable #define enable_if(x) std::enable_if<(x)>::type* = nullptr // recursive case template <std::size_t n, typename... args> typename enable_if(n >= 1) iterate(const std::tuple<args...>& ptuple) { // specific function instead of generic function push_lua(std::get<n - 1>(ptuple)); iterate<n - 1>(ptuple); } // base case template <std::size_t n, typename... args, typename func> typename enable_if(n == 0) iterate(const std::tuple<args...>&, func&) { // done } } // iterate tuple template <typename... args> void _push(const std::tuple<args...>& ptuple) { detail::iterate<sizeof...(args)>(ptuple); }
no idea why you'd avoid generic functionality though, or against structs.
oh how nice polymorphic lambda's be. ditch utility push_lua_stack
class , write:
std::size_t count = 0; iterate(sometuple, [&](auto px) { // push onto lua stack ++count; });
oh well.
Comments
Post a Comment