Reputation: 51
I'm implementing a lambda as variable. In C++20 it works this way:
auto lambda = []<typename T>() -> const T& {
...
};
Now I want to store this kind of lambda function as a member variable of a struct:
struct A {
??? m_lambda;
A(??? lambda) : m_lambda(lambda) {}
};
Is there a way to do this?
Upvotes: 2
Views: 120
Reputation: 41840
Since your lambda is templated, you will need to contain the lambda directly in your object.
Fortunately, it's quite easy to do in C++20 (and C++17):
auto lambda = []<typename T>() -> const T& {
// ...
};
template<typename L> // <-- L is the lambda type
struct A {
L m_lambda;
A(L lambda) : m_lambda(lambda) {}
void foo() {
// Can call using many types using the template
int const& a = m_lambda.template operator()<int>();
float const& b = m_lambda.template operator()<float>();
}
};
int main() {
auto my_a = A{lambda}; // construct using the lambda and CTAD
my_a.foo();
}
If on the contrary you need A
to only call one version of the template, you can wrap the lambda in another lambda:
struct A {
std::function<int const&()> m_lambda;
A(auto const& lambda) : m_lambda{
[lambda]{ return lambda.template operator()<int>(); }
} {}
void foo() {
// Can call and get a int const reference back
int const& a = m_lambda();
}
};
Upvotes: 3
Reputation: 75874
In c++20 you can do:
struct Foo
{
decltype([] <class T> () {/* ... */ }) m_lambda {};
};
That being said it doesn't make any sense to store a lambda as a data member. Lambdas cannot change so a method is the simple, preferred alternative.
Upvotes: 3
Reputation: 19223
You store any templated lambda the same ugly way you store ordinary ones:
constexpr auto lambda = []<typename T>() {};
struct Foo{
decltype(lambda) m_lambda;
Foo():m_lambda(lambda){}
};
This works because it is operator()
that is actually templated, not the automatically-generated lambda type.
If you do not rely on inlining any calls to the lambda (for performance), you can store it in std::function<Ret(Args)>
for correct signature.
std::function
is also the only* option if the lambda cannot be defined before Foo
as seems to be the case of your constructor.
struct A {
std::function<void()> m_lambda;
// Not a lambda per se.
A(std::function<void()> lambda) : m_lambda(std::move(lambda)) {}
};
The above is not a lambda exactly because it doesn't really make sense most of the time to take a lambda as parameter as each has a distinct type making the argument effectively redundant.
*One can always make A
a class template and use CTAD for deduction, not sure you want to go that way though.
Upvotes: 4