6

In looking at std::apply references from cpprefrence we can see that function templates cannot be passed as callable object of std::apply. Let's consider the following function template:

template<typename T>
T add_generic(T first, T second) { return first + second; }

So as the function template can't be deduced in std::apply call, we can't use the follwing code:

std::apply(add_generic, std::make_pair(2.0f, 3.0f)); // Error: can't deduce the function type

Please note that this is not the same question as this question. In that answer, the author writes a lambda expression without explicit template parameters.

std::cout << std::apply(
    [](auto first, auto second) { return add_generic(first, second); },
    std::make_tuple(2.0f,3.0f)) << '\n';

but as you know in c++20 you can have lambda expressions with explicit template parameter list. So I tried this feature to the case and surprisingly the compiler did not raise any errors.

std::apply([]<typename T>(T first,T second){
    return first+second;
},std::make_pair(2.0,3.0));

Why will the compiler be able to deduce type in the last case? Is there any difference between the two?

0

1 Answer 1

8

A function template is not a function, just like a cookie cutter is not a cookie. C++ templates create new functions for every set of template arguments. And this is precisely why add_generic is not a viable argument. It's not a function, it cannot be passed around as a value. To obtain the function, the compiler needs to deduce the template arguments. But it can only do that inside apply after the callable has been passed. Chicken and egg right there.

Why does a lambda work? Because it's not a plain function either. It produces a hidden object type

struct __lambda_at_line_N {
  template<typename T>
  auto operator()(T first, T second) { /* ... */ }
};

And passes that

std::apply(__lambda_at_line_N{},std::make_pair(2.0,3.0));

This is an actual object, a value. Its type does not depend on the template argument deduction that needs to happen inside std::apply to call operator(). That's why it works.

Sign up to request clarification or add additional context in comments.

1 Comment

It makes sense now, thanks

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.