I am trying to call a particular member function in all elements of a tuple using std::apply. This works when I use a lambda but not when defining a free function.
Following Template tuple - calling a function on each element the following code works when using a lambda:
#include<tuple> #include<iostream> struct Double { void print() { std::cout << "Double!" << std::endl;} }; struct Vector { void print() { std::cout << "Vector!" << std::endl;} }; template<class ...T> void printAll2(T &...x){(x.print(), ...);} int main() { auto workspace = std::make_tuple<Vector, Double, Vector>({},{},{}); auto printAll = [](auto &...x){(x.print(), ...);}; std::apply(printAll , workspace); // This does not work. //std::apply(printAll2, workspace); return 0; } However, when I try to use the free function printAll2 I get an error:
<source>:22:5: error: no matching function for call to 'apply' 22 | std::apply(printAll2, workspace); | ^~~~~~~~~~ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/ tuple:2955:5: note: candidate template ignored: couldn't infer template argument '_Fn' 2955 | apply(_Fn&& __f, _Tuple&& __t) | ^ 1 error generated. Compiler returned: 1 What is the difference between the lambda and the function?
Many thanks!
printAll2has no type (onlyprintAll2<T>does), so you can't pass it around without either specifying a template argument or casting a function pointer (that deduces that the template argument). While a lambda does have a type, since by itself it's not templated, only itsoperator()is templated.std::applywith a given argument will somehow "concretisize" the function template, (2) The OP asked about the difference from a generic lambda, not being aware that in the latter case only theoperator()is templated. I attempted to address these issues in my answer.printAll2isn't a type. The point is that the argument must have a (single) known type to be passed to a function, and you can't determine the type ofprintAll2.