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?
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); }
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With