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.