Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying a variadic function with std::apply

Is it possible to apply a variadic function to a tuple with std::apply?

For example, the following code works fine with GCC 6.2.1:

void print_t(std::string i, std::string j) {
    std::cout << i << " " << j << std::endl;
}

int main() {
        std::tuple<std::string, std::string> t{"ab", "cd"};
        std::experimental::apply(print_t, t);
        return 0;
}

But if I try to apply a variadic function:

template<typename T>
void vprint(T && t) {
    std::cout << std::forward<T>(t) << std::endl;
}

template<typename T, typename ... Ts>
void vprint(T && t, Ts ... ts) {
    std::cout << std::forward<T>(t) << " ";
    vprint<Ts...>(std::forward<Ts>(ts)...);
}

int main() {
        std::tuple<std::string, std::string> t{"fd", "ab"};
        std::experimental::apply(vprint, t);
        return 0;
}

the compiler complains that it cannot deduce template arguments of vprint. OK, let's write them explicitly:

std::experimental::apply(vprint<std::string, std::string>, t);

Now the compiler ends up with some obscure errors which expose standard library internals.

I wrote my own implementation of std::apply in C++11 and I understand why it can't deduce arguments of the variadic function template. But, in theory, std::apply has all the information needed for that deduction.

So is the application of variadic functions a not yet implemented feature in GCC6? Will C++17-compatible compilers allow such application? If not, will they allow application of instantiated variadic template functions, like vprint<std::string, std::string>?

like image 200
Sergey Avatar asked Nov 10 '16 08:11

Sergey


People also ask

How do you declare a variadic function in C++?

Variadic functions are functions (e.g. std::printf) which take a variable number of arguments. To declare a variadic function, an ellipsis appears after the list of parameters, e.g. int printf(const char* format...);, which may be preceded by an optional comma.

What is variadic template 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.

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.


1 Answers

With vprint<std::string, std::string>, you must pass r-value references, so

std::experimental::apply(vprint<std::string, std::string>, std::move(t));

The better way is to use functor (thanks to generic lambda):

std::experimental::apply([](auto&&... args) {
                             vprint(std::forward<decltype(args)>(args)...);
                         },
                         t);
like image 107
Jarod42 Avatar answered Oct 02 '22 03:10

Jarod42