Search code examples
c++c++11templatesvariadic-templates

Variadic templates: unfold arguments in groups


I have a function that takes two arguments:

template <typename T1, typename T2>
void foo(T1 arg1, T2 arg2)
{ std::cout << arg1 << " + " << arg2 << '\n'; }

And a variadic one that should forward its arguments in pairs :

template <typename... Args>
void bar(Args&&... args) {
    static_assert(sizeof...(Args) % 2 == 0);

    ( foo( std::forward<Args>(args), std::forward<Args>(args) ), ... );
    // ^ Sends each argument twice, not in pairs
}

I would want bar(1,2,3,4) to call foo(1,2) and foo(3,4)

Is there a way to do that ?


Solution

  • You can accomplish it with overloads.

    template <typename T1, typename T2>
    void bar(T1&& arg1, T2&& arg2) {
        foo( std::forward<T1>(arg1), std::forward<T2>(arg2) ); // (until) sends (the last) two arguments to foo
    }
    
    template <typename T1, typename T2, typename... Args>
    void bar(T1&& arg1, T2&& arg2, Args&&... args) {
        foo( std::forward<T1>(arg1), std::forward<T2>(arg2) ); // sends the 1st two arguments to foo
        bar( std::forward<Args>(args)... );                    // call bar with remaining elements recursively
    }
    

    LIVE


    Note that with the minimum snippet above when calling bar with 0 or odd arguments you'll get no matching function error. If you want more clear compilation message with static_assert you can start from this snippet.