用于分配成员函数指针的 lambda 表达式

lambda expression to assign a member function pointer

我需要 lambda 表达式的语法,它将 return 指向成员函数的指针。

例如我有 class A:

class A
{
int x;
void (A::*SomeFunction)();
}

我想将 SomeFunction 设置为 lambda。我试过这样做:

A a();
a.SomeFunction = [this](){ printf("Hello from lambada %d",this->x);};

问题在于:

[this](){ printf("Hello from lambda %d",this->x);};

没有给我一个指向 class A 的成员函数的指针。它给了我一个指向普通函数的指针。我如何在 lambda 内部声明这是 A 的成员函数。

或者如果这样的事情在 cpp 中是不可能的。你建议我如何在不使用虚函数的情况下从 SomeFunction 指向的函数访问 class A 的变量 x(这种代码将 运行 每秒大约 700 次)。

编辑:

明确地说,我确实关心性能。但我需要这个的主要原因是特定的设计问题而不是性能。 我知道这在 cpp 中可能是不可能的。 欢迎提出解决方法建议。

由于多种原因,这是不可能的。

首先,指向成员函数的指针与指向独立函数的指针在类型上不同,非捕获 lambda 只能转换为指向独立函数的指针。

其次,你的 lambda 正在捕获,因此,它根本无法转换为指向函数的指针,只能保留为未指定类型的函子。

但是,您不应该考虑太多,只需将 lambda 存储在 std::function 中即可。当然,您将以虚拟分派和与之相关的一些性能下降结束,但每秒 700 次算不了什么,而且由于虚拟分派,您永远不会检测到命中。

无法在 class 定义后添加额外的方法。因此,由于您的 class A 中没有方法,因此不可能将 A::SomeFunction 设置为指向 A 的任何非静态方法。作为解决方法,您可以

void (*SomeFunction)(A*);

A a {};  // note {} instead of ()
a.SomeFunction = [](A* a){ /* do something with a->x */ };

来自评论:

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.

您想要同一个 class 的不同行为而不需要任何间接访问?你必须放弃一个。

但您也不必为每个系统都编写 class。您可以将 class 设为模板,这样编译器就可以 为每个系统生成 一个 class:

template<typename T>
struct A : private T {
    A(T function) noexcept : T{std::move(function)} {}

    void SomeFunction() {
        (*this)(this);
    }

    int x = 0;
};

然后可以这样使用:

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!

好吧,为未来的人跟进这里有一个解决方法,可以让它看起来更好一些。

我创建了一个模板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;
    }
}; 

在class中的用法:

class A {
public:
int someMember; 
MemberLambda<A, void, int, int> func = 
MemberLambda<A, void, int, int>(this, nullptr);
};

*注意在示例中我将 lambda 设置为 nullptr 但它可以设置为 lambda 表达式。

在示例中,lambda 是 A 的成员,需要两个 int 和 returns void

用户使用情况:

A a;
a.someMember = 3;
a.func = [](A* self, int a, int b){ std::cout << self->someMember + a + b; };
a.func(5,6);

会输出14,也就是3 + 5 + 6。