code_fodder
code_fodder

Reputation: 16401

I can't pass template funtion to std::apply directly but I can through lambda

Based on: How do I expand a tuple into variadic template function's arguments?

#include <string>  
#include <iostream>    
#include <tuple>  

template <typename... Args>
void print_all(const Args &... args) {
    ((std::cout << " " << args), ...) << std::endl;
}

int main()
{

    // Create a tuple
    auto values = std::make_tuple(1, 2, 3.4f, 4.5, "bob");
    
    // Need to pass the tuple through the lambda for template type deduction and to pass param to template function?
    std::apply([](auto &&... args) { print_all(args...); }, values);

    // This does not work - other then there is no parameter I can't see how this does not work
    // and how the lambda does work as it has the same (roughly) param list
    std::apply(print_all(), values);


    return 0;
}

can someone explain why one works and the other does not?

Upvotes: 2

Views: 62

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123431

Behind the scences, this lambda expression [](auto &&... args) { print_all(args...); } is roughly of type:

 struct [unnamed] {
      template <typename ...Args>
      void operator()(Args&&...args) { ... };
 };

It is a type with a templated operator(), ie overload resolution and template argument dedcution only take place once the operator() is actually called. print_all on the other hand is a template, hence you cannot pass it to std::apply.

In other words, no matter what Args... is, the lambda is always of same type, but print_all isn't. You would need to instantiate it before you can get a pointer to the function. As mentioned by Scheff, this is fine:

std::apply(&print_all<int, int, float, double, const char*>, values);

Upvotes: 4

Related Questions