2014-09-05 92 views
5

我想将参数包拆分为第一个N-1和第N个参数,而不使用典型的index_sequence & tuple技巧,但似乎无法包住我的头在它周围,但我很确定它应该是可行的? (通过递归获得最后一个项目是很容易的)。在0 ... N-1和第N个元素中拆分参数包

最后函数调用看起来像

void Fun(Foo a, Bar b); 

和从可变参数一个又收购:

template< class... T > 
Foo CalcFoo(T... args); 

我目前的执行情况:

//get the last item of the pack 
template< class T > 
T split_last(T t){ return t; } 

template< class... T > 
T split_last(T, T... t){ return split_last(t...); } 

//helper 
template< class... T, size_t... Indices > 
Foo CalcFoo(const std::tuple<T...>& args, index_sequence<Indices...>) 
{ 
    return CalcFoo(std::get<Indices>(args)...); 
} 

//split and call 
template< class... T > 
void MoreFun(T... args) 
{ 
    //make a tuple containing all, then get n -1 items out of it 
    const auto tup = std::make_tuple<T...>(args...); 
    Fun(CalcFoo(tup, make_index_sequence< sizeof...(T) - 1 >()), 
     split_last(args...)); 
} 

更新除了想知道如何在没有at的情况下做到这一点为了它的缘故,我也问了这个问题,因为我不知何故可能会考虑一个元组会导致开销。从而忽略了过早的优化口头禅,而这个口头禅再次证明是正确的。在发布模式下使用VS2013进行编译时,我和Horstling的代码都会生成相同的汇编代码,其结果为,确切地说是。包括CalcFoo在内的所有内容都被内联,直到拨打Fun。换句话说,元组完全消失了。所以我可能会坚持这个实现,因为它很清楚。

回答

4

好的,让我们有创意。我真的肯定有一个更“标准”的方式来做到这一点,但我还挺喜欢这个解决方案;)

http://coliru.stacked-crooked.com/a/25a3fa276e56cd94

的核心思想是递归地旋转参数,直到我们能打出(原)最后一个论点。

template <size_t N> 
struct MoreFunHelper 
{ 
    template <class Head, class... Tail> 
    static void RotateLeft(Head head, Tail... tail) 
    { 
     MoreFunHelper<N - 1>::RotateLeft(tail..., head); 
    } 
}; 

template <> 
struct MoreFunHelper<0> 
{ 
    template <class Head, class... Tail> 
    static void RotateLeft(Head head, Tail... tail) 
    { 
     Fun(CalcFoo(tail...), head); 
    } 
}; 

template< class... T > 
void MoreFun(T... args) 
{ 
    MoreFunHelper<sizeof...(T) - 1>::RotateLeft(args...); 
} 

因此,如果我们先从参数

1 2 3 4 5 

它旋转他们4次:

2 3 4 5 1 
3 4 5 1 2 
4 5 1 2 3 
5 1 2 3 4 

现在我们可以顺利将它们分割成[5]和[1 2 3 4 ],这正是我们想要的。此时,递归停止,只是调用函数CalcFooFun

+0

+1现在确实很有创意! – stijn 2014-09-05 13:28:31

相关问题