Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can std::apply call a lambda but not the equivalent template function?

The following code snippet (compiled using gcc 6.3.0 on OS X with -std=c++17) demonstrates my conundrum:

#include <experimental/tuple>

template <class... Ts>
auto p(Ts... args) {
  return (... * args);
}

int main() {
  auto q = [](auto... args) {
    return (... * args);
  };

  p(1,2,3,4); // == 24
  q(1,2,3,4); // == 24

  auto tup = std::make_tuple(1,2,3,4);
  std::experimental::apply(q, tup); // == 24
  std::experimental::apply(p, tup); // error: no matching function for call to 'apply(<unresolved overloaded function type>, std::tuple<int, int, int, int>&)'
}

Why can apply successfully deduce the call to the lambda but not the call to the template function? Is this the expected behavior and, if so, why?

like image 516
RandomBits Avatar asked Mar 16 '17 05:03

RandomBits


1 Answers

The difference between the two is that p is a function template, while q - a generic lambda - is pretty much a closure class with a templated call operator.

Although the definition of said call operator is very much the same as p definition, the closure class is not a template at all, and therefore it doesn't stay in a way of template argument resolution for std::experimental::apply.

This can be checked by defining p as a functor class:

struct p
{
   auto operator()(auto... args)
   { return (... * args); }
};
like image 96
Ap31 Avatar answered Nov 04 '22 07:11

Ap31