Your two attempts fail for different reasons. Let's look at the second one first:
auto assign = [&](auto other){
//do something
};
This could work in theory: the lambda expression has a definite type that could be deduced and used. However, as addressed in this Q&A (for C++11 but still relevant), the language simply does not allow auto
member variables, so that's that.
Your first attempt fails for a more design-related reason. Well, the immediate issue is that void(auto)
is not a valid type (auto
is a syntactic keyword with tailored semantics, not a type), but one could conceivably use some tag types to make std::function<void(auto_t)>
a valid specialization.
The issue, however, is that std::function
is a type-erasure tool: its goal is to take in and conceal a functionoid (such as your lambda), then call it on demand. By the time the call is made, the functionoid's type is not known anymore, much less its potential operator()
template -- handling the general case would require instantiating that template at runtime for a yet-unknown argument type, which is not possible.
Bottom line: storing the lambda is conceptually valid but its type deduction is not supported, and type erasure is the wrong tool for the job since templates are involved. Your only solution is to create an explicit functor class, and use that as a member:
class MyClass {
struct {
template <class T>
void operator()(T other) const {
// do something
}
} assign;
};
Bonus point: C++20 allows lambdas in unevaluated context and default-constructible lambdas, which means that the following insanity is now valid
class MyClass {
decltype([](auto other) {
// do something
}) assign;
};