Reputation: 1202
I need the syntax for a lambda expression that will return a pointer to a member function.
For example I have class A:
class A
{
int x;
void (A::*SomeFunction)();
}
I want to set SomeFunction to a lambda. I tried doing it like this:
A a();
a.SomeFunction = [this](){ printf("Hello from lambada %d",this->x);};
The problem is that:
[this](){ printf("Hello from lambda %d",this->x);};
does not give me a pointer to a member function of class A. it gives me a pointer to a normal function. How do i declare inside the lambda that this is a member function of A.
Alternativly if such a thing isn't possible in cpp. How do you suggest I'll access variable x of class A from the function that SomeFunction is pointing at without using virtual functions (this kind of code will run about 700 times per second).
Edit:
To make it clear I do care about performance. but the main reason why I need this is specific design problems not performance. I understand this is probably not possible to do in cpp. Workarounds suggestions would be welcomed.
Upvotes: 1
Views: 1243
Reputation: 1202
Well following up for future people here's a workaround to make it look a bit nicer.
I created a template class
template <class Parent,class Return, class...Params>
struct MemberLambda
{
Parent* self; // pointer to self
void (*lambda)(Parent * self,Params...);//the lambda
MemberLambda() = default;//Constructor
MemberLambda(Parent* self, void(*lambda)(Parent* self,Params...)) :
self(self),lambda(lambda) {};//Constructor
Return operator()(Params... p) const { return lambda(self,p...); };
void operator=(void (*lambda)(Parent* self, Params...)) {
this->lambda = lambda;
}
};
Usage in class:
class A {
public:
int someMember;
MemberLambda<A, void, int, int> func =
MemberLambda<A, void, int, int>(this, nullptr);
};
*Note in the example I set the lambda to nullptr
but it can be set to a lambda expression.
In the example, the lambda is a member of A
takes two int
s and returns void
.
User usage:
A a;
a.someMember = 3;
a.func = [](A* self, int a, int b){ std::cout << self->someMember + a + b; };
a.func(5,6);
Will output 14, which is 3 + 5 + 6.
Upvotes: 0
Reputation: 41770
From the comments:
This is part of an ECS implemention. and I am simply not willing to create a new class for etch system i want to give the user the option to declare the system in the scene constructor or inheriate from the system class.
You want different behavior from the same class without any indirection? You'll have to give up one.
But you don't have to write a class for each system either. You can make the class a template, so the compiler can generate a class for each systems:
template<typename T>
struct A : private T {
A(T function) noexcept : T{std::move(function)} {}
void SomeFunction() {
(*this)(this);
}
int x = 0;
};
It can then be used like that:
auto lambda = [](auto a){ printf("Hello from lambda %d",a->x); };
auto my_a = A{lambda}; // Generate a new A type from lambda
my_a.SomeFunction(); // calls the lambda!
Upvotes: 0
Reputation: 119307
It's impossible to add extra methods to a class after its definition. Therefore, since there are no methods in your class A
, it's impossible to ever set A::SomeFunction
to point to any non-static method of A
. As a workaround, you could have
void (*SomeFunction)(A*);
and
A a {}; // note {} instead of ()
a.SomeFunction = [](A* a){ /* do something with a->x */ };
Upvotes: 2
Reputation: 62593
That is not possible for several reasons.
First, a pointer to member function is different in type from a pointer to stand-alone function, and non-capturing lambdas can only be converted to pointers to standalone functions.
Second, your lambda is capturing, and as such, it can not be converted to a pointer to function at all, and can only remain a functor of unspecified type.
However, you shouldn't think too much into it and just store a lambda in a std::function
. Granted, you will end with virtual dispatch and some performance degradation associated with that, but 700 times a second is nothing, and you will never detect a hit because of virtual dispatch.
Upvotes: 4