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

时间:2019-02-19 18:57:48

标签: c++ function polymorphism member

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

例如,我有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);};

没有给我指向类A成员函数的指针。它给了我指向普通函数的指针。我如何在lambda中声明这是A的成员函数。

或者,如果在cpp中不可能发生这种情况。您如何建议我不使用虚函数就从SomeFunction指向的函数访问类A的变量x(这种代码每秒将运行700次)。

编辑:

为了明确起见,我确实关心性能。但是我需要这样做的主要原因是特定的设计问题而不是性能。 我了解这可能无法在cpp中完成。 解决方法建议将受到欢迎。

4 个答案:

答案 0 :(得分:4)

由于某些原因,这是不可能的。

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

第二,您的lambda正在捕获,因此,它根本不能转换为函数指针,只能保留未指定类型的函子。

但是,您不应该考虑太多,而只是将一个lambda存储在std::function中。当然,您将以虚拟调度和与之相关的性能下降而告终,但是每秒700次是没有的,并且您永远都不会因为虚拟调度而检测到任何攻击。

答案 1 :(得分:3)

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

void (*SomeFunction)(A*);

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

答案 2 :(得分:0)

从评论中:

  

这是ECS实施的一部分。而且我根本不愿意为蚀刻系统创建新的类,我希望为用户提供在场景构造函数中声明系统或从系统类继承的选项。

您想要没有任何间接作用的同一个类不同的行为?您必须放弃一个。

但是您也不必为每个系统编写一个类。您可以将类作为模板,以便编译器可以为每个系统生成一个类:

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!

答案 3 :(得分:0)

很好地跟进未来的人,这是一个令人愉快的答案。设计花了我一段时间。我不知道它是否完美,但对我来说看起来不错;

我们要做的第一件事是创建一个结构“ MemberLambda”,我们将使用参数包功能,该功能对于我们所需的功能绝对是完美的:

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;
    }
}; 

现在我们可以使用它了。

课堂用法

这是一个名为A的示例类:

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

**在上面的示例中,我们将lambda设置为nullptr,但您可以将lambda设置为lambda表达式。

我决定将lambda作为“ A”的成员,并接受两个int并返回void。根据需要进行更改。

用户使用情况

对于用户来说,它很容易使用,例如:

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

将输出13,即3 + 5 + 5。

效果很好。