Search code examples
c++templatesc++11variadic-templatesvariadic-functions

How to reverse the order of arguments of a variadic template function?


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

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

And I want to write

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

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

Solution

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

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