Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 413
Fourmet Avatar asked Nov 24 '19 14:11

Fourmet


People also ask

Which of the following are valid reasons for using variadic templates in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.

What is Variadic template C++?

A variadic template is a class or function template that supports an arbitrary number of arguments. This mechanism is especially useful to C++ library developers: You can apply it to both class templates and function templates, and thereby provide a wide range of type-safe and non-trivial functionality and flexibility.

What are Variadic functions in C?

Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.

What is parameter pack in c++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.


1 Answers

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.

like image 132
songyuanyao Avatar answered Sep 21 '22 13:09

songyuanyao