The second definition is a variable template. It does not define the lambda's operator()
as a template, but rather takes the parameter pack for the argument types of operator()
. The resulting operator()
is a regular member function of the instantiated variable's closure type. There is no template argument deduction possible here.
So when you write lamd<int>
, the variable gets a closure type with a operator()(int)
, not something callable with 3 integers.
As mentioned already, you can use a generic lambda instead.
In C++20, if you'd need the lambda's argument types to be named and deduced, you can use the syntax:
auto lamd = []<typename... Pack>(Pack...) {}
This will define the operator as template, accepting a parameter pack, and leave the door open for template argument deduction.