如何反转可变参数模板函数的参数顺序?

我有一个带有 varargs 模板参数的模板函数,就像这样

I have a template function with varargs template arguments, like this

template<typename Args...>
void ascendingPrint(Args... args) { /* ... */ }

我想写

template<typename Args...>
void descendingPrint(Args... args) {
  /* implementation using ascendingPrint()? */
}

我如何反转参数包 args 的顺序,然后再传递它,即在伪代码中:

How do I reverse the order of the parameter-pack args before passing it along, i.e. in pseudo-code:

template<typename Args...>
void descendingPrint(Args... args) {
  ascendingPrint( reverse(args) );
}

推荐答案

这里是一个递归的特殊revert<>实现:

Here is a recursive implementation of a specialized revert<>:

// forward decl
template<class ...Tn>
struct revert;

// recursion anchor
template<>
struct revert<>
{
    template<class ...Un>
    static void apply(Un const&... un)
    {
        ascendingPrint(un...);
    }
};

// recursion
template<class T, class ...Tn>
struct revert<T, Tn...> 
{
    template<class ...Un>
    static void apply(T const& t, Tn const&... tn, Un const&... un)
    {
        // bubble 1st parameter backwards
        revert<Tn...>::apply(tn..., t, un...);
    }
};

// using recursive function
template<class A, class ...An>
void descendingPrint(A const& a, An const&... an)
{
    revert<An...>::apply(an..., a);
}

它适用于 gcc-4.6/7/8 和 clang 并且可能符合标准――唯一困难的部分是调用revert::apply(tn..., t, un...).

It works with gcc-4.6/7/8 and clang and is probably standard compliant -- the only difficult part being the call of revert<Tn...>::apply(tn..., t, un...).

虽然它有缺点(就像递归经常有的那样),它会生成目标函数的大量模板实例(代码膨胀)并且不使用完美转发,这可能是一个问题(但也许可以改进使用它).

It has drawbacks though (as recursion often has), that it generates a lot of template-instantiations of the target function (code bloat) and does not use perfect forwarding, which may be an issue (but maybe could be improved to use it).

相关文章