簡體   English   中英

用於分配成員函數指針的 lambda 表達式

[英]lambda expression to assign a member function pointer

我需要一個 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 中可能是不可能的。 歡迎提出解決方法的建議。

出於多種原因,這是不可能的。

首先,指向成員函數的指針與指向獨立函數的指針在類型上不同,非捕獲性 lambda 只能轉換為指向獨立函數的指針。

其次,您的 lambda 正在捕獲,因此,它根本無法轉換為指向函數的指針,並且只能保留為未指定類型的函子。

但是,您不應該考慮太多,只需將 lambda 存儲在std::function 誠然,您將以虛擬分派和與之相關的一些性能下降結束,但每秒 700 次算不了什么,而且您永遠不會因為虛擬分派而檢測到命中。

在定義之后,不可能向類添加額外的方法。 因此,由於在你的類中沒有方法A ,它不可能永遠集A::SomeFunction以點的任何非靜態方法A 作為一種解決方法,你可以

void (*SomeFunction)(A*);

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

來自評論:

這是 ECS 實施的一部分。 我只是不願意為 etch 系統創建一個新類,我想讓用戶選擇在場景構造函數中聲明系統或從系統類繼承。

你想要同一個類的不同行為而沒有任何間接性? 你必須放棄一個。

但是您也不必為每個系統編寫一個類。 您可以將該類設為模板,以便編譯器可以為每個系統生成一個類:

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!

很好地跟進未來的人,這里有一個解決方法,可以讓它看起來更好。

我創建了一個模板類

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 A {
public:
int someMember; 
MemberLambda<A, void, int, int> func = 
MemberLambda<A, void, int, int>(this, nullptr);
};

*注意在示例中我將 lambda 設置為nullptr但它可以設置為 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,6);

將輸出 14,即 3 + 5 + 6。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM