How can the same thing be archieved with above lambda?
You can't. You must always declare the type of a variable. If you define the lambda after the declaration of the variable, then the declared type cannot be deduced from the initialiser. But you cannot refer to the type of a lambda before it has been defined because the type is anonymous.
Instead of a lambda (i.e. an anonymous function object), you could simply use a function object of a named type. You can then split the function definition. Also, you must declare the return type of the function, because it cannot be deduced without the definition of the function:
class A final {
constexpr struct Foo {
template<class Param1, class Param2, class Param3>
void operator()(Param1&, Param2&, Param3&) const;
} foo{};
};
However, as you may notice, the function is in fact a function template. This is because you use auto
arguments in the lambda. If you wish to define the template outside the header, then you must constrain the instantiations to a limited set, and explicitly instantiate those where the template is defined:
// the definition
template<class Param1, class Param2, class Param3>
void A::Foo::operator()(Param1&, Param2&, Param3&) const {
// do stuff
return;
}
// explicit instantiations
template void A::Foo::operator()<int, int, int>(int&, int&, int&) const;
template void A::Foo::operator()<int, double, float>(int&, double&, float&) const;
If you attempt to call with arguments that haven't been instantiated, in a translation unit where the template isn't defined, then there will be a linker error.
If you wish to keep the arguments unconstrained, then you have conflicting requirements. Unconstrained templates can only be achieved by defining the template in the header.
On the other hand, you might want to consider whether you need a function object in the first place. You haven't demonstrate your need for it. The above example works just as well if you were to make it a a static member function (template) instead of a function object.