将参数包拆分为0 ... N-1和Nth个元素 [英] Split parameter pack in 0 ... N-1 and Nth element

查看:38
本文介绍了将参数包拆分为0 ... N-1和Nth个元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在不使用典型的index_sequence&的情况下将参数包分为前N-1个和第N个参数。元组把戏,但似乎无法绕过它,但我很确定它应该可行吗? (使用递归可以轻松获得最后一个项目。)

I would like to split a parameter pack into the first N - 1 and the Nth parameters without using the typical index_sequence & tuple trick but cannot seem to wrap my head around it, yet I'm pretty sure it should be doable? (getting the last item is easy enough with recursion).

最终调用的函数如下:

void Fun( Foo a, Bar b );

a又从可变参数的a中获取:

and a is acquired from a variadic one in turn:

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... ) ); 
}

更新,除了想知道如何做之外只是为了它而没有元组,我也问这个,因为我不知何故认为元组可能会引起开销。从而忽略了过早的优化口头禅,就像往常一样,它再次证明是正确的。我的代码和Horstling的代码均以VS2013的发布模式进行编译,产生的 exact 完全相同的汇编代码。包括 CalcFoo 在内的所有内容都已内联,直到调用 Fun 为止。换句话说:元组已完全消失。因此,无论如何,我还是会坚持使用此实现,因为它很清楚。

update apart from wanting to know how to do this without a tuple just for the sake of it I also asked this because I somehow thought maybe a tuple would cause overhead. Thereby ignoring the premature optimization mantra, which, as usual, turned out to be correct once again. Compiled in release mode with VS2013 both my and Horstling's code yield the exact same assembly code. Everything including CalcFoo is inlined up until the call to Fun. In other words: the tuple is completely gone. So I'll probably stick with this implementation anyway because it's pretty clear.

推荐答案

好吧,让我们发挥创造力。我敢肯定有一种更标准的方法可以做到这一点,但是我有点喜欢这种解决方案;)

Ok, let's be creative. I`m sure there is a more "standard" way to do this, but I kinda like this solution ;)

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

核心思想是递归旋转参数,直到我们可以分解出(以前)最后一个参数。

The core idea is to recursively rotate the arguments until we can split out the (formerly) last argument.

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...);
}

因此,如果我们以参数开头

So if we start with the arguments

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],这正是我们想要的。此时,递归停止,仅调用函数 CalcFoo Fun

Now we can split them smoothly into [5] and [1 2 3 4], which is exactly what we want. At this point, the recursion stops and just calls the functions CalcFoo and Fun.

这篇关于将参数包拆分为0 ... N-1和Nth个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆